vendor/assets/javascripts/angular-scenario.js in angularjs-rails-1.0.2 vs vendor/assets/javascripts/angular-scenario.js in angularjs-rails-1.0.3
- old
+ new
@@ -9402,11 +9402,11 @@
})( window );
/**
- * @license AngularJS v1.0.2
+ * @license AngularJS v1.0.3
* (c) 2010-2012 Google, Inc. http://angularjs.org
* License: MIT
*/
(function(window, document){
var _jQuery = window.jQuery.noConflict(true);
@@ -10197,11 +10197,11 @@
return parts.length ? parts.join('&') : '';
}
/**
- * We need our custom mehtod because encodeURIComponent is too agressive and doesn't follow
+ * We need our custom method because encodeURIComponent is too agressive and doesn't follow
* http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path
* segments:
* segment = *pchar
* pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
* pct-encoded = "%" HEXDIG HEXDIG
@@ -10241,11 +10241,11 @@
/**
* @ngdoc directive
* @name ng.directive:ngApp
*
* @element ANY
- * @param {angular.Module} ngApp on optional application
+ * @param {angular.Module} ngApp an optional application
* {@link angular.module module} name to load.
*
* @description
*
* Use this directive to auto-bootstrap on application. Only
@@ -10418,11 +10418,11 @@
* registered using this mechanism.
*
*
* # Module
*
- * A module is a collocation of services, directives, filters, and configure information. Module
+ * A module is a collocation of services, directives, filters, and configuration information. Module
* is used to configure the {@link AUTO.$injector $injector}.
*
* <pre>
* // Create a new module
* var myModule = angular.module('myModule', []);
@@ -10448,11 +10448,11 @@
* {@link angular.bootstrap} to simplify this process for you.
*
* @param {!string} name The name of the module to create or retrieve.
* @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the
* the module is being retrieved for further configuration.
- * @param {Function} configFn Option configuration function for the module. Same as
+ * @param {Function} configFn Optional configuration function for the module. Same as
* {@link angular.Module#config Module#config()}.
* @returns {module} new module with the {@link angular.Module} api.
*/
return function module(name, requires, configFn) {
if (requires && modules.hasOwnProperty(name)) {
@@ -10603,12 +10603,12 @@
* @name angular.Module#run
* @methodOf angular.Module
* @param {Function} initializationFn Execute this function after injector creation.
* Useful for application initialization.
* @description
- * Use this method to register work which needs to be performed when the injector with
- * with the current module is finished loading.
+ * Use this method to register work which should be performed when the injector is done
+ * loading all modules.
*/
run: function(block) {
runBlocks.push(block);
return this;
}
@@ -10650,15 +10650,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.0.2', // all of these placeholder strings will be replaced by rake's
+ full: '1.0.3', // all of these placeholder strings will be replaced by rake's
major: 1, // compile task
minor: 0,
- dot: 2,
- codeName: 'debilitating-awesomeness'
+ dot: 3,
+ codeName: 'bouncy-thunder'
};
function publishExternalAPI(angular){
extend(angular, {
@@ -10821,10 +10821,11 @@
* - [removeClass()](http://api.jquery.com/removeClass/)
* - [removeData()](http://api.jquery.com/removeData/)
* - [replaceWith()](http://api.jquery.com/replaceWith/)
* - [text()](http://api.jquery.com/text/)
* - [toggleClass()](http://api.jquery.com/toggleClass/)
+ * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.
* - [unbind()](http://api.jquery.com/unbind/)
* - [val()](http://api.jquery.com/val/)
* - [wrap()](http://api.jquery.com/wrap/)
*
* ## In addtion to the above, Angular privides an additional method to both jQuery and jQuery lite:
@@ -10896,16 +10897,11 @@
while(list.length) {
set = list.shift();
for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {
element = jqLite(set[setIndex]);
if (fireEvent) {
- events = element.data('events');
- if ( (fns = events && events.$destroy) ) {
- forEach(fns, function(fn){
- fn.handler();
- });
- }
+ element.triggerHandler('$destroy');
} else {
fireEvent = !fireEvent;
}
for(childIndex = 0, childLength = (children = element.children()).length;
childIndex < childLength;
@@ -11033,25 +11029,25 @@
function JQLiteHasClass(element, selector) {
return ((" " + element.className + " ").replace(/[\n\t]/g, " ").
indexOf( " " + selector + " " ) > -1);
}
-function JQLiteRemoveClass(element, selector) {
- if (selector) {
- forEach(selector.split(' '), function(cssClass) {
+function JQLiteRemoveClass(element, cssClasses) {
+ if (cssClasses) {
+ forEach(cssClasses.split(' '), function(cssClass) {
element.className = trim(
(" " + element.className + " ")
.replace(/[\n\t]/g, " ")
.replace(" " + trim(cssClass) + " ", " ")
);
});
}
}
-function JQLiteAddClass(element, selector) {
- if (selector) {
- forEach(selector.split(' '), function(cssClass) {
+function JQLiteAddClass(element, cssClasses) {
+ if (cssClasses) {
+ forEach(cssClasses.split(' '), function(cssClass) {
if (!JQLiteHasClass(element, cssClass)) {
element.className = trim(element.className + ' ' + trim(cssClass));
}
});
}
@@ -11495,11 +11491,19 @@
find: function(element, selector) {
return element.getElementsByTagName(selector);
},
- clone: JQLiteClone
+ clone: JQLiteClone,
+
+ triggerHandler: function(element, eventName) {
+ var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];
+
+ forEach(eventFns, function(fn) {
+ fn.call(element, null);
+ });
+ }
}, function(fn, name){
/**
* chaining functions
*/
JQLite.prototype[name] = function(arg1, arg2) {
@@ -11613,10 +11617,20 @@
return array[0];
} else {
return array.shift();
}
}
+ },
+
+ /**
+ * return the first item without deleting it
+ */
+ peek: function(key) {
+ var array = this[hashKey(key)];
+ if (array) {
+ return array[0];
+ }
}
};
/**
* @ngdoc function
@@ -11636,11 +11650,11 @@
* Typical usage
* <pre>
* // create an injector
* var $injector = angular.injector(['ng']);
*
- * // use the injector to kick of your application
+ * // use the injector to kick off your application
* // use the type inference to auto inject arguments, or use implicit injection
* $injector.invoke(function($rootScope, $compile, $document){
* $compile($document)($rootScope);
* $rootScope.$digest();
* });
@@ -11656,11 +11670,11 @@
* Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.
*/
var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
var FN_ARG_SPLIT = /,/;
-var FN_ARG = /^\s*(_?)(.+?)\1\s*$/;
+var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
function annotate(fn) {
var $inject,
fnText,
argDecl,
@@ -12275,13 +12289,14 @@
}
// does not scroll when user clicks on anchor link that is currently on
// (no url change, no $locaiton.hash() change), browser native does scroll
if (autoScrollingEnabled) {
- $rootScope.$watch(function() {return $location.hash();}, function() {
- $rootScope.$evalAsync(scroll);
- });
+ $rootScope.$watch(function autoScrollWatch() {return $location.hash();},
+ function autoScrollWatchAction() {
+ $rootScope.$evalAsync(scroll);
+ });
}
return scroll;
}];
}
@@ -12661,14 +12676,14 @@
*
* @returns {object} Newly created cache object with the following set of methods:
*
* - `{object}` `info()` — Returns id, size, and options of cache.
* - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.
- * - `{{*}} `get({string} key) — Returns cached value for `key` or undefined for cache miss.
- * - `{void}` `remove({string} key) — Removes a key-value pair from the cache.
- * - `{void}` `removeAll() — Removes all cached values.
- * - `{void}` `destroy() — Removes references to this cache from $cacheFactory.
+ * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.
+ * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.
+ * - `{void}` `removeAll()` — Removes all cached values.
+ * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.
*
*/
function $CacheFactoryProvider() {
this.$get = function() {
@@ -12716,10 +12731,12 @@
remove: function(key) {
var lruEntry = lruHash[key];
+ if (!lruEntry) return;
+
if (lruEntry == freshEnd) freshEnd = lruEntry.p;
if (lruEntry == staleEnd) staleEnd = lruEntry.n;
link(lruEntry.n,lruEntry.p);
delete lruHash[key];
@@ -13123,30 +13140,30 @@
return compile;
//================================
- function compile($compileNode, transcludeFn, maxPriority) {
- if (!($compileNode instanceof jqLite)) {
+ function compile($compileNodes, transcludeFn, maxPriority) {
+ if (!($compileNodes instanceof jqLite)) {
// jquery always rewraps, where as we need to preserve the original selector so that we can modify it.
- $compileNode = jqLite($compileNode);
+ $compileNodes = jqLite($compileNodes);
}
// We can not compile top level text elements since text nodes can be merged and we will
// not be able to attach scope data to them, so we will wrap them in <span>
- forEach($compileNode, function(node, index){
+ forEach($compileNodes, function(node, index){
if (node.nodeType == 3 /* text node */) {
- $compileNode[index] = jqLite(node).wrap('<span></span>').parent()[0];
+ $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];
}
});
- var compositeLinkFn = compileNodes($compileNode, transcludeFn, $compileNode, maxPriority);
- return function(scope, cloneConnectFn){
+ var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority);
+ return function publicLinkFn(scope, cloneConnectFn){
assertArg(scope, 'scope');
// important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart
// and sometimes changes the structure of the DOM.
var $linkNode = cloneConnectFn
- ? JQLitePrototype.clone.call($compileNode) // IMPORTANT!!!
- : $compileNode;
+ ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!
+ : $compileNodes;
$linkNode.data('$scope', scope);
safeAddClass($linkNode, 'ng-scope');
if (cloneConnectFn) cloneConnectFn($linkNode, scope);
if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);
return $linkNode;
@@ -13193,11 +13210,11 @@
nodeLinkFn = (directives.length)
? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)
: null;
- childLinkFn = (nodeLinkFn && nodeLinkFn.terminal)
+ childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)
? null
: compileNodes(nodeList[i].childNodes,
nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);
linkFns.push(nodeLinkFn);
@@ -13245,17 +13262,18 @@
}
}
/**
- * Looks for directives on the given node ands them to the directive collection which is sorted.
+ * Looks for directives on the given node and adds them to the directive collection which is
+ * sorted.
*
- * @param node node to search
- * @param directives an array to which the directives are added to. This array is sorted before
+ * @param node Node to search.
+ * @param directives An array to which the directives are added to. This array is sorted before
* the function returns.
- * @param attrs the shared attrs object which is used to populate the normalized attributes.
- * @param {number=} max directive priority
+ * @param attrs The shared attrs object which is used to populate the normalized attributes.
+ * @param {number=} maxPriority Max directive priority.
*/
function collectDirectives(node, directives, attrs, maxPriority) {
var nodeType = node.nodeType,
attrsMap = attrs.$attr,
match,
@@ -13286,11 +13304,11 @@
}
}
// use class as directive
className = node.className;
- if (isString(className)) {
+ if (isString(className) && className !== '') {
while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {
nName = directiveNormalize(match[2]);
if (addDirective(directives, nName, 'C', maxPriority)) {
attrs[nName] = trim(match[3]);
}
@@ -13340,11 +13358,11 @@
function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, $rootElement) {
var terminalPriority = -Number.MAX_VALUE,
preLinkFns = [],
postLinkFns = [],
newScopeDirective = null,
- newIsolatedScopeDirective = null,
+ newIsolateScopeDirective = null,
templateDirective = null,
$compileNode = templateAttrs.$$element = jqLite(compileNode),
directive,
directiveName,
$template,
@@ -13362,14 +13380,14 @@
if (terminalPriority > directive.priority) {
break; // prevent further processing of directives
}
if (directiveValue = directive.scope) {
- assertNoDuplicate('isolated scope', newIsolatedScopeDirective, directive, $compileNode);
+ assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);
if (isObject(directiveValue)) {
safeAddClass($compileNode, 'ng-isolate-scope');
- newIsolatedScopeDirective = directive;
+ newIsolateScopeDirective = directive;
}
safeAddClass($compileNode, 'ng-scope');
newScopeDirective = newScopeDirective || directive;
}
@@ -13519,16 +13537,16 @@
} else {
attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));
}
$element = attrs.$$element;
- if (newScopeDirective && isObject(newScopeDirective.scope)) {
+ if (newIsolateScopeDirective) {
var LOCAL_REGEXP = /^\s*([@=&])\s*(\w*)\s*$/;
var parentScope = scope.$parent || scope;
- forEach(newScopeDirective.scope, function(definiton, scopeName) {
+ forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) {
var match = definiton.match(LOCAL_REGEXP) || [],
attrName = match[2]|| scopeName,
mode = match[1], // @, =, or &
lastValue,
parentGet, parentSet;
@@ -13547,24 +13565,24 @@
parentGet = $parse(attrs[attrName]);
parentSet = parentGet.assign || function() {
// reset the change, or we will throw this exception on every $digest
lastValue = scope[scopeName] = parentGet(parentScope);
throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] +
- ' (directive: ' + newScopeDirective.name + ')');
+ ' (directive: ' + newIsolateScopeDirective.name + ')');
};
lastValue = scope[scopeName] = parentGet(parentScope);
- scope.$watch(function() {
+ scope.$watch(function parentValueWatch() {
var parentValue = parentGet(parentScope);
if (parentValue !== scope[scopeName]) {
// we are out of sync and need to copy
if (parentValue !== lastValue) {
// parent changed and it has precedence
lastValue = scope[scopeName] = parentValue;
} else {
// if the parent can be assigned then do so
- parentSet(parentScope, lastValue = scope[scopeName]);
+ parentSet(parentScope, parentValue = lastValue = scope[scopeName]);
}
}
return parentValue;
});
break;
@@ -13578,11 +13596,11 @@
break;
}
default: {
throw Error('Invalid isolate scope definition for directive ' +
- newScopeDirective.name + ': ' + definiton);
+ newIsolateScopeDirective.name + ': ' + definiton);
}
}
});
}
@@ -13712,11 +13730,11 @@
afterTemplateChildLinkFn,
beforeTemplateCompileNode = $compileNode[0],
origAsyncDirective = directives.shift(),
// The fact that we have to copy and patch the directive seems wrong!
derivedSyncDirective = extend({}, origAsyncDirective, {
- controller: null, templateUrl: null, transclude: null
+ controller: null, templateUrl: null, transclude: null, scope: null
});
$compileNode.html('');
$http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).
@@ -13804,16 +13822,16 @@
function addTextInterpolateDirective(directives, text) {
var interpolateFn = $interpolate(text, true);
if (interpolateFn) {
directives.push({
priority: 0,
- compile: valueFn(function(scope, node) {
+ compile: valueFn(function textInterpolateLinkFn(scope, node) {
var parent = node.parent(),
bindings = parent.data('$binding') || [];
bindings.push(interpolateFn);
safeAddClass(parent.data('$binding', bindings), 'ng-binding');
- scope.$watch(interpolateFn, function(value) {
+ scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {
node[0].nodeValue = value;
});
})
});
}
@@ -13827,11 +13845,11 @@
// no interpolation found -> ignore
if (!interpolateFn) return;
directives.push({
priority: 100,
- compile: valueFn(function(scope, element, attr) {
+ compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {
var $$observers = (attr.$$observers || (attr.$$observers = {}));
if (name === 'class') {
// we need to interpolate classes again, in the case the element was replaced
// and therefore the two class attrs got merged - we want to interpolate the result
@@ -13839,11 +13857,11 @@
}
attr[name] = undefined;
($$observers[name] || ($$observers[name] = [])).$$inter = true;
(attr.$$observers && attr.$$observers[name].$$scope || scope).
- $watch(interpolateFn, function(value) {
+ $watch(interpolateFn, function interpolateFnWatchAction(value) {
attr.$set(name, value);
});
})
});
}
@@ -14837,24 +14855,25 @@
// update browser
var changeCounter = 0;
$rootScope.$watch(function $locationWatch() {
var oldUrl = $browser.url();
+ var currentReplace = $location.$$replace;
if (!changeCounter || oldUrl != $location.absUrl()) {
changeCounter++;
$rootScope.$evalAsync(function() {
if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).
defaultPrevented) {
$location.$$parse(oldUrl);
} else {
- $browser.url($location.absUrl(), $location.$$replace);
- $location.$$replace = false;
+ $browser.url($location.absUrl(), currentReplace);
afterLocationChange(oldUrl);
}
});
}
+ $location.$$replace = false;
return changeCounter;
});
return $location;
@@ -14981,11 +15000,19 @@
var OPERATORS = {
'null':function(){return null;},
'true':function(){return true;},
'false':function(){return false;},
undefined:noop,
- '+':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)+(isDefined(b)?b:0);},
+ '+':function(self, locals, a,b){
+ a=a(self, locals); b=b(self, locals);
+ if (isDefined(a)) {
+ if (isDefined(b)) {
+ return a + b;
+ }
+ return a;
+ }
+ return isDefined(b)?b:undefined;},
'-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);},
'*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},
'/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},
'%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},
'^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},
@@ -15876,11 +15903,11 @@
* var promise = asyncGreet('Robin Hood');
* promise.then(function(greeting) {
* alert('Success: ' + greeting);
* }, function(reason) {
* alert('Failed: ' + reason);
- * );
+ * });
* </pre>
*
* At first it might not be obvious why this extra complexity is worth the trouble. The payoff
* comes in the way of
* [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).
@@ -16251,22 +16278,22 @@
* match.
*
* Object properties:
*
* - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly
- * created scope or the name of a {@link angular.Module#controller registered controller}
+ * created scope or the name of a {@link angular.Module#controller registered controller}
* if passed as a string.
* - `template` – `{string=}` – html template as a string that should be used by
* {@link ng.directive:ngView ngView} or
* {@link ng.directive:ngInclude ngInclude} directives.
* this property takes precedence over `templateUrl`.
* - `templateUrl` – `{string=}` – path to an html template that should be used by
* {@link ng.directive:ngView ngView}.
* - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should
* be injected into the controller. If any of these dependencies are promises, they will be
* resolved and converted to a value before the controller is instantiated and the
- * `$afterRouteChange` event is fired. The map object is:
+ * `$routeChangeSuccess` event is fired. The map object is:
*
* - `key` – `{string}`: a name of a dependency to be injected into the controller.
* - `factory` - `{string|function}`: If `string` then it is an alias for a service.
* Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected}
* and the return value is treated as the dependency. If the result is a promise, it is resolved
@@ -16596,11 +16623,11 @@
values = [],
template;
forEach(next.resolve || {}, function(value, key) {
keys.push(key);
- values.push(isFunction(value) ? $injector.invoke(value) : $injector.get(value));
+ values.push(isString(value) ? $injector.get(value) : $injector.invoke(value));
});
if (isDefined(template = next.template)) {
} else if (isDefined(template = next.templateUrl)) {
template = $http.get(template, {cache: $templateCache}).
then(function(response) { return response.data; });
@@ -16867,13 +16894,13 @@
*
* {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for
* the scope and its child scopes to be permanently detached from the parent and thus stop
* participating in model change detection and listener notification by invoking.
*
- * @param {boolean} isolate if true then the scoped does not prototypically inherit from the
- * parent scope. The scope is isolated, as it can not se parent scope properties.
- * When creating widgets it is useful for the widget to not accidently read parent
+ * @param {boolean} isolate if true then the scope does not prototypically inherit from the
+ * parent scope. The scope is isolated, as it can not see parent scope properties.
+ * When creating widgets it is useful for the widget to not accidentally read parent
* state.
*
* @returns {Object} The newly created child scope.
*
*/
@@ -16923,22 +16950,22 @@
* - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and
* should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()}
* reruns when it detects changes the `watchExpression` can execute multiple times per
* {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)
* - The `listener` is called only when the value from the current `watchExpression` and the
- * previous call to `watchExpression' are not equal (with the exception of the initial run
+ * previous call to `watchExpression` are not equal (with the exception of the initial run,
* see below). The inequality is determined according to
- * {@link angular.equals} function. To save the value of the object for later comparison
+ * {@link angular.equals} function. To save the value of the object for later comparison, the
* {@link angular.copy} function is used. It also means that watching complex options will
* have adverse memory and performance implications.
* - The watch `listener` may change the model, which may trigger other `listener`s to fire. This
* is achieved by rerunning the watchers until no changes are detected. The rerun iteration
- * limit is 100 to prevent infinity loop deadlock.
+ * limit is 10 to prevent an infinite loop deadlock.
*
*
* If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,
- * you can register an `watchExpression` function with no `listener`. (Since `watchExpression`,
+ * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`
* can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is
* detected, be prepared for multiple calls to your listener.)
*
* After a watcher is registered with the scope, the `listener` fn is called asynchronously
* (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the
@@ -16980,11 +17007,11 @@
* the `watchExpression` changes.
*
* - `string`: Evaluated as {@link guide/expression expression}
* - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.
*
- * @param {boolean=} objectEquality Compare object for equality rather then for refference.
+ * @param {boolean=} objectEquality Compare object for equality rather than for reference.
* @returns {function()} Returns a deregistration function for this listener.
*/
$watch: function(watchExp, listener, objectEquality) {
var scope = this,
get = compileToFn(watchExp, 'watch'),
@@ -17155,11 +17182,11 @@
* @name ng.$rootScope.Scope#$destroy
* @methodOf ng.$rootScope.Scope
* @function
*
* @description
- * Remove the current scope (and all of its children) from the parent scope. Removal implies
+ * Removes the current scope (and all of its children) from the parent scope. Removal implies
* that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer
* propagate to the current scope and its children. Removal also implies that the current
* scope is eligible for garbage collection.
*
* The `$destroy()` is usually used by directives such as
@@ -17178,21 +17205,26 @@
if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;
if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;
if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;
if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;
+
+ // This is bogus code that works around Chrome's GC leak
+ // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451
+ this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =
+ this.$$childTail = null;
},
/**
* @ngdoc function
* @name ng.$rootScope.Scope#$eval
* @methodOf ng.$rootScope.Scope
* @function
*
* @description
* Executes the `expression` on the current scope returning the result. Any exceptions in the
- * expression are propagated (uncaught). This is useful when evaluating engular expressions.
+ * expression are propagated (uncaught). This is useful when evaluating Angular expressions.
*
* # Example
* <pre>
var scope = ng.$rootScope.Scope();
scope.a = 1;
@@ -17309,37 +17341,37 @@
* @name ng.$rootScope.Scope#$on
* @methodOf ng.$rootScope.Scope
* @function
*
* @description
- * Listen on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of
+ * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of
* event life cycle.
*
* @param {string} name Event name to listen on.
* @param {function(event)} listener Function to call when the event is emitted.
* @returns {function()} Returns a deregistration function for this listener.
*
* The event listener function format is: `function(event, args...)`. The `event` object
* passed into the listener has the following attributes:
*
- * - `targetScope` - {Scope}: the scope on which the event was `$emit`-ed or `$broadcast`-ed.
- * - `currentScope` - {Scope}: the current scope which is handling the event.
- * - `name` - {string}: Name of the event.
- * - `stopPropagation` - {function=}: calling `stopPropagation` function will cancel further event propagation
- * (available only for events that were `$emit`-ed).
- * - `preventDefault` - {function}: calling `preventDefault` sets `defaultPrevented` flag to true.
- * - `defaultPrevented` - {boolean}: true if `preventDefault` was called.
+ * - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed.
+ * - `currentScope` - `{Scope}`: the current scope which is handling the event.
+ * - `name` - `{string}`: Name of the event.
+ * - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event
+ * propagation (available only for events that were `$emit`-ed).
+ * - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.
+ * - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.
*/
$on: function(name, listener) {
var namedListeners = this.$$listeners[name];
if (!namedListeners) {
this.$$listeners[name] = namedListeners = [];
}
namedListeners.push(listener);
return function() {
- arrayRemove(namedListeners, listener);
+ namedListeners[indexOf(namedListeners, listener)] = null;
};
},
/**
@@ -17383,10 +17415,18 @@
do {
namedListeners = scope.$$listeners[name] || empty;
event.currentScope = scope;
for (i=0, length=namedListeners.length; i<length; i++) {
+
+ // if listeners were deregistered, defragment the array
+ if (!namedListeners[i]) {
+ namedListeners.splice(i, 1);
+ i--;
+ length--;
+ continue;
+ }
try {
namedListeners[i].apply(null, listenerArgs);
if (stopPropagation) return event;
} catch (e) {
$exceptionHandler(e);
@@ -17432,23 +17472,33 @@
preventDefault: function() {
event.defaultPrevented = true;
},
defaultPrevented: false
},
- listenerArgs = concat([event], arguments, 1);
+ listenerArgs = concat([event], arguments, 1),
+ listeners, i, length;
//down while you can, then up and next sibling or up and next sibling until back at root
do {
current = next;
event.currentScope = current;
- forEach(current.$$listeners[name], function(listener) {
+ listeners = current.$$listeners[name] || [];
+ for (i=0, length = listeners.length; i<length; i++) {
+ // if listeners were deregistered, defragment the array
+ if (!listeners[i]) {
+ listeners.splice(i, 1);
+ i--;
+ length--;
+ continue;
+ }
+
try {
- listener.apply(null, listenerArgs);
+ listeners[i].apply(null, listenerArgs);
} catch(e) {
$exceptionHandler(e);
}
- });
+ }
// Insanity Warning: scope depth-first traversal
// yes, this code is a bit crazy, but it works and we have tests to prove it!
// this piece should be kept in sync with the traversal in $digest
if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {
@@ -18552,11 +18602,11 @@
*
* @param {function()} fn A function, who's execution should be delayed.
* @param {number=} [delay=0] Delay in milliseconds.
* @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 that will be resolved when the timeout is reached. The value this
+ * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this
* promise will be resolved with is the return value of the `fn` function.
*/
function timeout(fn, delay, invokeApply) {
var deferred = $q.defer(),
promise = deferred.promise,
@@ -18991,13 +19041,22 @@
number = Math.abs(number);
var numStr = number + '',
formatedText = '',
parts = [];
+ var hasExponent = false;
if (numStr.indexOf('e') !== -1) {
- formatedText = numStr;
- } else {
+ var match = numStr.match(/([\d\.]+)e(-?)(\d+)/);
+ if (match && match[2] == '-' && match[3] > fractionSize + 1) {
+ numStr = '0';
+ } else {
+ formatedText = numStr;
+ hasExponent = true;
+ }
+ }
+
+ if (!hasExponent) {
var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;
// determine fractionSize if it is not specified
if (isUndefined(fractionSize)) {
fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);
@@ -19194,11 +19253,11 @@
*/
dateFilter.$inject = ['$locale'];
function dateFilter($locale) {
- var R_ISO8601_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d{3}))?)?)?(Z|([+-])(\d\d):?(\d\d)))?$/;
+ var R_ISO8601_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;
function jsonStringToDate(string){
var match;
if (match = string.match(R_ISO8601_STR)) {
var date = new Date(0),
tzHour = 0,
@@ -19573,10 +19632,11 @@
return function(scope, element) {
element.bind('click', function(event){
// if we have no href url, then don't navigate anywhere.
if (!element.attr('href')) {
event.preventDefault();
+ return false; // Needed for opera
}
});
}
}
});
@@ -19863,11 +19923,11 @@
ngAttributeAliasDirectives[normalized] = function() {
return {
priority: 100,
compile: function() {
return function(scope, element, attr) {
- scope.$watch(attr[normalized], function(value) {
+ scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {
attr.$set(attrName, !!value);
});
};
}
};
@@ -19881,10 +19941,13 @@
ngAttributeAliasDirectives[normalized] = function() {
return {
priority: 99, // it needs to run after the attributes are interpolated
link: function(scope, element, attr) {
attr.$observe(normalized, function(value) {
+ if (!value)
+ return;
+
attr.$set(attrName, value);
// on IE, if "ng:src" directive declaration is used and "src" attribute doesn't exist
// then calling element.setAttribute('src', 'foo') doesn't do anything, so we need
// to set the property as well to achieve the desired effect
@@ -20009,10 +20072,11 @@
form.$setDirty = function() {
element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);
form.$dirty = true;
form.$pristine = false;
+ parentForm.$setDirty();
};
}
@@ -20194,11 +20258,14 @@
* @description
* Standard HTML text input with angular data binding.
*
* @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=} required Sets `required` validation error key if the value is not entered.
+ * @param {string=} required Adds `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
* @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
* minlength.
* @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
* maxlength.
* @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
@@ -20264,10 +20331,13 @@
* @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=} min Sets the `min` validation error key if the value entered is less then `min`.
* @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.
* @param {string=} required Sets `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
* @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
* minlength.
* @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
* maxlength.
* @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
@@ -20330,10 +20400,13 @@
* valid URL.
*
* @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=} required Sets `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
* @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
* minlength.
* @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
* maxlength.
* @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
@@ -20395,10 +20468,13 @@
* address.
*
* @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=} required Sets `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
* @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
* minlength.
* @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
* maxlength.
* @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
@@ -20817,10 +20893,13 @@
* {@link ng.directive:input input element}.
*
* @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=} required Sets `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
* @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
* minlength.
* @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
* maxlength.
* @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
@@ -20841,10 +20920,11 @@
* and polyfills the HTML5 validation behavior for older browsers.
*
* @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=} required Sets `required` validation error key if the value is not entered.
+ * @param {boolean=} ngRequired Sets `required` attribute if set to true
* @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
* minlength.
* @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
* maxlength.
* @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
@@ -21174,26 +21254,29 @@
}
};
// model -> value
var ctrl = this;
- $scope.$watch(ngModelGet, function(value) {
- // ignore change from view
- if (ctrl.$modelValue === value) return;
+ $scope.$watch(function ngModelWatch() {
+ var value = ngModelGet($scope);
- var formatters = ctrl.$formatters,
- idx = formatters.length;
+ // if scope model value and ngModel value are out of sync
+ if (ctrl.$modelValue !== value) {
- ctrl.$modelValue = value;
- while(idx--) {
- value = formatters[idx](value);
- }
+ var formatters = ctrl.$formatters,
+ idx = formatters.length;
- if (ctrl.$viewValue !== value) {
- ctrl.$viewValue = value;
- ctrl.$render();
+ ctrl.$modelValue = value;
+ while(idx--) {
+ value = formatters[idx](value);
+ }
+
+ if (ctrl.$viewValue !== value) {
+ ctrl.$viewValue = value;
+ ctrl.$render();
+ }
}
});
}];
@@ -21338,11 +21421,11 @@
/**
* @ngdoc directive
* @name ng.directive:ngList
*
* @description
- * Text input that converts between comma-seperated string into an array of strings.
+ * Text input that converts between comma-separated string into an array of strings.
*
* @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.
*
@@ -21421,11 +21504,11 @@
return function(scope, elm, attr) {
attr.$set('value', scope.$eval(attr.ngValue));
};
} else {
return function(scope, elm, attr) {
- scope.$watch(attr.ngValue, function(value) {
+ scope.$watch(attr.ngValue, function valueWatchAction(value) {
attr.$set('value', value, false);
});
};
}
}
@@ -21479,11 +21562,11 @@
</doc:scenario>
</doc:example>
*/
var ngBindDirective = ngDirective(function(scope, element, attr) {
element.addClass('ng-binding').data('$binding', attr.ngBind);
- scope.$watch(attr.ngBind, function(value) {
+ scope.$watch(attr.ngBind, function ngBindWatchAction(value) {
element.text(value == undefined ? '' : value);
});
});
@@ -21562,30 +21645,68 @@
* @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.
*/
var ngBindHtmlUnsafeDirective = [function() {
return function(scope, element, attr) {
element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);
- scope.$watch(attr.ngBindHtmlUnsafe, function(value) {
+ scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {
element.html(value || '');
});
};
}];
function classDirective(name, selector) {
name = 'ngClass' + name;
return ngDirective(function(scope, element, attr) {
- scope.$watch(attr[name], function(newVal, oldVal) {
+
+ scope.$watch(attr[name], ngClassWatchAction, true);
+
+ attr.$observe('class', function(value) {
+ var ngClass = scope.$eval(attr[name]);
+ ngClassWatchAction(ngClass, ngClass);
+ });
+
+
+ if (name !== 'ngClass') {
+ scope.$watch('$index', function($index, old$index) {
+ var mod = $index % 2;
+ if (mod !== old$index % 2) {
+ if (mod == selector) {
+ addClass(scope.$eval(attr[name]));
+ } else {
+ removeClass(scope.$eval(attr[name]));
+ }
+ }
+ });
+ }
+
+
+ function ngClassWatchAction(newVal, oldVal) {
if (selector === true || scope.$index % 2 === selector) {
if (oldVal && (newVal !== oldVal)) {
- if (isObject(oldVal) && !isArray(oldVal))
- oldVal = map(oldVal, function(v, k) { if (v) return k });
- element.removeClass(isArray(oldVal) ? oldVal.join(' ') : oldVal);
- }
- if (isObject(newVal) && !isArray(newVal))
- newVal = map(newVal, function(v, k) { if (v) return k });
- if (newVal) element.addClass(isArray(newVal) ? newVal.join(' ') : newVal); }
- }, true);
+ removeClass(oldVal);
+ }
+ addClass(newVal);
+ }
+ }
+
+
+ function removeClass(classVal) {
+ if (isObject(classVal) && !isArray(classVal)) {
+ classVal = map(classVal, function(v, k) { if (v) return k });
+ }
+ element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal);
+ }
+
+
+ function addClass(classVal) {
+ if (isObject(classVal) && !isArray(classVal)) {
+ classVal = map(classVal, function(v, k) { if (v) return k });
+ }
+ if (classVal) {
+ element.addClass(isArray(classVal) ? classVal.join(' ') : classVal);
+ }
+ }
});
}
/**
* @ngdoc directive
@@ -22240,11 +22361,11 @@
}
element.html('');
};
- scope.$watch(srcExp, function(src) {
+ scope.$watch(srcExp, function ngIncludeWatchAction(src) {
var thisChangeId = ++changeCounter;
if (src) {
$http.get(src, {cache: $templateCache}).success(function(response) {
if (thisChangeId !== changeCounter) return;
@@ -22525,22 +22646,22 @@
whensExpFns[key] =
$interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +
offset + endSymbol));
});
- scope.$watch(function() {
+ scope.$watch(function ngPluralizeWatch() {
var value = parseFloat(scope.$eval(numberExp));
if (!isNaN(value)) {
//if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,
//check it against pluralization rules in $locale service
if (!whens[value]) value = $locale.pluralCat(value - offset);
return whensExpFns[value](scope, element, true);
} else {
return '';
}
- }, function(newVal) {
+ }, function ngPluralizeWatchAction(newVal) {
element.text(newVal);
});
}
};
}];
@@ -22631,11 +22752,12 @@
// - element: previous element.
// - index: position
// We need an array of these objects since the same object can be returned from the iterator.
// We expect this to be a rare case.
var lastOrder = new HashQueueMap();
- scope.$watch(function(scope){
+
+ scope.$watch(function ngRepeatWatch(scope){
var index, length,
collection = scope.$eval(rhs),
collectionLength = size(collection, true),
childScope,
// Same as lastOrder but it has the current state. It will become the
@@ -22660,11 +22782,13 @@
// we are not using forEach for perf reasons (trying to avoid #call)
for (index = 0, length = array.length; index < length; index++) {
key = (collection === array) ? index : array[index];
value = collection[key];
+
last = lastOrder.shift(value);
+
if (last) {
// if we have already seen this object, then we need to reuse the
// associated scope/element
childScope = last.scope;
nextOrder.push(value, last);
@@ -22757,26 +22881,26 @@
</doc:scenario>
</doc:example>
*/
//TODO(misko): refactor to remove element from the DOM
var ngShowDirective = ngDirective(function(scope, element, attr){
- scope.$watch(attr.ngShow, function(value){
+ scope.$watch(attr.ngShow, function ngShowWatchAction(value){
element.css('display', toBoolean(value) ? '' : 'none');
});
});
/**
* @ngdoc directive
* @name ng.directive:ngHide
*
* @description
- * The `ngHide` and `ngShow` directives hide or show a portion
- * of the HTML conditionally.
+ * The `ngHide` and `ngShow` directives hide or show a portion of the DOM tree (HTML)
+ * conditionally.
*
* @element ANY
- * @param {expression} ngHide If the {@link guide/expression expression} truthy then
+ * @param {expression} ngHide If the {@link guide/expression expression} is truthy then
* the element is shown or hidden respectively.
*
* @example
<doc:example>
<doc:source>
@@ -22797,11 +22921,11 @@
</doc:scenario>
</doc:example>
*/
//TODO(misko): refactor to remove element from the DOM
var ngHideDirective = ngDirective(function(scope, element, attr){
- scope.$watch(attr.ngHide, function(value){
+ scope.$watch(attr.ngHide, function ngHideWatchAction(value){
element.css('display', toBoolean(value) ? 'none' : '');
});
});
/**
@@ -22840,11 +22964,11 @@
});
</file>
</example>
*/
var ngStyleDirective = ngDirective(function(scope, element, attr) {
- scope.$watch(attr.ngStyle, function(newStyles, oldStyles) {
+ scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {
if (oldStyles && (newStyles !== oldStyles)) {
forEach(oldStyles, function(val, style) { element.css(style, '');});
}
if (newStyles) element.css(newStyles);
}, true);
@@ -22920,11 +23044,11 @@
return function(scope, element){
var selectedTransclude,
selectedElement,
selectedScope;
- scope.$watch(watchExpr, function(value) {
+ scope.$watch(watchExpr, function ngSwitchWatchAction(value) {
if (selectedElement) {
selectedScope.$destroy();
selectedElement.remove();
selectedElement = selectedScope = null;
}
@@ -23254,10 +23378,13 @@
* `select` model to be bound to a non-string value. This is because an option element can currently
* be bound to string values only.
*
* @param {string} name assignable expression to data-bind to.
* @param {string=} required The control is considered valid only if value is entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
* @param {comprehension_expression=} ngOptions in one of the following forms:
*
* * for array data sources:
* * `label` **`for`** `value` **`in`** `array`
* * `select` **`as`** `label` **`for`** `value` **`in`** `array`
@@ -23494,11 +23621,11 @@
});
};
// we have to do it on each watch since ngModel watches reference, but
// we need to work of an array, so we need to see if anything was inserted/removed
- scope.$watch(function() {
+ scope.$watch(function selectMultipleWatch() {
if (!equals(lastView, ctrl.$viewValue)) {
lastView = copy(ctrl.$viewValue);
ctrl.$render();
}
});
@@ -23611,11 +23738,12 @@
groupIndex, index,
locals = {},
selected,
selectedSet = false, // nothing is selected yet
lastElement,
- element;
+ element,
+ label;
if (multiple) {
selectedSet = new HashMap(modelValue);
} else if (modelValue === null || nullOption) {
// if we are not multiselect, and we are null then we have to add the nullOption
@@ -23635,13 +23763,15 @@
selected = selectedSet.remove(valueFn(scope, locals)) != undefined;
} else {
selected = modelValue === valueFn(scope, locals);
selectedSet = selectedSet || selected; // see if at least one item is selected
}
+ label = displayFn(scope, locals); // what will be seen by the user
+ label = label === undefined ? '' : label; // doing displayFn(scope, locals) || '' overwrites zero values
optionGroup.push({
id: keyName ? keys[index] : index, // either the index into array or key from object
- label: displayFn(scope, locals) || '', // what will be seen by the user
+ label: label,
selected: selected // determine if we should be selected
});
}
if (!multiple && !selectedSet) {
// nothing was selected, we have to insert the undefined item
@@ -23769,11 +23899,11 @@
} else {
selectCtrl = nullSelectCtrl;
}
if (interpolateFn) {
- scope.$watch(interpolateFn, function(newVal, oldVal) {
+ scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {
attr.$set('value', newVal);
if (newVal !== oldVal) selectCtrl.removeOption(oldVal);
selectCtrl.addOption(newVal);
});
} else {
@@ -24084,26 +24214,27 @@
var evnt = document.createEvent('MouseEvents'),
originalPreventDefault = evnt.preventDefault,
iframe = _jQuery('#application iframe')[0],
appWindow = iframe ? iframe.contentWindow : window,
fakeProcessDefault = true,
- finalProcessDefault;
+ finalProcessDefault,
+ angular = appWindow.angular || {};
// igor: temporary fix for https://bugzilla.mozilla.org/show_bug.cgi?id=684208
- appWindow.angular['ff-684208-preventDefault'] = false;
+ angular['ff-684208-preventDefault'] = false;
evnt.preventDefault = function() {
fakeProcessDefault = false;
return originalPreventDefault.apply(evnt, arguments);
};
evnt.initMouseEvent(type, true, true, window, 0, 0, 0, 0, 0, pressed('ctrl'), pressed('alt'),
pressed('shift'), pressed('meta'), 0, element);
element.dispatchEvent(evnt);
- finalProcessDefault = !(appWindow.angular['ff-684208-preventDefault'] || !fakeProcessDefault);
+ finalProcessDefault = !(angular['ff-684208-preventDefault'] || !fakeProcessDefault);
- delete appWindow.angular['ff-684208-preventDefault'];
+ delete angular['ff-684208-preventDefault'];
return finalProcessDefault;
}
}
@@ -24635,10 +24766,13 @@
// forward the event
self.emit('StepError', it, modelStep, error);
});
+ runner.on('RunnerBegin', function() {
+ self.emit('RunnerBegin');
+ });
runner.on('RunnerEnd', function() {
self.emit('RunnerEnd');
});
function complete(item) {
@@ -25274,10 +25408,12 @@
angular.forEach(args, function(value, index) {
selector = selector.replace('$' + (index + 1), value);
});
var result = $document.find(selector);
if (selector.match(NG)) {
- result = result.add(selector.replace(NG, '[ng-'), $document);
+ angular.forEach(['[ng-','[data-ng-','[x-ng-'], function(value, index){
+ result = result.add(selector.replace(NG, value), $document);
+ });
}
if (!result.length) {
throw {
type: 'selector',
message: 'Selector ' + selector + ' did not match any elements.'
\ No newline at end of file