From 238abd8b6924fa047645fca0e33cef0f9b655bc3 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Wed, 29 Jan 2014 08:43:30 -0600 Subject: [PATCH] Update to Angular v1.2.10 --- CHANGELOG.md | 3 + dist/js/angular/angular-animate.js | 172 +++++++++++++++---- dist/js/angular/angular-animate.min.js | 38 +++-- dist/js/angular/angular-animate.min.js.map | 6 +- dist/js/angular/angular-cookies.js | 2 +- dist/js/angular/angular-cookies.min.js | 2 +- dist/js/angular/angular-loader.js | 4 +- dist/js/angular/angular-loader.min.js | 4 +- dist/js/angular/angular-loader.min.js.map | 2 +- dist/js/angular/angular-mocks.js | 37 +++- dist/js/angular/angular-resource.js | 2 +- dist/js/angular/angular-resource.min.js | 2 +- dist/js/angular/angular-route.js | 15 +- dist/js/angular/angular-route.min.js | 12 +- dist/js/angular/angular-route.min.js.map | 2 +- dist/js/angular/angular-sanitize.js | 2 +- dist/js/angular/angular-sanitize.min.js | 2 +- dist/js/angular/angular-scenario.js | 186 ++++++++++++-------- dist/js/angular/angular-touch.js | 2 +- dist/js/angular/angular-touch.min.js | 2 +- dist/js/angular/angular.js | 186 ++++++++++++-------- dist/js/angular/angular.min.js | 190 ++++++++++----------- dist/js/angular/angular.min.js.map | 4 +- dist/js/angular/errors.json | 2 +- dist/js/angular/version.json | 2 +- dist/js/angular/version.txt | 2 +- js/ext/angular/test/clickTests.html | 20 ++- 27 files changed, 574 insertions(+), 329 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0081f1e64f..cfc8ff1e15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ ## 0.9.22-alpha (pre-release) + - Tap polyfill overhaul to remove 300ms delay when firing a click + - Android click firing twice fixes + - Upgrade to Angular v1.2.10 ## 0.9.21 "Alpha Maine Coon" (2014-01-24) diff --git a/dist/js/angular/angular-animate.js b/dist/js/angular/angular-animate.js index d830ff68ce..9b3144dcc1 100755 --- a/dist/js/angular/angular-animate.js +++ b/dist/js/angular/angular-animate.js @@ -1,5 +1,5 @@ /** - * @license AngularJS v1.2.8 + * @license AngularJS v1.2.10 * (c) 2010-2014 Google, Inc. http://angularjs.org * License: MIT */ @@ -254,6 +254,26 @@ angular.module('ngAnimate', ['ng']) * Please visit the {@link ngAnimate `ngAnimate`} module overview page learn more about how to use animations in your application. * */ + .factory('$$animateReflow', ['$window', '$timeout', function($window, $timeout) { + var requestAnimationFrame = $window.requestAnimationFrame || + $window.webkitRequestAnimationFrame || + function(fn) { + return $timeout(fn, 10, false); + }; + + var cancelAnimationFrame = $window.cancelAnimationFrame || + $window.webkitCancelAnimationFrame || + function(timer) { + return $timeout.cancel(timer); + }; + return function(fn) { + var id = requestAnimationFrame(fn); + return function() { + cancelAnimationFrame(id); + }; + }; + }]) + .config(['$provide', '$animateProvider', function($provide, $animateProvider) { var noop = angular.noop; var forEach = angular.forEach; @@ -301,6 +321,10 @@ angular.module('ngAnimate', ['ng']) return classNameFilter.test(className); }; + function async(fn) { + return $timeout(fn, 0, false); + } + function lookup(name) { if (name) { var matches = [], @@ -592,6 +616,8 @@ angular.module('ngAnimate', ['ng']) //best to catch this early on to prevent any animation operations from occurring if(!node || !isAnimatableClassName(classes)) { fireDOMOperation(); + fireBeforeCallbackAsync(); + fireAfterCallbackAsync(); closeAnimation(); return; } @@ -611,6 +637,8 @@ angular.module('ngAnimate', ['ng']) //NOTE: IE8 + IE9 should close properly (run closeAnimation()) in case a NO animation is not found. if (animationsDisabled(element, parentElement) || matches.length === 0) { fireDOMOperation(); + fireBeforeCallbackAsync(); + fireAfterCallbackAsync(); closeAnimation(); return; } @@ -649,14 +677,17 @@ angular.module('ngAnimate', ['ng']) //animation do it's thing and close this one early if(animations.length === 0) { fireDOMOperation(); + fireBeforeCallbackAsync(); + fireAfterCallbackAsync(); fireDoneCallbackAsync(); return; } + var ONE_SPACE = ' '; //this value will be searched for class-based CSS className lookup. Therefore, //we prefix and suffix the current className value with spaces to avoid substring //lookups of className tokens - var futureClassName = ' ' + currentClassName + ' '; + var futureClassName = ONE_SPACE + currentClassName + ONE_SPACE; if(ngAnimateState.running) { //if an animation is currently running on the element then lets take the steps //to cancel that animation and fire any required callbacks @@ -664,12 +695,23 @@ angular.module('ngAnimate', ['ng']) cleanup(element); cancelAnimations(ngAnimateState.animations); + //in the event that the CSS is class is quickly added and removed back + //then we don't want to wait until after the reflow to add/remove the CSS + //class since both class animations may run into a race condition. + //The code below will check to see if that is occurring and will + //immediately remove the former class before the reflow so that the + //animation can snap back to the original animation smoothly + var isFullyClassBasedAnimation = isClassBased && !ngAnimateState.structural; + var isRevertingClassAnimation = isFullyClassBasedAnimation && + ngAnimateState.className == className && + animationEvent != ngAnimateState.event; + //if the class is removed during the reflow then it will revert the styles temporarily //back to the base class CSS styling causing a jump-like effect to occur. This check //here ensures that the domOperation is only performed after the reflow has commenced - if(ngAnimateState.beforeComplete) { + if(ngAnimateState.beforeComplete || isRevertingClassAnimation) { (ngAnimateState.done || noop)(true); - } else if(isClassBased && !ngAnimateState.structural) { + } else if(isFullyClassBasedAnimation) { //class-based animations will compare element className values after cancelling the //previous animation to see if the element properties already contain the final CSS //class and if so then the animation will be skipped. Since the domOperation will @@ -677,8 +719,8 @@ angular.module('ngAnimate', ['ng']) //will be invalid. Therefore the same string manipulation that would occur within the //DOM operation will be performed below so that the class comparison is valid... futureClassName = ngAnimateState.event == 'removeClass' ? - futureClassName.replace(ngAnimateState.className, '') : - futureClassName + ngAnimateState.className + ' '; + futureClassName.replace(ONE_SPACE + ngAnimateState.className + ONE_SPACE, ONE_SPACE) : + futureClassName + ngAnimateState.className + ONE_SPACE; } } @@ -686,10 +728,12 @@ angular.module('ngAnimate', ['ng']) //(on addClass) or doesn't contain (on removeClass) the className being animated. //The reason why this is being called after the previous animations are cancelled //is so that the CSS classes present on the element can be properly examined. - var classNameToken = ' ' + className + ' '; + var classNameToken = ONE_SPACE + className + ONE_SPACE; if((animationEvent == 'addClass' && futureClassName.indexOf(classNameToken) >= 0) || (animationEvent == 'removeClass' && futureClassName.indexOf(classNameToken) == -1)) { fireDOMOperation(); + fireBeforeCallbackAsync(); + fireAfterCallbackAsync(); fireDoneCallbackAsync(); return; } @@ -730,6 +774,10 @@ angular.module('ngAnimate', ['ng']) } function invokeRegisteredAnimationFns(animations, phase, allAnimationFnsComplete) { + phase == 'after' ? + fireAfterCallbackAsync() : + fireBeforeCallbackAsync(); + var endFnName = phase + 'End'; forEach(animations, function(animation, index) { var animationPhaseCompleted = function() { @@ -766,8 +814,30 @@ angular.module('ngAnimate', ['ng']) } } + function fireDOMCallback(animationPhase) { + element.triggerHandler('$animate:' + animationPhase, { + event : animationEvent, + className : className + }); + } + + function fireBeforeCallbackAsync() { + async(function() { + fireDOMCallback('before'); + }); + } + + function fireAfterCallbackAsync() { + async(function() { + fireDOMCallback('after'); + }); + } + function fireDoneCallbackAsync() { - doneCallback && $timeout(doneCallback, 0, false); + async(function() { + fireDOMCallback('close'); + doneCallback && doneCallback(); + }); } //it is less complicated to use a flag than managing and cancelling @@ -791,9 +861,9 @@ angular.module('ngAnimate', ['ng']) if(isClassBased) { cleanup(element); } else { - data.closeAnimationTimeout = $timeout(function() { + data.closeAnimationTimeout = async(function() { cleanup(element); - }, 0, false); + }); element.data(NG_ANIMATE_STATE, data); } } @@ -817,10 +887,10 @@ angular.module('ngAnimate', ['ng']) function cancelAnimations(animations) { var isCancelledFlag = true; forEach(animations, function(animation) { - if(!animations.beforeComplete) { + if(!animation.beforeComplete) { (animation.beforeEnd || noop)(isCancelledFlag); } - if(!animations.afterComplete) { + if(!animation.afterComplete) { (animation.afterEnd || noop)(isCancelledFlag); } }); @@ -866,7 +936,8 @@ angular.module('ngAnimate', ['ng']) } }]); - $animateProvider.register('', ['$window', '$sniffer', '$timeout', function($window, $sniffer, $timeout) { + $animateProvider.register('', ['$window', '$sniffer', '$timeout', '$$animateReflow', + function($window, $sniffer, $timeout, $$animateReflow) { // Detect proper transitionend/animationend event names. var CSS_PREFIX = '', TRANSITION_PROP, TRANSITIONEND_EVENT, ANIMATION_PROP, ANIMATIONEND_EVENT; @@ -911,11 +982,13 @@ angular.module('ngAnimate', ['ng']) var parentCounter = 0; var animationReflowQueue = []; var animationElementQueue = []; - var animationTimer; + var cancelAnimationReflow; var closingAnimationTime = 0; var timeOut = false; function afterReflow(element, callback) { - $timeout.cancel(animationTimer); + if(cancelAnimationReflow) { + cancelAnimationReflow(); + } animationReflowQueue.push(callback); @@ -924,15 +997,19 @@ angular.module('ngAnimate', ['ng']) animationElementQueue.push(element); var elementData = element.data(NG_ANIMATE_CSS_DATA_KEY); - closingAnimationTime = Math.max(closingAnimationTime, - (elementData.maxDelay + elementData.maxDuration) * CLOSING_TIME_BUFFER * ONE_SECOND); + + var stagger = elementData.stagger; + var staggerTime = elementData.itemIndex * (Math.max(stagger.animationDelay, stagger.transitionDelay) || 0); + + var animationTime = (elementData.maxDelay + elementData.maxDuration) * CLOSING_TIME_BUFFER; + closingAnimationTime = Math.max(closingAnimationTime, (staggerTime + animationTime) * ONE_SECOND); //by placing a counter we can avoid an accidental //race condition which may close an animation when //a follow-up animation is midway in its animation elementData.animationCount = animationCounter; - animationTimer = $timeout(function() { + cancelAnimationReflow = $$animateReflow(function() { forEach(animationReflowQueue, function(fn) { fn(); }); @@ -953,11 +1030,11 @@ angular.module('ngAnimate', ['ng']) animationReflowQueue = []; animationElementQueue = []; - animationTimer = null; + cancelAnimationReflow = null; lookupCache = {}; closingAnimationTime = 0; animationCounter++; - }, 10, false); + }); } function closeAllAnimations(elements, count) { @@ -1048,13 +1125,13 @@ angular.module('ngAnimate', ['ng']) return parentID + '-' + extractElementNode(element).className; } - function animateSetup(element, className) { + function animateSetup(element, className, calculationDecorator) { var cacheKey = getCacheKey(element); var eventCacheKey = cacheKey + ' ' + className; var stagger = {}; - var ii = lookupCache[eventCacheKey] ? ++lookupCache[eventCacheKey].total : 0; + var itemIndex = lookupCache[eventCacheKey] ? ++lookupCache[eventCacheKey].total : 0; - if(ii > 0) { + if(itemIndex > 0) { var staggerClassName = className + '-stagger'; var staggerCacheKey = cacheKey + ' ' + staggerClassName; var applyClasses = !lookupCache[staggerCacheKey]; @@ -1066,9 +1143,16 @@ angular.module('ngAnimate', ['ng']) applyClasses && element.removeClass(staggerClassName); } + /* the animation itself may need to add/remove special CSS classes + * before calculating the anmation styles */ + calculationDecorator = calculationDecorator || + function(fn) { return fn(); }; + element.addClass(className); - var timings = getElementAnimationDetails(element, eventCacheKey); + var timings = calculationDecorator(function() { + return getElementAnimationDetails(element, eventCacheKey); + }); /* there is no point in performing a reflow if the animation timeout is empty (this would cause a flicker bug normally @@ -1100,7 +1184,7 @@ angular.module('ngAnimate', ['ng']) classes : className + ' ' + activeClassName, timings : timings, stagger : stagger, - ii : ii + itemIndex : itemIndex }); return true; @@ -1145,7 +1229,7 @@ angular.module('ngAnimate', ['ng']) var maxDelayTime = Math.max(timings.transitionDelay, timings.animationDelay) * ONE_SECOND; var startTime = Date.now(); var css3AnimationEvents = ANIMATIONEND_EVENT + ' ' + TRANSITIONEND_EVENT; - var ii = elementData.ii; + var itemIndex = elementData.itemIndex; var style = '', appliedStyles = []; if(timings.transitionDuration > 0) { @@ -1158,17 +1242,17 @@ angular.module('ngAnimate', ['ng']) } } - if(ii > 0) { + if(itemIndex > 0) { if(stagger.transitionDelay > 0 && stagger.transitionDuration === 0) { var delayStyle = timings.transitionDelayStyle; style += CSS_PREFIX + 'transition-delay: ' + - prepareStaggerDelay(delayStyle, stagger.transitionDelay, ii) + '; '; + prepareStaggerDelay(delayStyle, stagger.transitionDelay, itemIndex) + '; '; appliedStyles.push(CSS_PREFIX + 'transition-delay'); } if(stagger.animationDelay > 0 && stagger.animationDuration === 0) { style += CSS_PREFIX + 'animation-delay: ' + - prepareStaggerDelay(timings.animationDelayStyle, stagger.animationDelay, ii) + '; '; + prepareStaggerDelay(timings.animationDelayStyle, stagger.animationDelay, itemIndex) + '; '; appliedStyles.push(CSS_PREFIX + 'animation-delay'); } } @@ -1233,8 +1317,8 @@ angular.module('ngAnimate', ['ng']) return style; } - function animateBefore(element, className) { - if(animateSetup(element, className)) { + function animateBefore(element, className, calculationDecorator) { + if(animateSetup(element, className, calculationDecorator)) { return function(cancelled) { cancelled && animateClose(element, className); }; @@ -1329,7 +1413,18 @@ angular.module('ngAnimate', ['ng']) }, beforeAddClass : function(element, className, animationCompleted) { - var cancellationMethod = animateBefore(element, suffixClasses(className, '-add')); + var cancellationMethod = animateBefore(element, suffixClasses(className, '-add'), function(fn) { + + /* when a CSS class is added to an element then the transition style that + * is applied is the transition defined on the element when the CSS class + * is added at the time of the animation. This is how CSS3 functions + * outside of ngAnimate. */ + element.addClass(className); + var timings = fn(); + element.removeClass(className); + return timings; + }); + if(cancellationMethod) { afterReflow(element, function() { unblockTransitions(element); @@ -1346,7 +1441,18 @@ angular.module('ngAnimate', ['ng']) }, beforeRemoveClass : function(element, className, animationCompleted) { - var cancellationMethod = animateBefore(element, suffixClasses(className, '-remove')); + var cancellationMethod = animateBefore(element, suffixClasses(className, '-remove'), function(fn) { + /* when classes are removed from an element then the transition style + * that is applied is the transition defined on the element without the + * CSS class being there. This is how CSS3 functions outside of ngAnimate. + * http://plnkr.co/edit/j8OzgTNxHTb4n3zLyjGW?p=preview */ + var klass = element.attr('class'); + element.removeClass(className); + var timings = fn(); + element.attr('class', klass); + return timings; + }); + if(cancellationMethod) { afterReflow(element, function() { unblockTransitions(element); diff --git a/dist/js/angular/angular-animate.min.js b/dist/js/angular/angular-animate.min.js index 1f0040a312..4f66338a70 100755 --- a/dist/js/angular/angular-animate.min.js +++ b/dist/js/angular/angular-animate.min.js @@ -1,23 +1,25 @@ /* - AngularJS v1.2.8 + AngularJS v1.2.10 (c) 2010-2014 Google, Inc. http://angularjs.org License: MIT */ -(function(E,p,F){'use strict';p.module("ngAnimate",["ng"]).config(["$provide","$animateProvider",function(R,L){function f(f){for(var l=0;l=v&&c>=s&&d()}var k=c.data(n),l=f(c);if(-1!=l.className.indexOf(a)&&k){var m=k.timings,p=k.stagger,s=k.maxDuration,r=k.activeClassName,v=Math.max(m.transitionDelay,m.animationDelay)*B,w=Date.now(),u=C+" "+g,t=k.ii,A="",q=[];if(0=u&&a>=p&&h()}var f=b.data(n),g=d(b);if(-1!=g.className.indexOf(a)&&f){var l=f.timings,m=f.stagger,p=f.maxDuration,r=f.activeClassName,u=Math.max(l.transitionDelay, +l.animationDelay)*x,w=Date.now(),v=T+" "+S,t=f.itemIndex,q="",s=[];if(0 - * $log.log('Some Error'); + * $log.error('Some Error'); * var first = $log.error.logs.unshift(); * */ @@ -763,6 +763,36 @@ angular.mock.TzDate = function (offset, timestamp) { angular.mock.TzDate.prototype = Date.prototype; /* jshint +W101 */ +// TODO(matias): remove this IMMEDIATELY once we can properly detect the +// presence of a registered module +var animateLoaded; +try { + angular.module('ngAnimate'); + animateLoaded = true; +} catch(e) {} + +if(animateLoaded) { + angular.module('ngAnimate').config(['$provide', function($provide) { + var reflowQueue = []; + $provide.value('$$animateReflow', function(fn) { + reflowQueue.push(fn); + return angular.noop; + }); + $provide.decorator('$animate', function($delegate) { + $delegate.triggerReflow = function() { + if(reflowQueue.length === 0) { + throw new Error('No animation reflows present'); + } + angular.forEach(reflowQueue, function(fn) { + fn(); + }); + reflowQueue = []; + }; + return $delegate; + }); + }]); +} + angular.mock.animate = angular.module('mock.animate', ['ng']) .config(['$provide', function($provide) { @@ -1706,7 +1736,7 @@ angular.mock.$RootElementProvider = function() { * In addition, ngMock also extends various core ng services such that they can be * inspected and controlled in a synchronous manner within test code. * - * {@installModule mocks} + * {@installModule mock} * *
* @@ -1920,7 +1950,6 @@ angular.mock.clearDataCache = function() { }; - if(window.jasmine || window.mocha) { var currentSpec = null, diff --git a/dist/js/angular/angular-resource.js b/dist/js/angular/angular-resource.js index 150f6d5d76..38bebab22c 100755 --- a/dist/js/angular/angular-resource.js +++ b/dist/js/angular/angular-resource.js @@ -1,5 +1,5 @@ /** - * @license AngularJS v1.2.8 + * @license AngularJS v1.2.10 * (c) 2010-2014 Google, Inc. http://angularjs.org * License: MIT */ diff --git a/dist/js/angular/angular-resource.min.js b/dist/js/angular/angular-resource.min.js index f968cb2d48..9df2b8309f 100755 --- a/dist/js/angular/angular-resource.min.js +++ b/dist/js/angular/angular-resource.min.js @@ -1,5 +1,5 @@ /* - AngularJS v1.2.8 + AngularJS v1.2.10 (c) 2010-2014 Google, Inc. http://angularjs.org License: MIT */ diff --git a/dist/js/angular/angular-route.js b/dist/js/angular/angular-route.js index d31d4ca537..cf1e4b6edb 100755 --- a/dist/js/angular/angular-route.js +++ b/dist/js/angular/angular-route.js @@ -1,5 +1,5 @@ /** - * @license AngularJS v1.2.8 + * @license AngularJS v1.2.10 * (c) 2010-2014 Google, Inc. http://angularjs.org * License: MIT */ @@ -190,7 +190,7 @@ function $RouteProvider(){ path = path .replace(/([().])/g, '\\$1') - .replace(/(\/)?:(\w+)([\?|\*])?/g, function(_, slash, key, option){ + .replace(/(\/)?:(\w+)([\?\*])?/g, function(_, slash, key, option){ var optional = option === '?' ? option : null; var star = option === '*' ? option : null; keys.push({ name: key, optional: !!optional }); @@ -375,7 +375,7 @@ function $RouteProvider(){ * @eventType broadcast on root scope * @description * Broadcasted before a route change. At this point the route services starts - * resolving all of the dependencies needed for the route change to occurs. + * resolving all of the dependencies needed for the route change to occur. * Typically this involves fetching the view template as well as any dependencies * defined in `resolve` route property. Once all of the dependencies are resolved * `$routeChangeSuccess` is fired. @@ -669,6 +669,15 @@ ngRouteModule.directive('ngView', ngViewFillContentFactory); * * @scope * @priority 400 + * @param {string=} onload Expression to evaluate whenever the view updates. + * + * @param {string=} autoscroll Whether `ngView` should call {@link ng.$anchorScroll + * $anchorScroll} to scroll the viewport after the view is updated. + * + * - If the attribute is not set, disable scrolling. + * - If the attribute is set without value, enable scrolling. + * - Otherwise enable scrolling only if the `autoscroll` attribute value evaluated + * as an expression yields a truthy value. * @example diff --git a/dist/js/angular/angular-route.min.js b/dist/js/angular/angular-route.min.js index 5cdb6a88af..62bed89360 100755 --- a/dist/js/angular/angular-route.min.js +++ b/dist/js/angular/angular-route.min.js @@ -1,14 +1,14 @@ /* - AngularJS v1.2.8 + AngularJS v1.2.10 (c) 2010-2014 Google, Inc. http://angularjs.org License: MIT */ (function(h,e,A){'use strict';function u(w,q,k){return{restrict:"ECA",terminal:!0,priority:400,transclude:"element",link:function(a,c,b,f,n){function y(){l&&(l.$destroy(),l=null);g&&(k.leave(g),g=null)}function v(){var b=w.current&&w.current.locals;if(e.isDefined(b&&b.$template)){var b=a.$new(),f=w.current;g=n(b,function(d){k.enter(d,null,g||c,function(){!e.isDefined(t)||t&&!a.$eval(t)||q()});y()});l=f.scope=b;l.$emit("$viewContentLoaded");l.$eval(h)}else y()}var l,g,t=b.autoscroll,h=b.onload||""; a.$on("$routeChangeSuccess",v);v()}}}function z(e,h,k){return{restrict:"ECA",priority:-400,link:function(a,c){var b=k.current,f=b.locals;c.html(f.$template);var n=e(c.contents());b.controller&&(f.$scope=a,f=h(b.controller,f),b.controllerAs&&(a[b.controllerAs]=f),c.data("$ngControllerController",f),c.children().data("$ngControllerController",f));n(a)}}}h=e.module("ngRoute",["ng"]).provider("$route",function(){function h(a,c){return e.extend(new (e.extend(function(){},{prototype:a})),c)}function q(a, -e){var b=e.caseInsensitiveMatch,f={originalPath:a,regexp:a},h=f.keys=[];a=a.replace(/([().])/g,"\\$1").replace(/(\/)?:(\w+)([\?|\*])?/g,function(a,e,b,c){a="?"===c?c:null;c="*"===c?c:null;h.push({name:b,optional:!!a});e=e||"";return""+(a?"":e)+"(?:"+(a?e:"")+(c&&"(.+?)"||"([^/]+)")+(a||"")+")"+(a||"")}).replace(/([\/$\*])/g,"\\$1");f.regexp=RegExp("^"+a+"$",b?"i":"");return f}var k={};this.when=function(a,c){k[a]=e.extend({reloadOnSearch:!0},c,a&&q(a,c));if(a){var b="/"==a[a.length-1]?a.substr(0, -a.length-1):a+"/";k[b]=e.extend({redirectTo:a},q(b,c))}return this};this.otherwise=function(a){this.when(null,a);return this};this.$get=["$rootScope","$location","$routeParams","$q","$injector","$http","$templateCache","$sce",function(a,c,b,f,n,q,v,l){function g(){var d=t(),m=r.current;if(d&&m&&d.$$route===m.$$route&&e.equals(d.pathParams,m.pathParams)&&!d.reloadOnSearch&&!x)m.params=d.params,e.copy(m.params,b),a.$broadcast("$routeUpdate",m);else if(d||m)x=!1,a.$broadcast("$routeChangeStart",d,m), -(r.current=d)&&d.redirectTo&&(e.isString(d.redirectTo)?c.path(u(d.redirectTo,d.params)).search(d.params).replace():c.url(d.redirectTo(d.pathParams,c.path(),c.search())).replace()),f.when(d).then(function(){if(d){var a=e.extend({},d.resolve),c,b;e.forEach(a,function(d,c){a[c]=e.isString(d)?n.get(d):n.invoke(d)});e.isDefined(c=d.template)?e.isFunction(c)&&(c=c(d.params)):e.isDefined(b=d.templateUrl)&&(e.isFunction(b)&&(b=b(d.params)),b=l.getTrustedResourceUrl(b),e.isDefined(b)&&(d.loadedTemplateUrl= -b,c=q.get(b,{cache:v}).then(function(a){return a.data})));e.isDefined(c)&&(a.$template=c);return f.all(a)}}).then(function(c){d==r.current&&(d&&(d.locals=c,e.copy(d.params,b)),a.$broadcast("$routeChangeSuccess",d,m))},function(c){d==r.current&&a.$broadcast("$routeChangeError",d,m,c)})}function t(){var a,b;e.forEach(k,function(f,k){var p;if(p=!b){var s=c.path();p=f.keys;var l={};if(f.regexp)if(s=f.regexp.exec(s)){for(var g=1,q=s.length;g - * class Ping - * constructor: (@$http) -> - * send: () => - * @$http.get('/ping') - * - * $provide.service('ping', ['$http', Ping]) + * $provide.service('ping', ['$http', function($http) { + * var Ping = function() { + * this.$http = $http; + * }; + * + * Ping.prototype.send = function() { + * return this.$http.get('/ping'); + * }; + * + * return Ping; + * }]); * * You would then inject and use this service like this: *
- *   someModule.controller 'Ctrl', ['ping', (ping) ->
- *     ping.send()
- *   ]
+ *   someModule.controller('Ctrl', ['ping', function(ping) {
+ *     ping.send();
+ *   }]);
  * 
*/ @@ -16737,9 +16741,9 @@ function $HttpProvider() { common: { 'Accept': 'application/json, text/plain, */*' }, - post: CONTENT_TYPE_APPLICATION_JSON, - put: CONTENT_TYPE_APPLICATION_JSON, - patch: CONTENT_TYPE_APPLICATION_JSON + post: copy(CONTENT_TYPE_APPLICATION_JSON), + put: copy(CONTENT_TYPE_APPLICATION_JSON), + patch: copy(CONTENT_TYPE_APPLICATION_JSON) }, xsrfCookieName: 'XSRF-TOKEN', @@ -16849,31 +16853,14 @@ function $HttpProvider() { * XMLHttpRequest will transparently follow it, meaning that the error callback will not be * called for such responses. * - * # Calling $http from outside AngularJS - * The `$http` service will not actually send the request until the next `$digest()` is - * executed. Normally this is not an issue, since almost all the time your call to `$http` will - * be from within a `$apply()` block. - * If you are calling `$http` from outside Angular, then you should wrap it in a call to - * `$apply` to cause a $digest to occur and also to handle errors in the block correctly. - * - * ``` - * $scope.$apply(function() { - * $http(...); - * }); - * ``` - * * # Writing Unit Tests that use $http - * When unit testing you are mostly responsible for scheduling the `$digest` cycle. If you do - * not trigger a `$digest` before calling `$httpBackend.flush()` then the request will not have - * been made and `$httpBackend.expect(...)` expectations will fail. The solution is to run the - * code that calls the `$http()` method inside a $apply block as explained in the previous - * section. + * When unit testing (using {@link api/ngMock ngMock}), it is necessary to call + * {@link api/ngMock.$httpBackend#methods_flush $httpBackend.flush()} to flush each pending + * request using trained responses. * * ``` * $httpBackend.expectGET(...); - * $scope.$apply(function() { - * $http.get(...); - * }); + * $http.get(...); * $httpBackend.flush(); * ``` * @@ -16950,7 +16937,7 @@ function $HttpProvider() { * to `push` or `unshift` a new transformation function into the transformation chain. You can * also decide to completely override any default transformations by assigning your * transformation functions to these properties directly without the array wrapper. These defaults - * are again available on the $http factory at run-time, which may be useful if you have run-time + * are again available on the $http factory at run-time, which may be useful if you have run-time * services you wish to be involved in your transformations. * * Similarly, to locally override the request/response transforms, augment the @@ -18108,7 +18095,7 @@ function $IntervalProvider() { * In tests you can use {@link ngMock.$interval#methods_flush `$interval.flush(millis)`} to * move forward by `millis` milliseconds and trigger any functions scheduled to run in that * time. - * + * *
* **Note**: Intervals created by this service must be explicitly destroyed when you are finished * with them. In particular they are not automatically destroyed when a controller's scope or a @@ -18221,8 +18208,8 @@ function $IntervalProvider() { promise = deferred.promise, iteration = 0, skipApply = (isDefined(invokeApply) && !invokeApply); - - count = isDefined(count) ? count : 0, + + count = isDefined(count) ? count : 0; promise.then(null, null, fn); @@ -19922,7 +19909,7 @@ Parser.prototype = { var getter = getterFn(field, this.options, this.text); return extend(function(scope, locals, self) { - return getter(self || object(scope, locals), locals); + return getter(self || object(scope, locals)); }, { assign: function(scope, value, locals) { return setter(object(scope, locals), field, value, parser.text, parser.options); @@ -20498,9 +20485,9 @@ function $ParseProvider() { * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming. * *
- *   // for the purpose of this example let's assume that variables `$q` and `scope` are
- *   // available in the current lexical scope (they could have been injected or passed in).
- *
+ *   // for the purpose of this example let's assume that variables `$q`, `scope` and `okToGreet`
+ *   // are available in the current lexical scope (they could have been injected or passed in).
+ * 
  *   function asyncGreet(name) {
  *     var deferred = $q.defer();
  *
@@ -21628,7 +21615,7 @@ function $RootScopeProvider(){
 
           // `break traverseScopesLoop;` takes us to here
 
-          if(dirty && !(ttl--)) {
+          if((dirty || asyncQueue.length) && !(ttl--)) {
             clearPhase();
             throw $rootScopeMinErr('infdig',
                 '{0} $digest() iterations reached. Aborting!\n' +
@@ -22433,7 +22420,7 @@ function $SceDelegateProvider() {
      *
      * @description
      * Returns an object that is trusted by angular for use in specified strict
-     * contextual escaping contexts (such as ng-html-bind-unsafe, ng-include, any src
+     * contextual escaping contexts (such as ng-bind-html, ng-include, any src
      * attribute interpolation, any dom event binding attribute interpolation
      * such as for onclick,  etc.) that uses the provided value.
      * See {@link ng.$sce $sce} for enabling strict contextual escaping.
@@ -22479,7 +22466,7 @@ function $SceDelegateProvider() {
      *
      * @param {*} value The result of a prior {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs`}
      *      call or anything else.
-     * @returns {*} The value the was originally provided to {@link ng.$sceDelegate#methods_trustAs
+     * @returns {*} The `value` that was originally provided to {@link ng.$sceDelegate#methods_trustAs
      *     `$sceDelegate.trustAs`} if `value` is the result of such a call.  Otherwise, returns
      *     `value` unchanged.
      */
@@ -22660,8 +22647,8 @@ function $SceDelegateProvider() {
  * It's important to remember that SCE only applies to interpolation expressions.
  *
  * If your expressions are constant literals, they're automatically trusted and you don't need to
- * call `$sce.trustAs` on them.  (e.g.
- * `
`) just works. + * call `$sce.trustAs` on them (remember to include the `ngSanitize` module) (e.g. + * `
`) just works. * * Additionally, `a[href]` and `img[src]` automatically sanitize their URLs and do not pass them * through {@link ng.$sce#methods_getTrusted $sce.getTrusted}. SCE doesn't play a role here. @@ -22721,7 +22708,7 @@ function $SceDelegateProvider() { * matched against the **entire** *normalized / absolute URL* of the resource being tested * (even when the RegExp did not have the `^` and `$` codes.) In addition, any flags * present on the RegExp (such as multiline, global, ignoreCase) are ignored. - * - If you are generating your Javascript from some other templating engine (not + * - If you are generating your JavaScript from some other templating engine (not * recommended, e.g. in issue [#4006](https://github.com/angular/angular.js/issues/4006)), * remember to escape your regular expression (and be aware that you might need more than * one level of escaping depending on your templating engine and the way you interpolated @@ -22738,7 +22725,7 @@ function $SceDelegateProvider() { * ## Show me an example using SCE. * * @example - +


@@ -22963,8 +22950,8 @@ function $SceProvider() { * * @description * Delegates to {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs`}. As such, - * returns an objectthat is trusted by angular for use in specified strict contextual - * escaping contexts (such as ng-html-bind-unsafe, ng-include, any src attribute + * returns an object that is trusted by angular for use in specified strict contextual + * escaping contexts (such as ng-bind-html, ng-include, any src attribute * interpolation, any dom event binding attribute interpolation such as for onclick, etc.) * that uses the provided value. See * {@link ng.$sce $sce} for enabling strict contextual * escaping. @@ -24642,11 +24629,14 @@ var htmlAnchorDirective = valueFn({ element.append(document.createComment('IE fix')); } - if (!attr.href && !attr.name) { + if (!attr.href && !attr.xlinkHref && !attr.name) { return function(scope, element) { + // SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute. + var href = toString.call(element.prop('href')) === '[object SVGAnimatedString]' ? + 'xlink:href' : 'href'; element.on('click', function(event){ // if we have no href url, then don't navigate anywhere. - if (!element.attr('href')) { + if (!element.attr(href)) { event.preventDefault(); } }); @@ -25413,7 +25403,7 @@ var ngFormDirective = formDirectiveFactory(true); */ var URL_REGEXP = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/; -var EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}$/; +var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+/=?^_`{|}~.-]+@[a-z0-9-]+(\.[a-z0-9-]+)*$/i; var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/; var inputType = { @@ -25713,6 +25703,8 @@ var inputType = { * @param {string=} name Property name of the form under which the control is published. * @param {string=} ngChange Angular expression to be executed when input changes due to user * interaction with the input element. + * @param {string} ngValue Angular expression which sets the value to which the expression should + * be set when selected. * * @example @@ -25720,21 +25712,26 @@ var inputType = {
Red
- Green
+ Green
Blue
- color = {{color}}
+ color = {{color | json}}
+ Note that `ng-value="specialValue"` sets radio item's value to be the value of `$scope.specialValue`. it('should change state', function() { - expect(binding('color')).toEqual('blue'); + expect(binding('color')).toEqual('"blue"'); input('color').select('red'); - expect(binding('color')).toEqual('red'); + expect(binding('color')).toEqual('"red"'); });
@@ -26592,7 +26589,10 @@ var ngModelDirective = function() { * @name ng.directive:ngChange * * @description - * Evaluate given expression when user changes the input. + * Evaluate the given expression when the user changes the input. + * The expression is evaluated immediately, unlike the JavaScript onchange event + * which only triggers at the end of a change (usually, when the user leaves the + * form element or presses the return key). * The expression is not evaluated when the value change is coming from the model. * * Note, this directive requires `ngModel` to be present. @@ -27585,6 +27585,7 @@ var ngControllerDirective = [function() { * an element is clicked. * * @element ANY + * @priority 0 * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon * click. (Event object is available as `$event`) * @@ -27641,6 +27642,7 @@ forEach( * The `ngDblclick` directive allows you to specify custom behavior on a dblclick event. * * @element ANY + * @priority 0 * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon * a dblclick. (The Event object is available as `$event`) * @@ -27664,6 +27666,7 @@ forEach( * The ngMousedown directive allows you to specify custom behavior on mousedown event. * * @element ANY + * @priority 0 * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon * mousedown. (Event object is available as `$event`) * @@ -27687,6 +27690,7 @@ forEach( * Specify custom behavior on mouseup event. * * @element ANY + * @priority 0 * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon * mouseup. (Event object is available as `$event`) * @@ -27709,6 +27713,7 @@ forEach( * Specify custom behavior on mouseover event. * * @element ANY + * @priority 0 * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon * mouseover. (Event object is available as `$event`) * @@ -27732,6 +27737,7 @@ forEach( * Specify custom behavior on mouseenter event. * * @element ANY + * @priority 0 * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon * mouseenter. (Event object is available as `$event`) * @@ -27755,6 +27761,7 @@ forEach( * Specify custom behavior on mouseleave event. * * @element ANY + * @priority 0 * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon * mouseleave. (Event object is available as `$event`) * @@ -27778,6 +27785,7 @@ forEach( * Specify custom behavior on mousemove event. * * @element ANY + * @priority 0 * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon * mousemove. (Event object is available as `$event`) * @@ -27801,6 +27809,7 @@ forEach( * Specify custom behavior on keydown event. * * @element ANY + * @priority 0 * @param {expression} ngKeydown {@link guide/expression Expression} to evaluate upon * keydown. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.) * @@ -27822,6 +27831,7 @@ forEach( * Specify custom behavior on keyup event. * * @element ANY + * @priority 0 * @param {expression} ngKeyup {@link guide/expression Expression} to evaluate upon * keyup. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.) * @@ -27868,6 +27878,7 @@ forEach( * attribute**. * * @element form + * @priority 0 * @param {expression} ngSubmit {@link guide/expression Expression} to eval. (Event object is available as `$event`) * * @example @@ -27917,6 +27928,7 @@ forEach( * Specify custom behavior on focus event. * * @element window, input, select, textarea, a + * @priority 0 * @param {expression} ngFocus {@link guide/expression Expression} to evaluate upon * focus. (Event object is available as `$event`) * @@ -27932,6 +27944,7 @@ forEach( * Specify custom behavior on blur event. * * @element window, input, select, textarea, a + * @priority 0 * @param {expression} ngBlur {@link guide/expression Expression} to evaluate upon * blur. (Event object is available as `$event`) * @@ -27947,6 +27960,7 @@ forEach( * Specify custom behavior on copy event. * * @element window, input, select, textarea, a + * @priority 0 * @param {expression} ngCopy {@link guide/expression Expression} to evaluate upon * copy. (Event object is available as `$event`) * @@ -27967,6 +27981,7 @@ forEach( * Specify custom behavior on cut event. * * @element window, input, select, textarea, a + * @priority 0 * @param {expression} ngCut {@link guide/expression Expression} to evaluate upon * cut. (Event object is available as `$event`) * @@ -27987,6 +28002,7 @@ forEach( * Specify custom behavior on paste event. * * @element window, input, select, textarea, a + * @priority 0 * @param {expression} ngPaste {@link guide/expression Expression} to evaluate upon * paste. (Event object is available as `$event`) * @@ -28370,6 +28386,13 @@ var ngIncludeFillContentDirective = ['$compile', * should use {@link guide/controller controllers} rather than `ngInit` * to initialize values on a scope. *
+ *
+ * **Note**: If you have assignment in `ngInit` along with {@link api/ng.$filter `$filter`}, make + * sure you have parenthesis for correct precedence: + *
+ *   
+ *
+ *
* * @priority 450 * @@ -29105,6 +29128,11 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) { * * Just remember to include the important flag so the CSS override will function. * + *
+ * **Note:** Here is a list of values that ngShow will consider as a falsy value (case insensitive):
+ * "f" / "0" / "false" / "no" / "n" / "[]" + *
+ * * ## A note about animations with ngShow * * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression @@ -29253,6 +29281,11 @@ var ngShowDirective = ['$animate', function($animate) { *
* * Just remember to include the important flag so the CSS override will function. + * + *
+ * **Note:** Here is a list of values that ngHide will consider as a falsy value (case insensitive):
+ * "f" / "0" / "false" / "no" / "n" / "[]" + *
* * ## A note about animations with ngHide * @@ -29724,14 +29757,21 @@ var ngOptionsMinErr = minErr('ngOptions'); * represented by the selected option will be bound to the model identified by the `ngModel` * directive. * + *
+ * **Note:** `ngModel` compares by reference, not value. This is important when binding to an + * array of objects. See an example {@link http://jsfiddle.net/qWzTb/ in this jsfiddle}. + *
+ * * Optionally, a single hard-coded `
+ *
+ * **Note**: If you have assignment in `ngInit` along with {@link api/ng.$filter `$filter`}, make + * sure you have parenthesis for correct precedence: + *
+ *   
+ *
+ *
* * @priority 450 * @@ -19313,6 +19336,11 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) { * * Just remember to include the important flag so the CSS override will function. * + *
+ * **Note:** Here is a list of values that ngShow will consider as a falsy value (case insensitive):
+ * "f" / "0" / "false" / "no" / "n" / "[]" + *
+ * * ## A note about animations with ngShow * * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression @@ -19461,6 +19489,11 @@ var ngShowDirective = ['$animate', function($animate) { * * * Just remember to include the important flag so the CSS override will function. + * + *
+ * **Note:** Here is a list of values that ngHide will consider as a falsy value (case insensitive):
+ * "f" / "0" / "false" / "no" / "n" / "[]" + *
* * ## A note about animations with ngHide * @@ -19932,14 +19965,21 @@ var ngOptionsMinErr = minErr('ngOptions'); * represented by the selected option will be bound to the model identified by the `ngModel` * directive. * + *
+ * **Note:** `ngModel` compares by reference, not value. This is important when binding to an + * array of objects. See an example {@link http://jsfiddle.net/qWzTb/ in this jsfiddle}. + *
+ * * Optionally, a single hard-coded `