From 97f4f6eacea512c5ef3845e0ba89663ef0758915 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Mon, 17 Feb 2014 16:15:15 -0600 Subject: [PATCH] feat(angular): Update to Angular v1.2.13, closes #600 --- config/build.js | 2 - config/lib/js/angular/angular-animate.js | 559 ++++--- config/lib/js/angular/angular-animate.min.js | 42 +- config/lib/js/angular/angular-mocks.js | 83 +- config/lib/js/angular/angular-resource.js | 8 +- config/lib/js/angular/angular-resource.min.js | 8 +- config/lib/js/angular/angular-sanitize.js | 622 -------- config/lib/js/angular/angular-sanitize.min.js | 14 - config/lib/js/angular/angular-scenario.js | 1420 ++++++++++------- config/lib/js/angular/angular.js | 1418 +++++++++------- config/lib/js/angular/angular.min.js | 392 ++--- config/lib/js/angular/errors.json | 2 +- .../test/service/ionicActionSheet.unit.js | 2 - 13 files changed, 2286 insertions(+), 2286 deletions(-) mode change 100644 => 100755 config/lib/js/angular/angular-resource.js mode change 100644 => 100755 config/lib/js/angular/angular-resource.min.js delete mode 100755 config/lib/js/angular/angular-sanitize.js delete mode 100755 config/lib/js/angular/angular-sanitize.min.js diff --git a/config/build.js b/config/build.js index 42b3b811b06..3e836a8df1a 100644 --- a/config/build.js +++ b/config/build.js @@ -54,8 +54,6 @@ module.exports = { 'js/angular/angular-animate.min.js', 'js/angular/angular-resource.js', 'js/angular/angular-resource.min.js', - 'js/angular/angular-sanitize.js', - 'js/angular/angular-sanitize.min.js', 'js/angular/angular.js', 'js/angular/angular.min.js', 'js/angular-ui/angular-ui-router.js', diff --git a/config/lib/js/angular/angular-animate.js b/config/lib/js/angular/angular-animate.js index 9b3144dcc1e..d8a7855ae00 100755 --- a/config/lib/js/angular/angular-animate.js +++ b/config/lib/js/angular/angular-animate.js @@ -1,5 +1,5 @@ /** - * @license AngularJS v1.2.10 + * @license AngularJS v1.2.13 * (c) 2010-2014 Google, Inc. http://angularjs.org * License: MIT */ @@ -254,7 +254,9 @@ 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) { + .factory('$$animateReflow', ['$window', '$timeout', '$document', + function($window, $timeout, $document) { + var bod = $document[0].body; var requestAnimationFrame = $window.requestAnimationFrame || $window.webkitRequestAnimationFrame || function(fn) { @@ -267,13 +269,30 @@ angular.module('ngAnimate', ['ng']) return $timeout.cancel(timer); }; return function(fn) { - var id = requestAnimationFrame(fn); + var id = requestAnimationFrame(function() { + var a = bod.offsetWidth + 1; + fn(); + }); return function() { cancelAnimationFrame(id); }; }; }]) + .factory('$$asyncQueueBuffer', ['$timeout', function($timeout) { + var timer, queue = []; + return function(fn) { + $timeout.cancel(timer); + queue.push(fn); + timer = $timeout(function() { + for(var i = 0; i < queue.length; i++) { + queue[i](); + } + queue = []; + }, 0, false); + }; + }]) + .config(['$provide', '$animateProvider', function($provide, $animateProvider) { var noop = angular.noop; var forEach = angular.forEach; @@ -293,13 +312,18 @@ angular.module('ngAnimate', ['ng']) } } + function stripCommentsFromElement(element) { + return angular.element(extractElementNode(element)); + } + function isMatchingElement(elm1, elm2) { return extractElementNode(elm1) == extractElementNode(elm2); } - $provide.decorator('$animate', ['$delegate', '$injector', '$sniffer', '$rootElement', '$timeout', '$rootScope', '$document', - function($delegate, $injector, $sniffer, $rootElement, $timeout, $rootScope, $document) { + $provide.decorator('$animate', ['$delegate', '$injector', '$sniffer', '$rootElement', '$$asyncQueueBuffer', '$rootScope', '$document', + function($delegate, $injector, $sniffer, $rootElement, $$asyncQueueBuffer, $rootScope, $document) { + var globalAnimationCounter = 0; $rootElement.data(NG_ANIMATE_STATE, rootAnimateState); // disable animations during bootstrap, but once we bootstrapped, wait again @@ -321,10 +345,6 @@ angular.module('ngAnimate', ['ng']) return classNameFilter.test(className); }; - function async(fn) { - return $timeout(fn, 0, false); - } - function lookup(name) { if (name) { var matches = [], @@ -406,6 +426,7 @@ angular.module('ngAnimate', ['ng']) this.enabled(false, element); $delegate.enter(element, parentElement, afterElement); $rootScope.$$postDigest(function() { + element = stripCommentsFromElement(element); performAnimation('enter', 'ng-enter', element, parentElement, afterElement, noop, doneCallback); }); }, @@ -442,6 +463,7 @@ angular.module('ngAnimate', ['ng']) cancelChildAnimations(element); this.enabled(false, element); $rootScope.$$postDigest(function() { + element = stripCommentsFromElement(element); performAnimation('leave', 'ng-leave', element, null, null, function() { $delegate.leave(element); }, doneCallback); @@ -484,6 +506,7 @@ angular.module('ngAnimate', ['ng']) this.enabled(false, element); $delegate.move(element, parentElement, afterElement); $rootScope.$$postDigest(function() { + element = stripCommentsFromElement(element); performAnimation('move', 'ng-move', element, parentElement, afterElement, noop, doneCallback); }); }, @@ -519,6 +542,7 @@ angular.module('ngAnimate', ['ng']) * @param {function()=} doneCallback the callback function that will be called once the animation is complete */ addClass : function(element, className, doneCallback) { + element = stripCommentsFromElement(element); performAnimation('addClass', className, element, null, null, function() { $delegate.addClass(element, className); }, doneCallback); @@ -555,11 +579,34 @@ angular.module('ngAnimate', ['ng']) * @param {function()=} doneCallback the callback function that will be called once the animation is complete */ removeClass : function(element, className, doneCallback) { + element = stripCommentsFromElement(element); performAnimation('removeClass', className, element, null, null, function() { $delegate.removeClass(element, className); }, doneCallback); }, + /** + * + * @ngdoc function + * @name ng.$animate#setClass + * @methodOf ng.$animate + * @function + * @description Adds and/or removes the given CSS classes to and from the element. + * Once complete, the done() callback will be fired (if provided). + * @param {jQuery/jqLite element} element the element which will it's CSS classes changed + * removed from it + * @param {string} add the CSS classes which will be added to the element + * @param {string} remove the CSS class which will be removed from the element + * @param {function=} done the callback function (if provided) that will be fired after the + * CSS classes have been set on the element + */ + setClass : function(element, add, remove, doneCallback) { + element = stripCommentsFromElement(element); + performAnimation('setClass', [add, remove], element, null, null, function() { + $delegate.setClass(element, add, remove); + }, doneCallback); + }, + /** * @ngdoc function * @name ngAnimate.$animate#enabled @@ -606,7 +653,15 @@ angular.module('ngAnimate', ['ng']) and the onComplete callback will be fired once the animation is fully complete. */ function performAnimation(animationEvent, className, element, parentElement, afterElement, domOperation, doneCallback) { - var currentClassName, classes, node = extractElementNode(element); + + var classNameAdd, classNameRemove, setClassOperation = animationEvent == 'setClass'; + if(setClassOperation) { + classNameAdd = className[0]; + classNameRemove = className[1]; + className = classNameAdd + ' ' + classNameRemove; + } + + var currentClassName, classes, node = element[0]; if(node) { currentClassName = node.className; classes = currentClassName + ' ' + className; @@ -618,18 +673,27 @@ angular.module('ngAnimate', ['ng']) fireDOMOperation(); fireBeforeCallbackAsync(); fireAfterCallbackAsync(); - closeAnimation(); + fireDoneCallbackAsync(); return; } + var elementEvents = angular.element._data(node); + elementEvents = elementEvents && elementEvents.events; + var animationLookup = (' ' + classes).replace(/\s+/g,'.'); if (!parentElement) { parentElement = afterElement ? afterElement.parent() : element.parent(); } - var matches = lookup(animationLookup); - var isClassBased = animationEvent == 'addClass' || animationEvent == 'removeClass'; - var ngAnimateState = element.data(NG_ANIMATE_STATE) || {}; + var matches = lookup(animationLookup); + var isClassBased = animationEvent == 'addClass' || + animationEvent == 'removeClass' || + setClassOperation; + var ngAnimateState = element.data(NG_ANIMATE_STATE) || {}; + + var runningAnimations = ngAnimateState.active || {}; + var totalActiveAnimations = ngAnimateState.totalActive || 0; + var lastAnimation = ngAnimateState.last; //skip the animation if animations are disabled, a parent is already being animated, //the element is not currently attached to the document body or then completely close @@ -648,7 +712,7 @@ angular.module('ngAnimate', ['ng']) //only add animations if the currently running animation is not structural //or if there is no animation running at all var allowAnimations = isClassBased ? - !ngAnimateState.disabled && (!ngAnimateState.running || !ngAnimateState.structural) : + !ngAnimateState.disabled && (!lastAnimation || lastAnimation.classBased) : true; if(allowAnimations) { @@ -683,55 +747,48 @@ angular.module('ngAnimate', ['ng']) 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 = 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 - $timeout.cancel(ngAnimateState.closeAnimationTimeout); - 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 || isRevertingClassAnimation) { - (ngAnimateState.done || noop)(true); - } 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 - //be performed only after the reflow is complete then our element's className value - //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(ONE_SPACE + ngAnimateState.className + ONE_SPACE, ONE_SPACE) : - futureClassName + ngAnimateState.className + ONE_SPACE; + var skipAnimation = false; + if(totalActiveAnimations > 0) { + var animationsToCancel = []; + if(!isClassBased) { + if(animationEvent == 'leave' && runningAnimations['ng-leave']) { + skipAnimation = true; + } else { + //cancel all animations when a structural animation takes place + for(var klass in runningAnimations) { + animationsToCancel.push(runningAnimations[klass]); + cleanup(element, klass); + } + runningAnimations = {}; + totalActiveAnimations = 0; + } + } else if(lastAnimation.event == 'setClass') { + animationsToCancel.push(lastAnimation); + cleanup(element, className); + } + else if(runningAnimations[className]) { + var current = runningAnimations[className]; + if(current.event == animationEvent) { + skipAnimation = true; + } else { + animationsToCancel.push(current); + cleanup(element, className); + } + } + + if(animationsToCancel.length > 0) { + angular.forEach(animationsToCancel, function(operation) { + (operation.done || noop)(true); + cancelAnimations(operation.animations); + }); } } - //There is no point in perform a class-based animation if the element already contains - //(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 = ONE_SPACE + className + ONE_SPACE; - if((animationEvent == 'addClass' && futureClassName.indexOf(classNameToken) >= 0) || - (animationEvent == 'removeClass' && futureClassName.indexOf(classNameToken) == -1)) { - fireDOMOperation(); + if(isClassBased && !setClassOperation && !skipAnimation) { + skipAnimation = (animationEvent == 'addClass') == element.hasClass(className); //opposite of XOR + } + + if(skipAnimation) { fireBeforeCallbackAsync(); fireAfterCallbackAsync(); fireDoneCallbackAsync(); @@ -742,13 +799,22 @@ angular.module('ngAnimate', ['ng']) //parent animations to find and cancel child animations when needed element.addClass(NG_ANIMATE_CLASS_NAME); - element.data(NG_ANIMATE_STATE, { - running:true, - event:animationEvent, - className:className, - structural:!isClassBased, - animations:animations, + var localAnimationCount = globalAnimationCounter++; + lastAnimation = { + classBased : isClassBased, + event : animationEvent, + animations : animations, done:onBeforeAnimationsComplete + }; + + totalActiveAnimations++; + runningAnimations[className] = lastAnimation; + + element.data(NG_ANIMATE_STATE, { + last : lastAnimation, + active : runningAnimations, + index : localAnimationCount, + totalActive : totalActiveAnimations }); //first we run the before animations and when all of those are complete @@ -756,6 +822,11 @@ angular.module('ngAnimate', ['ng']) invokeRegisteredAnimationFns(animations, 'before', onBeforeAnimationsComplete); function onBeforeAnimationsComplete(cancelled) { + var data = element.data(NG_ANIMATE_STATE); + cancelled = cancelled || + !data || !data.active[className] || + (isClassBased && data.active[className].event != animationEvent); + fireDOMOperation(); if(cancelled === true) { closeAnimation(); @@ -765,11 +836,8 @@ angular.module('ngAnimate', ['ng']) //set the done function to the final done function //so that the DOM event won't be executed twice by accident //if the after animation is cancelled as well - var data = element.data(NG_ANIMATE_STATE); - if(data) { - data.done = closeAnimation; - element.data(NG_ANIMATE_STATE, data); - } + var currentAnimation = data.active[className]; + currentAnimation.done = closeAnimation; invokeRegisteredAnimationFns(animations, 'after', closeAnimation); } @@ -792,9 +860,13 @@ angular.module('ngAnimate', ['ng']) } if(animation[phase]) { - animation[endFnName] = isClassBased ? - animation[phase](element, className, animationPhaseCompleted) : - animation[phase](element, animationPhaseCompleted); + if(setClassOperation) { + animation[endFnName] = animation[phase](element, classNameAdd, classNameRemove, animationPhaseCompleted); + } else { + animation[endFnName] = isClassBased ? + animation[phase](element, className, animationPhaseCompleted) : + animation[phase](element, animationPhaseCompleted); + } } else { animationPhaseCompleted(); } @@ -815,29 +887,32 @@ angular.module('ngAnimate', ['ng']) } function fireDOMCallback(animationPhase) { - element.triggerHandler('$animate:' + animationPhase, { - event : animationEvent, - className : className - }); + var eventName = '$animate:' + animationPhase; + if(elementEvents && elementEvents[eventName] && elementEvents[eventName].length > 0) { + $$asyncQueueBuffer(function() { + element.triggerHandler(eventName, { + event : animationEvent, + className : className + }); + }); + } } function fireBeforeCallbackAsync() { - async(function() { - fireDOMCallback('before'); - }); + fireDOMCallback('before'); } function fireAfterCallbackAsync() { - async(function() { - fireDOMCallback('after'); - }); + fireDOMCallback('after'); } function fireDoneCallbackAsync() { - async(function() { - fireDOMCallback('close'); - doneCallback && doneCallback(); - }); + fireDOMCallback('close'); + if(doneCallback) { + $$asyncQueueBuffer(function() { + doneCallback(); + }); + } } //it is less complicated to use a flag than managing and cancelling @@ -859,10 +934,13 @@ angular.module('ngAnimate', ['ng']) failing would be when a parent HTML tag has a ng-class attribute causing ALL directives below to skip animations during the digest */ if(isClassBased) { - cleanup(element); + cleanup(element, className); } else { - data.closeAnimationTimeout = async(function() { - cleanup(element); + $$asyncQueueBuffer(function() { + var data = element.data(NG_ANIMATE_STATE) || {}; + if(localAnimationCount == data.index) { + cleanup(element, className, animationEvent); + } }); element.data(NG_ANIMATE_STATE, data); } @@ -877,9 +955,11 @@ angular.module('ngAnimate', ['ng']) forEach(node.querySelectorAll('.' + NG_ANIMATE_CLASS_NAME), function(element) { element = angular.element(element); var data = element.data(NG_ANIMATE_STATE); - if(data) { - cancelAnimations(data.animations); - cleanup(element); + if(data && data.active) { + angular.forEach(data.active, function(operation) { + (operation.done || noop)(true); + cancelAnimations(operation.animations); + }); } }); } @@ -896,15 +976,27 @@ angular.module('ngAnimate', ['ng']) }); } - function cleanup(element) { + function cleanup(element, className) { if(isMatchingElement(element, $rootElement)) { if(!rootAnimateState.disabled) { rootAnimateState.running = false; rootAnimateState.structural = false; } - } else { - element.removeClass(NG_ANIMATE_CLASS_NAME); - element.removeData(NG_ANIMATE_STATE); + } else if(className) { + var data = element.data(NG_ANIMATE_STATE) || {}; + + var removeAnimations = className === true; + if(!removeAnimations) { + if(data.active && data.active[className]) { + data.totalActive--; + delete data.active[className]; + } + } + + if(removeAnimations || !data.totalActive) { + element.removeClass(NG_ANIMATE_CLASS_NAME); + element.removeData(NG_ANIMATE_STATE); + } } } @@ -923,7 +1015,7 @@ angular.module('ngAnimate', ['ng']) var isRoot = isMatchingElement(parentElement, $rootElement); var state = isRoot ? rootAnimateState : parentElement.data(NG_ANIMATE_STATE); - var result = state && (!!state.disabled || !!state.running); + var result = state && (!!state.disabled || state.running || state.totalActive > 0); if(isRoot || result) { return result; } @@ -973,74 +1065,57 @@ angular.module('ngAnimate', ['ng']) var ANIMATION_ITERATION_COUNT_KEY = 'IterationCount'; var NG_ANIMATE_PARENT_KEY = '$$ngAnimateKey'; var NG_ANIMATE_CSS_DATA_KEY = '$$ngAnimateCSS3Data'; + var NG_ANIMATE_BLOCK_CLASS_NAME = 'ng-animate-block-transitions'; var ELAPSED_TIME_MAX_DECIMAL_PLACES = 3; var CLOSING_TIME_BUFFER = 1.5; var ONE_SECOND = 1000; - var animationCounter = 0; var lookupCache = {}; var parentCounter = 0; var animationReflowQueue = []; - var animationElementQueue = []; var cancelAnimationReflow; - var closingAnimationTime = 0; - var timeOut = false; function afterReflow(element, callback) { if(cancelAnimationReflow) { cancelAnimationReflow(); } - animationReflowQueue.push(callback); - - var node = extractElementNode(element); - element = angular.element(node); - animationElementQueue.push(element); - - var elementData = element.data(NG_ANIMATE_CSS_DATA_KEY); - - 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; - cancelAnimationReflow = $$animateReflow(function() { forEach(animationReflowQueue, function(fn) { fn(); }); - //copy the list of elements so that successive - //animations won't conflict if they're added before - //the closing animation timeout has run - var elementQueueSnapshot = []; - var animationCounterSnapshot = animationCounter; - forEach(animationElementQueue, function(elm) { - elementQueueSnapshot.push(elm); - }); - - $timeout(function() { - closeAllAnimations(elementQueueSnapshot, animationCounterSnapshot); - elementQueueSnapshot = null; - }, closingAnimationTime, false); - animationReflowQueue = []; - animationElementQueue = []; cancelAnimationReflow = null; lookupCache = {}; - closingAnimationTime = 0; - animationCounter++; }); } - function closeAllAnimations(elements, count) { + var closingTimer = null; + var closingTimestamp = 0; + var animationElementQueue = []; + function animationCloseHandler(element, totalTime) { + var futureTimestamp = Date.now() + (totalTime * 1000); + if(futureTimestamp <= closingTimestamp) { + return; + } + + $timeout.cancel(closingTimer); + + var node = extractElementNode(element); + element = angular.element(node); + animationElementQueue.push(element); + + closingTimestamp = futureTimestamp; + closingTimer = $timeout(function() { + closeAllAnimations(animationElementQueue); + animationElementQueue = []; + }, totalTime, false); + } + + function closeAllAnimations(elements) { forEach(elements, function(element) { var elementData = element.data(NG_ANIMATE_CSS_DATA_KEY); - if(elementData && elementData.animationCount == count) { + if(elementData) { (elementData.closeAnimationFn || noop)(); } }); @@ -1125,12 +1200,12 @@ angular.module('ngAnimate', ['ng']) return parentID + '-' + extractElementNode(element).className; } - function animateSetup(element, className, calculationDecorator) { + function animateSetup(animationEvent, element, className, calculationDecorator) { var cacheKey = getCacheKey(element); var eventCacheKey = cacheKey + ' ' + className; - var stagger = {}; var itemIndex = lookupCache[eventCacheKey] ? ++lookupCache[eventCacheKey].total : 0; + var stagger = {}; if(itemIndex > 0) { var staggerClassName = className + '-stagger'; var staggerCacheKey = cacheKey + ' ' + staggerClassName; @@ -1150,60 +1225,63 @@ angular.module('ngAnimate', ['ng']) element.addClass(className); + var formerData = element.data(NG_ANIMATE_CSS_DATA_KEY) || {}; + 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 - in the page. There is also no point in performing an animation - that only has a delay and no duration */ - var maxDelay = Math.max(timings.transitionDelay, timings.animationDelay); - var maxDuration = Math.max(timings.transitionDuration, timings.animationDuration); - if(maxDuration === 0) { + var transitionDuration = timings.transitionDuration; + var animationDuration = timings.animationDuration; + if(transitionDuration === 0 && animationDuration === 0) { element.removeClass(className); return false; } - //temporarily disable the transition so that the enter styles - //don't animate twice (this is here to avoid a bug in Chrome/FF). - var activeClassName = ''; - timings.transitionDuration > 0 ? - blockTransitions(element) : - blockKeyframeAnimations(element); - - forEach(className.split(' '), function(klass, i) { - activeClassName += (i > 0 ? ' ' : '') + klass + '-active'; - }); - element.data(NG_ANIMATE_CSS_DATA_KEY, { - className : className, - activeClassName : activeClassName, - maxDuration : maxDuration, - maxDelay : maxDelay, - classes : className + ' ' + activeClassName, - timings : timings, + running : formerData.running || 0, + itemIndex : itemIndex, stagger : stagger, - itemIndex : itemIndex + timings : timings, + closeAnimationFn : angular.noop }); + //temporarily disable the transition so that the enter styles + //don't animate twice (this is here to avoid a bug in Chrome/FF). + var isCurrentlyAnimating = formerData.running > 0 || animationEvent == 'setClass'; + if(transitionDuration > 0) { + blockTransitions(element, className, isCurrentlyAnimating); + } + if(animationDuration > 0) { + blockKeyframeAnimations(element); + } + return true; } - function blockTransitions(element) { - extractElementNode(element).style[TRANSITION_PROP + PROPERTY_KEY] = 'none'; + function isStructuralAnimation(className) { + return className == 'ng-enter' || className == 'ng-move' || className == 'ng-leave'; + } + + function blockTransitions(element, className, isAnimating) { + if(isStructuralAnimation(className) || !isAnimating) { + extractElementNode(element).style[TRANSITION_PROP + PROPERTY_KEY] = 'none'; + } else { + element.addClass(NG_ANIMATE_BLOCK_CLASS_NAME); + } } function blockKeyframeAnimations(element) { extractElementNode(element).style[ANIMATION_PROP] = 'none 0s'; } - function unblockTransitions(element) { + function unblockTransitions(element, className) { var prop = TRANSITION_PROP + PROPERTY_KEY; var node = extractElementNode(element); if(node.style[prop] && node.style[prop].length > 0) { node.style[prop] = ''; } + element.removeClass(NG_ANIMATE_BLOCK_CLASS_NAME); } function unblockKeyframeAnimations(element) { @@ -1214,22 +1292,28 @@ angular.module('ngAnimate', ['ng']) } } - function animateRun(element, className, activeAnimationComplete) { - var elementData = element.data(NG_ANIMATE_CSS_DATA_KEY); + function animateRun(animationEvent, element, className, activeAnimationComplete) { var node = extractElementNode(element); + var elementData = element.data(NG_ANIMATE_CSS_DATA_KEY); if(node.className.indexOf(className) == -1 || !elementData) { activeAnimationComplete(); return; } - var timings = elementData.timings; + var activeClassName = ''; + forEach(className.split(' '), function(klass, i) { + activeClassName += (i > 0 ? ' ' : '') + klass + '-active'; + }); + var stagger = elementData.stagger; - var maxDuration = elementData.maxDuration; - var activeClassName = elementData.activeClassName; - var maxDelayTime = Math.max(timings.transitionDelay, timings.animationDelay) * ONE_SECOND; + var timings = elementData.timings; + var itemIndex = elementData.itemIndex; + var maxDuration = Math.max(timings.transitionDuration, timings.animationDuration); + var maxDelay = Math.max(timings.transitionDelay, timings.animationDelay); + var maxDelayTime = maxDelay * ONE_SECOND; + var startTime = Date.now(); var css3AnimationEvents = ANIMATIONEND_EVENT + ' ' + TRANSITIONEND_EVENT; - var itemIndex = elementData.itemIndex; var style = '', appliedStyles = []; if(timings.transitionDuration > 0) { @@ -1271,6 +1355,13 @@ angular.module('ngAnimate', ['ng']) onEnd(); activeAnimationComplete(); }; + + var staggerTime = itemIndex * (Math.max(stagger.animationDelay, stagger.transitionDelay) || 0); + var animationTime = (maxDelay + maxDuration) * CLOSING_TIME_BUFFER; + var totalTime = (staggerTime + animationTime) * ONE_SECOND; + + elementData.running++; + animationCloseHandler(element, totalTime); return onEnd; // This will automatically be called by $animate so @@ -1290,7 +1381,7 @@ angular.module('ngAnimate', ['ng']) event.stopPropagation(); var ev = event.originalEvent || event; var timeStamp = ev.$manualTimeStamp || ev.timeStamp || Date.now(); - + /* Firefox (or possibly just Gecko) likes to not round values up * when a ms measurement is used for the animation */ var elapsedTime = parseFloat(ev.elapsedTime.toFixed(ELAPSED_TIME_MAX_DECIMAL_PLACES)); @@ -1317,28 +1408,28 @@ angular.module('ngAnimate', ['ng']) return style; } - function animateBefore(element, className, calculationDecorator) { - if(animateSetup(element, className, calculationDecorator)) { + function animateBefore(animationEvent, element, className, calculationDecorator) { + if(animateSetup(animationEvent, element, className, calculationDecorator)) { return function(cancelled) { cancelled && animateClose(element, className); }; } } - function animateAfter(element, className, afterAnimationComplete) { + function animateAfter(animationEvent, element, className, afterAnimationComplete) { if(element.data(NG_ANIMATE_CSS_DATA_KEY)) { - return animateRun(element, className, afterAnimationComplete); + return animateRun(animationEvent, element, className, afterAnimationComplete); } else { animateClose(element, className); afterAnimationComplete(); } } - function animate(element, className, animationComplete) { + function animate(animationEvent, element, className, animationComplete) { //If the animateSetup function doesn't bother returning a //cancellation function then it means that there is no animation //to perform at all - var preReflowCancellation = animateBefore(element, className); + var preReflowCancellation = animateBefore(animationEvent, element, className); if(!preReflowCancellation) { animationComplete(); return; @@ -1351,12 +1442,12 @@ angular.module('ngAnimate', ['ng']) //happen in the first place var cancel = preReflowCancellation; afterReflow(element, function() { - unblockTransitions(element); + unblockTransitions(element, className); unblockKeyframeAnimations(element); //once the reflow is complete then we point cancel to //the new cancellation function which will remove all of the //animation properties from the active animation - cancel = animateAfter(element, className, animationComplete); + cancel = animateAfter(animationEvent, element, className, animationComplete); }); return function(cancelled) { @@ -1366,54 +1457,59 @@ angular.module('ngAnimate', ['ng']) function animateClose(element, className) { element.removeClass(className); - element.removeData(NG_ANIMATE_CSS_DATA_KEY); + var data = element.data(NG_ANIMATE_CSS_DATA_KEY); + if(data) { + if(data.running) { + data.running--; + } + if(!data.running || data.running === 0) { + element.removeData(NG_ANIMATE_CSS_DATA_KEY); + } + } } return { - allowCancel : function(element, animationEvent, className) { - //always cancel the current animation if it is a - //structural animation - var oldClasses = (element.data(NG_ANIMATE_CSS_DATA_KEY) || {}).classes; - if(!oldClasses || ['enter','leave','move'].indexOf(animationEvent) >= 0) { - return true; - } - - var parentElement = element.parent(); - var clone = angular.element(extractElementNode(element).cloneNode()); - - //make the element super hidden and override any CSS style values - clone.attr('style','position:absolute; top:-9999px; left:-9999px'); - clone.removeAttr('id'); - clone.empty(); - - forEach(oldClasses.split(' '), function(klass) { - clone.removeClass(klass); - }); - - var suffix = animationEvent == 'addClass' ? '-add' : '-remove'; - clone.addClass(suffixClasses(className, suffix)); - parentElement.append(clone); - - var timings = getElementAnimationDetails(clone); - clone.remove(); - - return Math.max(timings.transitionDuration, timings.animationDuration) > 0; - }, - enter : function(element, animationCompleted) { - return animate(element, 'ng-enter', animationCompleted); + return animate('enter', element, 'ng-enter', animationCompleted); }, leave : function(element, animationCompleted) { - return animate(element, 'ng-leave', animationCompleted); + return animate('leave', element, 'ng-leave', animationCompleted); }, move : function(element, animationCompleted) { - return animate(element, 'ng-move', animationCompleted); + return animate('move', element, 'ng-move', animationCompleted); + }, + + beforeSetClass : function(element, add, remove, animationCompleted) { + var className = suffixClasses(remove, '-remove') + ' ' + + suffixClasses(add, '-add'); + var cancellationMethod = animateBefore('setClass', element, className, 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(remove); + element.addClass(add); + var timings = fn(); + element.attr('class', klass); + return timings; + }); + + if(cancellationMethod) { + afterReflow(element, function() { + unblockTransitions(element, className); + unblockKeyframeAnimations(element); + animationCompleted(); + }); + return cancellationMethod; + } + animationCompleted(); }, beforeAddClass : function(element, className, animationCompleted) { - var cancellationMethod = animateBefore(element, suffixClasses(className, '-add'), function(fn) { + var cancellationMethod = animateBefore('addClass', 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 @@ -1427,7 +1523,7 @@ angular.module('ngAnimate', ['ng']) if(cancellationMethod) { afterReflow(element, function() { - unblockTransitions(element); + unblockTransitions(element, className); unblockKeyframeAnimations(element); animationCompleted(); }); @@ -1436,12 +1532,19 @@ angular.module('ngAnimate', ['ng']) animationCompleted(); }, + setClass : function(element, add, remove, animationCompleted) { + remove = suffixClasses(remove, '-remove'); + add = suffixClasses(add, '-add'); + var className = remove + ' ' + add; + return animateAfter('setClass', element, className, animationCompleted); + }, + addClass : function(element, className, animationCompleted) { - return animateAfter(element, suffixClasses(className, '-add'), animationCompleted); + return animateAfter('addClass', element, suffixClasses(className, '-add'), animationCompleted); }, beforeRemoveClass : function(element, className, animationCompleted) { - var cancellationMethod = animateBefore(element, suffixClasses(className, '-remove'), function(fn) { + var cancellationMethod = animateBefore('removeClass', 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. @@ -1455,7 +1558,7 @@ angular.module('ngAnimate', ['ng']) if(cancellationMethod) { afterReflow(element, function() { - unblockTransitions(element); + unblockTransitions(element, className); unblockKeyframeAnimations(element); animationCompleted(); }); @@ -1465,7 +1568,7 @@ angular.module('ngAnimate', ['ng']) }, removeClass : function(element, className, animationCompleted) { - return animateAfter(element, suffixClasses(className, '-remove'), animationCompleted); + return animateAfter('removeClass', element, suffixClasses(className, '-remove'), animationCompleted); } }; diff --git a/config/lib/js/angular/angular-animate.min.js b/config/lib/js/angular/angular-animate.min.js index 4f66338a702..45028654106 100755 --- a/config/lib/js/angular/angular-animate.min.js +++ b/config/lib/js/angular/angular-animate.min.js @@ -1,25 +1,27 @@ /* - AngularJS v1.2.10 + AngularJS v1.2.13 (c) 2010-2014 Google, Inc. http://angularjs.org License: MIT */ -(function(v,k,t){'use strict';k.module("ngAnimate",["ng"]).factory("$$animateReflow",["$window","$timeout",function(k,B){var d=k.requestAnimationFrame||k.webkitRequestAnimationFrame||function(d){return B(d,10,!1)},q=k.cancelAnimationFrame||k.webkitCancelAnimationFrame||function(d){return B.cancel(d)};return function(p){var k=d(p);return function(){q(k)}}}]).config(["$provide","$animateProvider",function(R,B){function d(d){for(var k=0;k=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= +u&&a>=s&&e()}var h=d(a);b=a.data(E);if(-1!=h.className.indexOf(c)&&b){var l="";D(c.split(" "),function(b,a){l+=(0 // The controller code @@ -1032,7 +1003,7 @@ angular.mock.dump = function(object) { } * - * Now we setup the mock backend and create the test specs. + * Now we setup the mock backend and create the test specs: *
     // testing controller
@@ -1954,7 +1925,7 @@ if(window.jasmine || window.mocha) {
 
   var currentSpec = null,
       isSpecRunning = function() {
-        return currentSpec && (window.mocha || currentSpec.queue.running);
+        return !!currentSpec;
       };
 
 
@@ -2132,7 +2103,7 @@ if(window.jasmine || window.mocha) {
   window.inject = angular.mock.inject = function() {
     var blockFns = Array.prototype.slice.call(arguments, 0);
     var errorForStack = new Error('Declaration Location');
-    return isSpecRunning() ? workFn() : workFn;
+    return isSpecRunning() ? workFn.call(currentSpec) : workFn;
     /////////////////////
     function workFn() {
       var modules = currentSpec.$modules || [];
diff --git a/config/lib/js/angular/angular-resource.js b/config/lib/js/angular/angular-resource.js
old mode 100644
new mode 100755
index 38bebab22c5..36b34b48453
--- a/config/lib/js/angular/angular-resource.js
+++ b/config/lib/js/angular/angular-resource.js
@@ -1,5 +1,5 @@
 /**
- * @license AngularJS v1.2.10
+ * @license AngularJS v1.2.13
  * (c) 2010-2014 Google, Inc. http://angularjs.org
  * License: MIT
  */
@@ -40,7 +40,7 @@ function shallowClearAndCopy(src, dst) {
   });
 
   for (var key in src) {
-    if (src.hasOwnProperty(key) && key.charAt(0) !== '$' && key.charAt(1) !== '$') {
+    if (src.hasOwnProperty(key) && !(key.charAt(0) === '$' && key.charAt(1) === '$')) {
       dst[key] = src[key];
     }
   }
@@ -392,7 +392,9 @@ angular.module('ngResource', ['ng']).
           val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam];
           if (angular.isDefined(val) && val !== null) {
             encodedVal = encodeUriSegment(val);
-            url = url.replace(new RegExp(":" + urlParam + "(\\W|$)", "g"), encodedVal + "$1");
+            url = url.replace(new RegExp(":" + urlParam + "(\\W|$)", "g"), function(match, p1) {
+              return encodedVal + p1;
+            });
           } else {
             url = url.replace(new RegExp("(\/?):" + urlParam + "(\\W|$)", "g"), function(match,
                 leadingSlashes, tail) {
diff --git a/config/lib/js/angular/angular-resource.min.js b/config/lib/js/angular/angular-resource.min.js
old mode 100644
new mode 100755
index 9df2b8309fb..3496cfcf458
--- a/config/lib/js/angular/angular-resource.min.js
+++ b/config/lib/js/angular/angular-resource.min.js
@@ -1,13 +1,13 @@
 /*
- AngularJS v1.2.10
+ AngularJS v1.2.13
  (c) 2010-2014 Google, Inc. http://angularjs.org
  License: MIT
 */
-(function(H,a,A){'use strict';function D(p,g){g=g||{};a.forEach(g,function(a,c){delete g[c]});for(var c in p)p.hasOwnProperty(c)&&("$"!==c.charAt(0)&&"$"!==c.charAt(1))&&(g[c]=p[c]);return g}var v=a.$$minErr("$resource"),C=/^(\.[a-zA-Z_$][0-9a-zA-Z_$]*)+$/;a.module("ngResource",["ng"]).factory("$resource",["$http","$q",function(p,g){function c(a,c){this.template=a;this.defaults=c||{};this.urlParams={}}function t(n,w,l){function r(h,d){var e={};d=x({},w,d);s(d,function(b,d){u(b)&&(b=b());var k;if(b&&
+(function(H,a,A){'use strict';function D(p,g){g=g||{};a.forEach(g,function(a,c){delete g[c]});for(var c in p)!p.hasOwnProperty(c)||"$"===c.charAt(0)&&"$"===c.charAt(1)||(g[c]=p[c]);return g}var v=a.$$minErr("$resource"),C=/^(\.[a-zA-Z_$][0-9a-zA-Z_$]*)+$/;a.module("ngResource",["ng"]).factory("$resource",["$http","$q",function(p,g){function c(a,c){this.template=a;this.defaults=c||{};this.urlParams={}}function t(n,w,l){function r(h,d){var e={};d=x({},w,d);s(d,function(b,d){u(b)&&(b=b());var k;if(b&&
 b.charAt&&"@"==b.charAt(0)){k=h;var a=b.substr(1);if(null==a||""===a||"hasOwnProperty"===a||!C.test("."+a))throw v("badmember",a);for(var a=a.split("."),f=0,c=a.length;f
- *
- * See {@link ngSanitize.$sanitize `$sanitize`} for usage.
- */
-
-/*
- * HTML Parser By Misko Hevery (misko@hevery.com)
- * based on:  HTML Parser By John Resig (ejohn.org)
- * Original code by Erik Arvidsson, Mozilla Public License
- * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js
- *
- * // Use like so:
- * htmlParser(htmlString, {
- *     start: function(tag, attrs, unary) {},
- *     end: function(tag) {},
- *     chars: function(text) {},
- *     comment: function(text) {}
- * });
- *
- */
-
-
-/**
- * @ngdoc service
- * @name ngSanitize.$sanitize
- * @function
- *
- * @description
- *   The input is sanitized by parsing the html into tokens. All safe tokens (from a whitelist) are
- *   then serialized back to properly escaped html string. This means that no unsafe input can make
- *   it into the returned string, however, since our parser is more strict than a typical browser
- *   parser, it's possible that some obscure input, which would be recognized as valid HTML by a
- *   browser, won't make it through the sanitizer.
- *   The whitelist is configured using the functions `aHrefSanitizationWhitelist` and
- *   `imgSrcSanitizationWhitelist` of {@link ng.$compileProvider `$compileProvider`}.
- *
- * @param {string} html Html input.
- * @returns {string} Sanitized html.
- *
- * @example
-   
-   
-     
-     
- Snippet: - - - - - - - - - - - - - - - - - - - - - - - - - -
DirectiveHowSourceRendered
ng-bind-htmlAutomatically uses $sanitize
<div ng-bind-html="snippet">
</div>
ng-bind-htmlBypass $sanitize by explicitly trusting the dangerous value -
<div ng-bind-html="deliberatelyTrustDangerousSnippet()">
-</div>
-
ng-bindAutomatically escapes
<div ng-bind="snippet">
</div>
-
-
- - it('should sanitize the html snippet by default', function() { - expect(using('#bind-html-with-sanitize').element('div').html()). - toBe('

an html\nclick here\nsnippet

'); - }); - - it('should inline raw snippet if bound to a trusted value', function() { - expect(using('#bind-html-with-trust').element("div").html()). - toBe("

an html\n" + - "click here\n" + - "snippet

"); - }); - - it('should escape snippet without any filter', function() { - expect(using('#bind-default').element('div').html()). - toBe("<p style=\"color:blue\">an html\n" + - "<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" + - "snippet</p>"); - }); - - it('should update', function() { - input('snippet').enter('new text'); - expect(using('#bind-html-with-sanitize').element('div').html()).toBe('new text'); - expect(using('#bind-html-with-trust').element('div').html()).toBe( - 'new text'); - expect(using('#bind-default').element('div').html()).toBe( - "new <b onclick=\"alert(1)\">text</b>"); - }); -
-
- */ -function $SanitizeProvider() { - this.$get = ['$$sanitizeUri', function($$sanitizeUri) { - return function(html) { - var buf = []; - htmlParser(html, htmlSanitizeWriter(buf, function(uri, isImage) { - return !/^unsafe/.test($$sanitizeUri(uri, isImage)); - })); - return buf.join(''); - }; - }]; -} - -function sanitizeText(chars) { - var buf = []; - var writer = htmlSanitizeWriter(buf, angular.noop); - writer.chars(chars); - return buf.join(''); -} - - -// Regular Expressions for parsing tags and attributes -var START_TAG_REGEXP = - /^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/, - END_TAG_REGEXP = /^<\s*\/\s*([\w:-]+)[^>]*>/, - ATTR_REGEXP = /([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g, - BEGIN_TAG_REGEXP = /^/g, - DOCTYPE_REGEXP = /]*?)>/i, - CDATA_REGEXP = //g, - // Match everything outside of normal chars and " (quote character) - NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g; - - -// Good source of info about elements and attributes -// http://dev.w3.org/html5/spec/Overview.html#semantics -// http://simon.html5.org/html-elements - -// Safe Void Elements - HTML5 -// http://dev.w3.org/html5/spec/Overview.html#void-elements -var voidElements = makeMap("area,br,col,hr,img,wbr"); - -// Elements that you can, intentionally, leave open (and which close themselves) -// http://dev.w3.org/html5/spec/Overview.html#optional-tags -var optionalEndTagBlockElements = makeMap("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"), - optionalEndTagInlineElements = makeMap("rp,rt"), - optionalEndTagElements = angular.extend({}, - optionalEndTagInlineElements, - optionalEndTagBlockElements); - -// Safe Block Elements - HTML5 -var blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap("address,article," + - "aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5," + - "h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul")); - -// Inline Elements - HTML5 -var inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap("a,abbr,acronym,b," + - "bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s," + - "samp,small,span,strike,strong,sub,sup,time,tt,u,var")); - - -// Special Elements (can contain anything) -var specialElements = makeMap("script,style"); - -var validElements = angular.extend({}, - voidElements, - blockElements, - inlineElements, - optionalEndTagElements); - -//Attributes that have href and hence need to be sanitized -var uriAttrs = makeMap("background,cite,href,longdesc,src,usemap"); -var validAttrs = angular.extend({}, uriAttrs, makeMap( - 'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+ - 'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,'+ - 'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,'+ - 'scope,scrolling,shape,size,span,start,summary,target,title,type,'+ - 'valign,value,vspace,width')); - -function makeMap(str) { - var obj = {}, items = str.split(','), i; - for (i = 0; i < items.length; i++) obj[items[i]] = true; - return obj; -} - - -/** - * @example - * htmlParser(htmlString, { - * start: function(tag, attrs, unary) {}, - * end: function(tag) {}, - * chars: function(text) {}, - * comment: function(text) {} - * }); - * - * @param {string} html string - * @param {object} handler - */ -function htmlParser( html, handler ) { - var index, chars, match, stack = [], last = html; - stack.last = function() { return stack[ stack.length - 1 ]; }; - - while ( html ) { - chars = true; - - // Make sure we're not in a script or style element - if ( !stack.last() || !specialElements[ stack.last() ] ) { - - // Comment - if ( html.indexOf("", index) === index) { - if (handler.comment) handler.comment( html.substring( 4, index ) ); - html = html.substring( index + 3 ); - chars = false; - } - // DOCTYPE - } else if ( DOCTYPE_REGEXP.test(html) ) { - match = html.match( DOCTYPE_REGEXP ); - - if ( match ) { - html = html.replace( match[0] , ''); - chars = false; - } - // end tag - } else if ( BEGING_END_TAGE_REGEXP.test(html) ) { - match = html.match( END_TAG_REGEXP ); - - if ( match ) { - html = html.substring( match[0].length ); - match[0].replace( END_TAG_REGEXP, parseEndTag ); - chars = false; - } - - // start tag - } else if ( BEGIN_TAG_REGEXP.test(html) ) { - match = html.match( START_TAG_REGEXP ); - - if ( match ) { - html = html.substring( match[0].length ); - match[0].replace( START_TAG_REGEXP, parseStartTag ); - chars = false; - } - } - - if ( chars ) { - index = html.indexOf("<"); - - var text = index < 0 ? html : html.substring( 0, index ); - html = index < 0 ? "" : html.substring( index ); - - if (handler.chars) handler.chars( decodeEntities(text) ); - } - - } else { - html = html.replace(new RegExp("(.*)<\\s*\\/\\s*" + stack.last() + "[^>]*>", 'i'), - function(all, text){ - text = text.replace(COMMENT_REGEXP, "$1").replace(CDATA_REGEXP, "$1"); - - if (handler.chars) handler.chars( decodeEntities(text) ); - - return ""; - }); - - parseEndTag( "", stack.last() ); - } - - if ( html == last ) { - throw $sanitizeMinErr('badparse', "The sanitizer was unable to parse the following block " + - "of html: {0}", html); - } - last = html; - } - - // Clean up any remaining tags - parseEndTag(); - - function parseStartTag( tag, tagName, rest, unary ) { - tagName = angular.lowercase(tagName); - if ( blockElements[ tagName ] ) { - while ( stack.last() && inlineElements[ stack.last() ] ) { - parseEndTag( "", stack.last() ); - } - } - - if ( optionalEndTagElements[ tagName ] && stack.last() == tagName ) { - parseEndTag( "", tagName ); - } - - unary = voidElements[ tagName ] || !!unary; - - if ( !unary ) - stack.push( tagName ); - - var attrs = {}; - - rest.replace(ATTR_REGEXP, - function(match, name, doubleQuotedValue, singleQuotedValue, unquotedValue) { - var value = doubleQuotedValue - || singleQuotedValue - || unquotedValue - || ''; - - attrs[name] = decodeEntities(value); - }); - if (handler.start) handler.start( tagName, attrs, unary ); - } - - function parseEndTag( tag, tagName ) { - var pos = 0, i; - tagName = angular.lowercase(tagName); - if ( tagName ) - // Find the closest opened tag of the same type - for ( pos = stack.length - 1; pos >= 0; pos-- ) - if ( stack[ pos ] == tagName ) - break; - - if ( pos >= 0 ) { - // Close all the open elements, up the stack - for ( i = stack.length - 1; i >= pos; i-- ) - if (handler.end) handler.end( stack[ i ] ); - - // Remove the open elements from the stack - stack.length = pos; - } - } -} - -var hiddenPre=document.createElement("pre"); -var spaceRe = /^(\s*)([\s\S]*?)(\s*)$/; -/** - * decodes all entities into regular string - * @param value - * @returns {string} A string with decoded entities. - */ -function decodeEntities(value) { - if (!value) { return ''; } - - // Note: IE8 does not preserve spaces at the start/end of innerHTML - // so we must capture them and reattach them afterward - var parts = spaceRe.exec(value); - var spaceBefore = parts[1]; - var spaceAfter = parts[3]; - var content = parts[2]; - if (content) { - hiddenPre.innerHTML=content.replace(//g, '>'); -} - -/** - * create an HTML/XML writer which writes to buffer - * @param {Array} buf use buf.jain('') to get out sanitized html string - * @returns {object} in the form of { - * start: function(tag, attrs, unary) {}, - * end: function(tag) {}, - * chars: function(text) {}, - * comment: function(text) {} - * } - */ -function htmlSanitizeWriter(buf, uriValidator){ - var ignore = false; - var out = angular.bind(buf, buf.push); - return { - start: function(tag, attrs, unary){ - tag = angular.lowercase(tag); - if (!ignore && specialElements[tag]) { - ignore = tag; - } - if (!ignore && validElements[tag] === true) { - out('<'); - out(tag); - angular.forEach(attrs, function(value, key){ - var lkey=angular.lowercase(key); - var isImage = (tag === 'img' && lkey === 'src') || (lkey === 'background'); - if (validAttrs[lkey] === true && - (uriAttrs[lkey] !== true || uriValidator(value, isImage))) { - out(' '); - out(key); - out('="'); - out(encodeEntities(value)); - out('"'); - } - }); - out(unary ? '/>' : '>'); - } - }, - end: function(tag){ - tag = angular.lowercase(tag); - if (!ignore && validElements[tag] === true) { - out(''); - } - if (tag == ignore) { - ignore = false; - } - }, - chars: function(chars){ - if (!ignore) { - out(encodeEntities(chars)); - } - } - }; -} - - -// define ngSanitize module and register $sanitize service -angular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider); - -/* global sanitizeText: false */ - -/** - * @ngdoc filter - * @name ngSanitize.filter:linky - * @function - * - * @description - * Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and - * plain email address links. - * - * Requires the {@link ngSanitize `ngSanitize`} module to be installed. - * - * @param {string} text Input text. - * @param {string} target Window (_blank|_self|_parent|_top) or named frame to open links in. - * @returns {string} Html-linkified text. - * - * @usage - - * - * @example - - - -
- Snippet: - - - - - - - - - - - - - - - - - - - - - -
FilterSourceRendered
linky filter -
<div ng-bind-html="snippet | linky">
</div>
-
-
-
linky target -
<div ng-bind-html="snippetWithTarget | linky:'_blank'">
</div>
-
-
-
no filter
<div ng-bind="snippet">
</div>
- - - it('should linkify the snippet with urls', function() { - expect(using('#linky-filter').binding('snippet | linky')). - toBe('Pretty text with some links: ' + - 'http://angularjs.org/, ' + - 'us@somewhere.org, ' + - 'another@somewhere.org, ' + - 'and one more: ftp://127.0.0.1/.'); - }); - - it ('should not linkify snippet without the linky filter', function() { - expect(using('#escaped-html').binding('snippet')). - toBe("Pretty text with some links:\n" + - "http://angularjs.org/,\n" + - "mailto:us@somewhere.org,\n" + - "another@somewhere.org,\n" + - "and one more: ftp://127.0.0.1/."); - }); - - it('should update', function() { - input('snippet').enter('new http://link.'); - expect(using('#linky-filter').binding('snippet | linky')). - toBe('new http://link.'); - expect(using('#escaped-html').binding('snippet')).toBe('new http://link.'); - }); - - it('should work with the target property', function() { - expect(using('#linky-target').binding("snippetWithTarget | linky:'_blank'")). - toBe('http://angularjs.org/'); - }); - - - */ -angular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) { - var LINKY_URL_REGEXP = - /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>]/, - MAILTO_REGEXP = /^mailto:/; - - return function(text, target) { - if (!text) return text; - var match; - var raw = text; - var html = []; - var url; - var i; - while ((match = raw.match(LINKY_URL_REGEXP))) { - // We can not end in these as they are sometimes found at the end of the sentence - url = match[0]; - // if we did not match ftp/http/mailto then assume mailto - if (match[2] == match[3]) url = 'mailto:' + url; - i = match.index; - addText(raw.substr(0, i)); - addLink(url, match[0].replace(MAILTO_REGEXP, '')); - raw = raw.substring(i + match[0].length); - } - addText(raw); - return $sanitize(html.join('')); - - function addText(text) { - if (!text) { - return; - } - html.push(sanitizeText(text)); - } - - function addLink(url, text) { - html.push(''); - addText(text); - html.push(''); - } - }; -}]); - - -})(window, window.angular); diff --git a/config/lib/js/angular/angular-sanitize.min.js b/config/lib/js/angular/angular-sanitize.min.js deleted file mode 100755 index 1a98e5a68ae..00000000000 --- a/config/lib/js/angular/angular-sanitize.min.js +++ /dev/null @@ -1,14 +0,0 @@ -/* - AngularJS v1.2.10 - (c) 2010-2014 Google, Inc. http://angularjs.org - License: MIT -*/ -(function(p,h,q){'use strict';function E(a){var e=[];s(e,h.noop).chars(a);return e.join("")}function k(a){var e={};a=a.split(",");var d;for(d=0;d=c;d--)e.end&&e.end(f[d]);f.length=c}}var b,g,f=[],l=a;for(f.last=function(){return f[f.length-1]};a;){g=!0;if(f.last()&&x[f.last()])a=a.replace(RegExp("(.*)<\\s*\\/\\s*"+f.last()+"[^>]*>","i"),function(b,a){a=a.replace(H,"$1").replace(I,"$1");e.chars&&e.chars(r(a));return""}),c("",f.last());else{if(0===a.indexOf("\x3c!--"))b=a.indexOf("--",4),0<=b&&a.lastIndexOf("--\x3e",b)===b&&(e.comment&&e.comment(a.substring(4,b)),a=a.substring(b+3),g=!1);else if(y.test(a)){if(b=a.match(y))a= -a.replace(b[0],""),g=!1}else if(J.test(a)){if(b=a.match(z))a=a.substring(b[0].length),b[0].replace(z,c),g=!1}else K.test(a)&&(b=a.match(A))&&(a=a.substring(b[0].length),b[0].replace(A,d),g=!1);g&&(b=a.indexOf("<"),g=0>b?a:a.substring(0,b),a=0>b?"":a.substring(b),e.chars&&e.chars(r(g)))}if(a==l)throw L("badparse",a);l=a}c()}function r(a){if(!a)return"";var e=M.exec(a);a=e[1];var d=e[3];if(e=e[2])n.innerHTML=e.replace(//g,">")}function s(a,e){var d=!1,c=h.bind(a,a.push);return{start:function(a,g,f){a=h.lowercase(a);!d&&x[a]&&(d=a);d||!0!==C[a]||(c("<"),c(a),h.forEach(g,function(d,f){var g=h.lowercase(f),k="img"===a&&"src"===g||"background"===g;!0!==O[g]||!0===D[g]&&!e(d,k)||(c(" "),c(f),c('="'),c(B(d)),c('"'))}),c(f?"/>":">"))},end:function(a){a=h.lowercase(a);d||!0!==C[a]||(c(""));a==d&&(d=!1)},chars:function(a){d|| -c(B(a))}}}var L=h.$$minErr("$sanitize"),A=/^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/,z=/^<\s*\/\s*([\w:-]+)[^>]*>/,G=/([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,K=/^]*?)>/i,I=/]/,d=/^mailto:/;return function(c,b){function g(a){a&&m.push(E(a))}function f(a,c){m.push("');g(c);m.push("")}if(!c)return c;for(var l,k=c,m=[],n,p;l=k.match(e);)n=l[0],l[2]==l[3]&&(n="mailto:"+n),p=l.index,g(k.substr(0,p)),f(n,l[0].replace(d,"")),k=k.substring(p+l[0].length);g(k);return a(m.join(""))}}])})(window,window.angular); -//# sourceMappingURL=angular-sanitize.min.js.map diff --git a/config/lib/js/angular/angular-scenario.js b/config/lib/js/angular/angular-scenario.js index 2523ef6bd23..752d85efe79 100755 --- a/config/lib/js/angular/angular-scenario.js +++ b/config/lib/js/angular/angular-scenario.js @@ -9790,7 +9790,7 @@ if ( typeof module === "object" && module && typeof module.exports === "object" })( window ); /** - * @license AngularJS v1.2.10 + * @license AngularJS v1.2.13 * (c) 2010-2014 Google, Inc. http://angularjs.org * License: MIT */ @@ -9860,7 +9860,7 @@ function minErr(module) { return match; }); - message = message + '\nhttp://errors.angularjs.org/1.2.10/' + + message = message + '\nhttp://errors.angularjs.org/1.2.13/' + (module ? module + '/' : '') + code; for (i = 2; i < arguments.length; i++) { message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' + @@ -9952,6 +9952,7 @@ function minErr(module) { -assertNotHasOwnProperty, -getter, -getBlockElements, + -hasOwnProperty, */ @@ -9967,7 +9968,7 @@ function minErr(module) { * @returns {string} Lowercased string. */ var lowercase = function(string){return isString(string) ? string.toLowerCase() : string;}; - +var hasOwnProperty = Object.prototype.hasOwnProperty; /** * @ngdoc function @@ -10063,7 +10064,7 @@ function isArrayLike(obj) { * is the value of an object property or an array element and `key` is the object property key or * array element index. Specifying a `context` for the function is optional. * - * It is worth nothing that `.forEach` does not iterate over inherited properties because it filters + * It is worth noting that `.forEach` does not iterate over inherited properties because it filters * using the `hasOwnProperty` method. *
@@ -10072,7 +10073,7 @@ function isArrayLike(obj) {
      angular.forEach(values, function(value, key){
        this.push(key + ': ' + value);
      }, log);
-     expect(log).toEqual(['name: misko', 'gender:male']);
+     expect(log).toEqual(['name: misko', 'gender: male']);
    
* * @param {Object|Array} obj Object to iterate over. @@ -10643,7 +10644,7 @@ function shallowCopy(src, dst) { for(var key in src) { // shallowCopy is only ever called by $compile nodeLinkFn, which has control over src // so we don't need to worry about using our custom hasOwnProperty here - if (src.hasOwnProperty(key) && key.charAt(0) !== '$' && key.charAt(1) !== '$') { + if (src.hasOwnProperty(key) && !(key.charAt(0) === '$' && key.charAt(1) === '$')) { dst[key] = src[key]; } } @@ -11002,6 +11003,7 @@ function encodeUriQuery(val, pctEncodeSpaces) {
I can add: {{a}} + {{b}} = {{ a+b }} +
angular.module('ngAppDemo', []).controller('ngAppDemoController', function($scope) { @@ -11626,11 +11628,11 @@ function setupModuleLoader(window) { * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat". */ var version = { - full: '1.2.10', // all of these placeholder strings will be replaced by grunt's + full: '1.2.13', // all of these placeholder strings will be replaced by grunt's major: 1, // package task minor: 2, - dot: 10, - codeName: 'augmented-serendipity' + dot: 13, + codeName: 'romantic-transclusion' }; @@ -11792,7 +11794,7 @@ function publishExternalAPI(angular){ * - [`after()`](http://api.jquery.com/after/) * - [`append()`](http://api.jquery.com/append/) * - [`attr()`](http://api.jquery.com/attr/) - * - [`bind()`](http://api.jquery.com/on/) - Does not support namespaces, selectors or eventData + * - [`bind()`](http://api.jquery.com/bind/) - Does not support namespaces, selectors or eventData * - [`children()`](http://api.jquery.com/children/) - Does not support selectors * - [`clone()`](http://api.jquery.com/clone/) * - [`contents()`](http://api.jquery.com/contents/) @@ -11819,7 +11821,7 @@ function publishExternalAPI(angular){ * - [`text()`](http://api.jquery.com/text/) * - [`toggleClass()`](http://api.jquery.com/toggleClass/) * - [`triggerHandler()`](http://api.jquery.com/triggerHandler/) - Passes a dummy event object to handlers. - * - [`unbind()`](http://api.jquery.com/off/) - Does not support namespaces + * - [`unbind()`](http://api.jquery.com/unbind/) - Does not support namespaces * - [`val()`](http://api.jquery.com/val/) * - [`wrap()`](http://api.jquery.com/wrap/) * @@ -11859,6 +11861,14 @@ var jqCache = JQLite.cache = {}, ? function(element, type, fn) {element.removeEventListener(type, fn, false); } : function(element, type, fn) {element.detachEvent('on' + type, fn); }); +/* + * !!! This is an undocumented "private" function !!! + */ +var jqData = JQLite._data = function(node) { + //jQuery always returns an object on cache miss + return this.cache[node[this.expando]] || {}; +}; + function jqNextId() { return ++jqId; } @@ -11927,6 +11937,9 @@ function JQLite(element) { if (element instanceof JQLite) { return element; } + if (isString(element)) { + element = trim(element); + } if (!(this instanceof JQLite)) { if (isString(element) && element.charAt(0) != '<') { throw jqLiteMinErr('nosel', 'Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element'); @@ -13200,17 +13213,16 @@ function annotate(fn) { * Here is an example of registering a service using * {@link AUTO.$provide#methods_service $provide.service(class)}. *
- *   $provide.service('ping', ['$http', function($http) {
- *     var Ping = function() {
- *       this.$http = $http;
- *     };
- *   
- *     Ping.prototype.send = function() {
- *       return this.$http.get('/ping');
- *     }; 
+ *   var Ping = function($http) {
+ *     this.$http = $http;
+ *   };
+ * 
+ *   Ping.$inject = ['$http'];
  *   
- *     return Ping;
- *   }]);
+ *   Ping.prototype.send = function() {
+ *     return this.$http.get('/ping');
+ *   };
+ *   $provide.service('ping', Ping);
  * 
* You would then inject and use this service like this: *
@@ -13308,7 +13320,7 @@ function annotate(fn) {
  * Here we decorate the {@link ng.$log $log} service to convert warnings to errors by intercepting
  * calls to {@link ng.$log#error $log.warn()}.
  * 
- *   $provider.decorator('$log', ['$delegate', function($delegate) {
+ *   $provide.decorator('$log', ['$delegate', function($delegate) {
  *     $delegate.warn = $delegate.error;
  *     return $delegate;
  *   }]);
@@ -13847,6 +13859,29 @@ var $AnimateProvider = ['$provide', function($provide) {
         done && $timeout(done, 0, false);
       },
 
+      /**
+       *
+       * @ngdoc function
+       * @name ng.$animate#setClass
+       * @methodOf ng.$animate
+       * @function
+       * @description Adds and/or removes the given CSS classes to and from the element.
+       * Once complete, the done() callback will be fired (if provided).
+       * @param {jQuery/jqLite element} element the element which will it's CSS classes changed
+       *   removed from it
+       * @param {string} add the CSS classes which will be added to the element
+       * @param {string} remove the CSS class which will be removed from the element
+       * @param {function=} done the callback function (if provided) that will be fired after the
+       *   CSS classes have been set on the element
+       */
+      setClass : function(element, add, remove, done) {
+        forEach(element, function (element) {
+          jqLiteAddClass(element, add);
+          jqLiteRemoveClass(element, remove);
+        });
+        done && $timeout(done, 0, false);
+      },
+
       enabled : noop
     };
   }];
@@ -14911,13 +14946,17 @@ function $TemplateCacheProvider() {
       
- + it('should auto compile', function() { - expect(element('div[compile]').text()).toBe('Hello Angular'); - input('html').enter('{{name}}!'); - expect(element('div[compile]').text()).toBe('Angular!'); + var textarea = $('textarea'); + var output = $('div[compile]'); + // The initial state reads 'Hello Angular'. + expect(output.getText()).toBe('Hello Angular'); + textarea.clear(); + textarea.sendKeys('{{name}}!'); + expect(output.getText()).toBe('Angular!'); }); - +
* @@ -14985,7 +15024,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { var hasDirectives = {}, Suffix = 'Directive', COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\d\w\-_]+)\s+(.*)$/, - CLASS_DIRECTIVE_REGEXP = /(([\d\w\-_]+)(?:\:([^;]+))?;?)/; + CLASS_DIRECTIVE_REGEXP = /(([\d\w\-_]+)(?:\:([^;]+))?;?)/, + TABLE_CONTENT_REGEXP = /^<\s*(tr|th|td|tbody)(\s+[^>]*)?>/i; // Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes // The assumption is that future DOM event attribute names will begin with @@ -15172,8 +15212,16 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { * @param {string} oldClasses The former CSS className value */ $updateClass : function(newClasses, oldClasses) { - this.$removeClass(tokenDifference(oldClasses, newClasses)); - this.$addClass(tokenDifference(newClasses, oldClasses)); + var toAdd = tokenDifference(newClasses, oldClasses); + var toRemove = tokenDifference(oldClasses, newClasses); + + if(toAdd.length === 0) { + $animate.removeClass(this.$$element, toRemove); + } else if(toRemove.length === 0) { + $animate.addClass(this.$$element, toAdd); + } else { + $animate.setClass(this.$$element, toAdd, toRemove); + } }, /** @@ -15625,7 +15673,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { templateDirective = previousCompileContext.templateDirective, nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective, hasTranscludeDirective = false, - hasElementTranscludeDirective = false, + hasElementTranscludeDirective = previousCompileContext.hasElementTranscludeDirective, $compileNode = templateAttrs.$$element = jqLite(compileNode), directive, directiveName, @@ -15679,7 +15727,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { hasTranscludeDirective = true; // Special case ngIf and ngRepeat so that we don't complain about duplicate transclusion. - // This option should only be used by directives that know how to how to safely handle element transclusion, + // This option should only be used by directives that know how to safely handle element transclusion, // where the transcluded nodes are added or replaced after linking. if (!directive.$$tlb) { assertNoDuplicate('transclusion', nonTlbTranscludeDirective, directive, $compileNode); @@ -15726,9 +15774,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { if (directive.replace) { replaceDirective = directive; - $template = jqLite('
' + - trim(directiveValue) + - '
').contents(); + $template = directiveTemplateContents(directiveValue); compileNode = $template[0]; if ($template.length != 1 || compileNode.nodeType !== 1) { @@ -15799,6 +15845,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true; nodeLinkFn.transclude = hasTranscludeDirective && childTranscludeFn; + previousCompileContext.hasElementTranscludeDirective = hasElementTranscludeDirective; // might be normal or delayed nodeLinkFn depending on if templateUrl is present return nodeLinkFn; @@ -16126,6 +16173,28 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { } + function directiveTemplateContents(template) { + var type; + template = trim(template); + if ((type = TABLE_CONTENT_REGEXP.exec(template))) { + type = type[1].toLowerCase(); + var table = jqLite('' + template + '
'), + tbody = table.children('tbody'), + leaf = /(td|th)/.test(type) && table.find('tr'); + if (tbody.length && type !== 'tbody') { + table = tbody; + } + if (leaf && leaf.length) { + table = leaf; + } + return table.contents(); + } + return jqLite('
' + + template + + '
').contents(); + } + + function compileTemplateUrl(directives, $compileNode, tAttrs, $rootElement, childTranscludeFn, preLinkFns, postLinkFns, previousCompileContext) { var linkQueue = [], @@ -16150,7 +16219,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { content = denormalizeTemplate(content); if (origAsyncDirective.replace) { - $template = jqLite('
' + trim(content) + '
').contents(); + $template = directiveTemplateContents(content); compileNode = $template[0]; if ($template.length != 1 || compileNode.nodeType !== 1) { @@ -16194,9 +16263,18 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { linkNode = $compileNode[0]; if (beforeTemplateLinkNode !== beforeTemplateCompileNode) { - // it was cloned therefore we have to clone as well. - linkNode = jqLiteClone(compileNode); + var oldClasses = beforeTemplateLinkNode.className; + + if (!(previousCompileContext.hasElementTranscludeDirective && + origAsyncDirective.replace)) { + // it was cloned therefore we have to clone as well. + linkNode = jqLiteClone(compileNode); + } + replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode); + + // Copy in CSS classes from original node + safeAddClass(jqLite(linkNode), oldClasses); } if (afterTemplateNodeLinkFn.transclude) { childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude); @@ -17217,14 +17295,14 @@ function $HttpProvider() { -
- -
+ + - @@ -17261,27 +17339,34 @@ function $HttpProvider() { Hello, $http! - + + var status = element(by.binding('status')); + var data = element(by.binding('data')); + var fetchBtn = element(by.id('fetchbtn')); + var sampleGetBtn = element(by.id('samplegetbtn')); + var sampleJsonpBtn = element(by.id('samplejsonpbtn')); + var invalidJsonpBtn = element(by.id('invalidjsonpbtn')); + it('should make an xhr GET request', function() { - element(':button:contains("Sample GET")').click(); - element(':button:contains("fetch")').click(); - expect(binding('status')).toBe('200'); - expect(binding('data')).toMatch(/Hello, \$http!/); + sampleGetBtn.click(); + fetchBtn.click(); + expect(status.getText()).toMatch('200'); + expect(data.getText()).toMatch(/Hello, \$http!/) }); it('should make a JSONP request to angularjs.org', function() { - element(':button:contains("Sample JSONP")').click(); - element(':button:contains("fetch")').click(); - expect(binding('status')).toBe('200'); - expect(binding('data')).toMatch(/Super Hero!/); + sampleJsonpBtn.click(); + fetchBtn.click(); + expect(status.getText()).toMatch('200'); + expect(data.getText()).toMatch(/Super Hero!/); }); it('should make JSONP request to invalid URL and invoke the error handler', function() { - element(':button:contains("Invalid JSONP")').click(); - element(':button:contains("fetch")').click(); - expect(binding('status')).toBe('0'); - expect(binding('data')).toBe('Request failed'); + invalidJsonpBtn.click(); + fetchBtn.click(); + expect(status.getText()).toMatch('0'); + expect(data.getText()).toMatch('Request failed'); }); @@ -17663,13 +17748,18 @@ function $HttpProvider() { } function createXhr(method) { - // IE8 doesn't support PATCH method, but the ActiveX object does - /* global ActiveXObject */ - return (msie <= 8 && lowercase(method) === 'patch') - ? new ActiveXObject('Microsoft.XMLHTTP') - : new window.XMLHttpRequest(); -} + //if IE and the method is not RFC2616 compliant, or if XMLHttpRequest + //is not available, try getting an ActiveXObject. Otherwise, use XMLHttpRequest + //if it is available + if (msie <= 8 && (!method.match(/^(get|post|head|put|delete|options)$/i) || + !window.XMLHttpRequest)) { + return new window.ActiveXObject("Microsoft.XMLHTTP"); + } else if (window.XMLHttpRequest) { + return new window.XMLHttpRequest(); + } + throw minErr('$httpBackend')('noxhr', "This browser does not support XMLHttpRequest."); +} /** * @ngdoc object @@ -17764,7 +17854,20 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc } if (responseType) { - xhr.responseType = responseType; + try { + xhr.responseType = responseType; + } catch (e) { + // WebKit added support for the json responseType value on 09/03/2013 + // https://bugs.webkit.org/show_bug.cgi?id=73648. Versions of Safari prior to 7 are + // known to throw when setting the value "json" as the response type. Other older + // browsers implementing the responseType + // + // The json response type can be ignored if not supported, because JSON payloads are + // parsed on the client-side regardless. + if (responseType !== 'json') { + throw e; + } + } } xhr.send(post || null); @@ -17863,11 +17966,11 @@ var $interpolateMinErr = minErr('$interpolate'); //demo.label// - - it('should interpolate binding with custom symbols', function() { - expect(binding('demo.label')).toBe('This binding is brought you by // interpolation symbols.'); - }); - + + it('should interpolate binding with custom symbols', function() { + expect(element(by.binding('demo.label')).getText()).toBe('This binding is brought you by // interpolation symbols.'); + }); + */ function $InterpolateProvider() { @@ -18059,7 +18162,7 @@ function $InterpolateProvider() { * @description * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`. * - * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change + * Use {@link ng.$interpolateProvider#methods_endSymbol $interpolateProvider#endSymbol} to change * the symbol. * * @returns {string} start symbol. @@ -18903,7 +19006,7 @@ function $LocationProvider(){ * @eventType broadcast on root scope * @description * Broadcasted before a URL will change. This change can be prevented by calling - * `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on} for more + * `preventDefault` method of the event. See {@link ng.$rootScope.Scope#methods_$on} for more * details about event object. Upon successful change * {@link ng.$location#events_$locationChangeSuccess $locationChangeSuccess} is fired. * @@ -19086,7 +19189,7 @@ function $LogProvider(){ * @name ng.$logProvider#debugEnabled * @methodOf ng.$logProvider * @description - * @param {string=} flag enable or disable debug level messages + * @param {boolean=} flag enable or disable debug level messages * @returns {*} current value if used as getter or itself (chaining) if used as setter */ this.debugEnabled = function(flag) { @@ -20542,7 +20645,7 @@ function $ParseProvider() { * constructed via `$q.reject`, the promise will be rejected instead. * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to * resolving it with a rejection constructed via `$q.reject`. - * - `notify(value)` - provides updates on the status of the promises execution. This may be called + * - `notify(value)` - provides updates on the status of the promise's execution. This may be called * multiple times before the promise is either resolved or rejected. * * **Properties** @@ -20692,7 +20795,7 @@ function qFactory(nextTick, exceptionHandler) { reject: function(reason) { - deferred.resolve(reject(reason)); + deferred.resolve(createInternalRejectedPromise(reason)); }, @@ -20849,6 +20952,12 @@ function qFactory(nextTick, exceptionHandler) { * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`. */ var reject = function(reason) { + var result = defer(); + result.reject(reason); + return result.promise; + }; + + var createInternalRejectedPromise = function(reason) { return { then: function(callback, errback) { var result = defer(); @@ -21909,7 +22018,7 @@ function $RootScopeProvider(){ * onto the {@link ng.$exceptionHandler $exceptionHandler} service. * * @param {string} name Event name to emit. - * @param {...*} args Optional set of arguments which will be passed onto the event listeners. + * @param {...*} args Optional one or more arguments which will be passed onto the event listeners. * @return {Object} Event object (see {@link ng.$rootScope.Scope#methods_$on}). */ $emit: function(name, args) { @@ -21977,7 +22086,7 @@ function $RootScopeProvider(){ * onto the {@link ng.$exceptionHandler $exceptionHandler} service. * * @param {string} name Event name to broadcast. - * @param {...*} args Optional set of arguments which will be passed onto the event listeners. + * @param {...*} args Optional one or more arguments which will be passed onto the event listeners. * @return {Object} Event object, see {@link ng.$rootScope.Scope#methods_$on} */ $broadcast: function(name, args) { @@ -22769,13 +22878,15 @@ function $SceDelegateProvider() { ] - + describe('SCE doc demo', function() { it('should sanitize untrusted values', function() { - expect(element('.htmlComment').html()).toBe('Is anyone reading this?'); + expect(element(by.css('.htmlComment')).getInnerHtml()) + .toBe('Is anyone reading this?'); }); + it('should NOT sanitize explicitly trusted values', function() { - expect(element('#explicitlyTrustedHtml').html()).toBe( + expect(element(by.id('explicitlyTrustedHtml')).getInnerHtml()).toBe( 'Hover over this text.'); }); @@ -23534,13 +23645,13 @@ function urlIsSameOrigin(requestUrl) { - + it('should display the greeting in the input box', function() { - input('greeting').enter('Hello, E2E Tests'); + element(by.model('greeting')).sendKeys('Hello, E2E Tests'); // If we click the button it will block the test runner // element(':button').click(); }); - + */ function $WindowProvider(){ @@ -23749,35 +23860,47 @@ function $FilterProvider($provide) { Equality
- - - + + +
NamePhone
{{friend.name}}{{friend.phone}}
{{friendObj.name}}{{friendObj.phone}}
- - it('should search across all fields when filtering with a string', function() { - input('searchText').enter('m'); - expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')). - toEqual(['Mary', 'Mike', 'Adam']); + + var expectFriendNames = function(expectedNames, key) { + element.all(by.repeater(key + ' in friends').column(key + '.name')).then(function(arr) { + arr.forEach(function(wd, i) { + expect(wd.getText()).toMatch(expectedNames[i]); + }); + }); + }; - input('searchText').enter('76'); - expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')). - toEqual(['John', 'Julie']); + it('should search across all fields when filtering with a string', function() { + var searchText = element(by.model('searchText')); + searchText.clear(); + searchText.sendKeys('m'); + expectFriendNames(['Mary', 'Mike', 'Adam'], 'friend'); + + searchText.clear(); + searchText.sendKeys('76'); + expectFriendNames(['John', 'Julie'], 'friend'); }); it('should search in specific fields when filtering with a predicate object', function() { - input('search.$').enter('i'); - expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')). - toEqual(['Mary', 'Mike', 'Julie', 'Juliette']); + var searchAny = element(by.model('search.$')); + searchAny.clear(); + searchAny.sendKeys('i'); + expectFriendNames(['Mary', 'Mike', 'Julie', 'Juliette'], 'friendObj'); }); it('should use a equal comparison when comparator is true', function() { - input('search.name').enter('Julie'); - input('strict').check(); - expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')). - toEqual(['Julie']); + var searchName = element(by.model('search.name')); + var strict = element(by.model('strict')); + searchName.clear(); + searchName.sendKeys('Julie'); + strict.click(); + expectFriendNames(['Julie'], 'friendObj'); }); - + */ function filterFilter() { @@ -23803,6 +23926,15 @@ function filterFilter() { }; } else { comparator = function(obj, text) { + if (obj && text && typeof obj === 'object' && typeof text === 'object') { + for (var objKey in obj) { + if (objKey.charAt(0) !== '$' && hasOwnProperty.call(obj, objKey) && + comparator(obj[objKey], text[objKey])) { + return true; + } + } + return false; + } text = (''+text).toLowerCase(); return (''+obj).toLowerCase().indexOf(text) > -1; }; @@ -23855,7 +23987,7 @@ function filterFilter() { (function(path) { if (typeof expression[path] == 'undefined') return; predicates.push(function(value) { - return search(path == '$' ? value : getter(value, path), expression[path]); + return search(path == '$' ? value : (value && value[path]), expression[path]); }); })(key); } @@ -23901,21 +24033,27 @@ function filterFilter() {

- default currency symbol ($): {{amount | currency}}
- custom currency identifier (USD$): {{amount | currency:"USD$"}} + default currency symbol ($): {{amount | currency}}
+ custom currency identifier (USD$): {{amount | currency:"USD$"}}
- + it('should init with 1234.56', function() { - expect(binding('amount | currency')).toBe('$1,234.56'); - expect(binding('amount | currency:"USD$"')).toBe('USD$1,234.56'); + expect(element(by.id('currency-default')).getText()).toBe('$1,234.56'); + expect(element(by.binding('amount | currency:"USD$"')).getText()).toBe('USD$1,234.56'); }); it('should update', function() { - input('amount').enter('-1234'); - expect(binding('amount | currency')).toBe('($1,234.00)'); - expect(binding('amount | currency:"USD$"')).toBe('(USD$1,234.00)'); + if (browser.params.browser == 'safari') { + // Safari does not understand the minus key. See + // https://github.com/angular/protractor/issues/481 + return; + } + element(by.model('amount')).clear(); + element(by.model('amount')).sendKeys('-1234'); + expect(element(by.id('currency-default')).getText()).toBe('($1,234.00)'); + expect(element(by.binding('amount | currency:"USD$"')).getText()).toBe('(USD$1,234.00)'); }); - + */ currencyFilter.$inject = ['$locale']; @@ -23954,25 +24092,26 @@ function currencyFilter($locale) {
Enter number:
- Default formatting: {{val | number}}
- No fractions: {{val | number:0}}
- Negative number: {{-val | number:4}} + Default formatting: {{val | number}}
+ No fractions: {{val | number:0}}
+ Negative number: {{-val | number:4}}
- + it('should format numbers', function() { - expect(binding('val | number')).toBe('1,234.568'); - expect(binding('val | number:0')).toBe('1,235'); - expect(binding('-val | number:4')).toBe('-1,234.5679'); + expect(element(by.id('number-default')).getText()).toBe('1,234.568'); + expect(element(by.binding('val | number:0')).getText()).toBe('1,235'); + expect(element(by.binding('-val | number:4')).getText()).toBe('-1,234.5679'); }); it('should update', function() { - input('val').enter('3374.333'); - expect(binding('val | number')).toBe('3,374.333'); - expect(binding('val | number:0')).toBe('3,374'); - expect(binding('-val | number:4')).toBe('-3,374.3330'); - }); - + element(by.model('val')).clear(); + element(by.model('val')).sendKeys('3374.333'); + expect(element(by.id('number-default')).getText()).toBe('3,374.333'); + expect(element(by.binding('val | number:0')).getText()).toBe('3,374'); + expect(element(by.binding('-val | number:4')).getText()).toBe('-3,374.3330'); + }); + */ @@ -24202,22 +24341,22 @@ var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+ {{1288323623006 | date:'medium'}}: - {{1288323623006 | date:'medium'}}
+ {{1288323623006 | date:'medium'}}
{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}: - {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}
+ {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}
{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}: - {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}
+ {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}
- + it('should format date', function() { - expect(binding("1288323623006 | date:'medium'")). + expect(element(by.binding("1288323623006 | date:'medium'")).getText()). toMatch(/Oct 2\d, 2010 \d{1,2}:\d{2}:\d{2} (AM|PM)/); - expect(binding("1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'")). + expect(element(by.binding("1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'")).getText()). toMatch(/2010\-10\-2\d \d{2}:\d{2}:\d{2} (\-|\+)?\d{4}/); - expect(binding("'1288323623006' | date:'MM/dd/yyyy @ h:mma'")). + expect(element(by.binding("'1288323623006' | date:'MM/dd/yyyy @ h:mma'")).getText()). toMatch(/10\/2\d\/2010 @ \d{1,2}:\d{2}(AM|PM)/); }); - +
*/ dateFilter.$inject = ['$locale']; @@ -24316,11 +24455,11 @@ function dateFilter($locale) {
{{ {'name':'value'} | json }}
- + it('should jsonify filtered objects', function() { - expect(binding("{'name':'value'}")).toMatch(/\{\n "name": ?"value"\n}/); + expect(element(by.binding("{'name':'value'}")).getText()).toMatch(/\{\n "name": ?"value"\n}/); }); - + * */ @@ -24388,28 +24527,37 @@ var uppercaseFilter = valueFn(uppercase);

Output letters: {{ letters | limitTo:letterLimit }}

- + + var numLimitInput = element(by.model('numLimit')); + var letterLimitInput = element(by.model('letterLimit')); + var limitedNumbers = element(by.binding('numbers | limitTo:numLimit')); + var limitedLetters = element(by.binding('letters | limitTo:letterLimit')); + it('should limit the number array to first three items', function() { - expect(element('.doc-example-live input[ng-model=numLimit]').val()).toBe('3'); - expect(element('.doc-example-live input[ng-model=letterLimit]').val()).toBe('3'); - expect(binding('numbers | limitTo:numLimit')).toEqual('[1,2,3]'); - expect(binding('letters | limitTo:letterLimit')).toEqual('abc'); + expect(numLimitInput.getAttribute('value')).toBe('3'); + expect(letterLimitInput.getAttribute('value')).toBe('3'); + expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3]'); + expect(limitedLetters.getText()).toEqual('Output letters: abc'); }); it('should update the output when -3 is entered', function() { - input('numLimit').enter(-3); - input('letterLimit').enter(-3); - expect(binding('numbers | limitTo:numLimit')).toEqual('[7,8,9]'); - expect(binding('letters | limitTo:letterLimit')).toEqual('ghi'); + numLimitInput.clear(); + numLimitInput.sendKeys('-3'); + letterLimitInput.clear(); + letterLimitInput.sendKeys('-3'); + expect(limitedNumbers.getText()).toEqual('Output numbers: [7,8,9]'); + expect(limitedLetters.getText()).toEqual('Output letters: ghi'); }); it('should not exceed the maximum size of input array', function() { - input('numLimit').enter(100); - input('letterLimit').enter(100); - expect(binding('numbers | limitTo:numLimit')).toEqual('[1,2,3,4,5,6,7,8,9]'); - expect(binding('letters | limitTo:letterLimit')).toEqual('abcdefghi'); + numLimitInput.clear(); + numLimitInput.sendKeys('100'); + letterLimitInput.clear(); + letterLimitInput.sendKeys('100'); + expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3,4,5,6,7,8,9]'); + expect(limitedLetters.getText()).toEqual('Output letters: abcdefghi'); }); - + */ function limitToFilter(){ @@ -24510,29 +24658,6 @@ function limitToFilter(){ - - it('should be reverse ordered by aged', function() { - expect(binding('predicate')).toBe('-age'); - expect(repeater('table.friend', 'friend in friends').column('friend.age')). - toEqual(['35', '29', '21', '19', '10']); - expect(repeater('table.friend', 'friend in friends').column('friend.name')). - toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']); - }); - - it('should reorder the table when user selects different predicate', function() { - element('.doc-example-live a:contains("Name")').click(); - expect(repeater('table.friend', 'friend in friends').column('friend.name')). - toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']); - expect(repeater('table.friend', 'friend in friends').column('friend.age')). - toEqual(['35', '10', '29', '19', '21']); - - element('.doc-example-live a:contains("Phone")').click(); - expect(repeater('table.friend', 'friend in friends').column('friend.phone')). - toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']); - expect(repeater('table.friend', 'friend in friends').column('friend.name')). - toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']); - }); - */ orderByFilter.$inject = ['$parse']; @@ -24686,46 +24811,55 @@ var htmlAnchorDirective = valueFn({ anchor (no link)
link (link, change location) - + it('should execute ng-click but not reload when href without value', function() { - element('#link-1').click(); - expect(input('value').val()).toEqual('1'); - expect(element('#link-1').attr('href')).toBe(""); + element(by.id('link-1')).click(); + expect(element(by.model('value')).getAttribute('value')).toEqual('1'); + expect(element(by.id('link-1')).getAttribute('href')).toBe(''); }); it('should execute ng-click but not reload when href empty string', function() { - element('#link-2').click(); - expect(input('value').val()).toEqual('2'); - expect(element('#link-2').attr('href')).toBe(""); + element(by.id('link-2')).click(); + expect(element(by.model('value')).getAttribute('value')).toEqual('2'); + expect(element(by.id('link-2')).getAttribute('href')).toBe(''); }); it('should execute ng-click and change url when ng-href specified', function() { - expect(element('#link-3').attr('href')).toBe("/123"); + expect(element(by.id('link-3')).getAttribute('href')).toMatch(/\/123$/); - element('#link-3').click(); - expect(browser().window().path()).toEqual('/123'); + element(by.id('link-3')).click(); + + // At this point, we navigate away from an Angular page, so we need + // to use browser.driver to get the base webdriver. + + browser.wait(function() { + return browser.driver.getCurrentUrl().then(function(url) { + return url.match(/\/123$/); + }); + }, 1000, 'page should navigate to /123'); }); it('should execute ng-click but not reload when href empty string and name specified', function() { - element('#link-4').click(); - expect(input('value').val()).toEqual('4'); - expect(element('#link-4').attr('href')).toBe(''); + element(by.id('link-4')).click(); + expect(element(by.model('value')).getAttribute('value')).toEqual('4'); + expect(element(by.id('link-4')).getAttribute('href')).toBe(''); }); it('should execute ng-click but not reload when no href but name specified', function() { - element('#link-5').click(); - expect(input('value').val()).toEqual('5'); - expect(element('#link-5').attr('href')).toBe(undefined); + element(by.id('link-5')).click(); + expect(element(by.model('value')).getAttribute('value')).toEqual('5'); + expect(element(by.id('link-5')).getAttribute('href')).toBe(null); }); it('should only change url when only ng-href', function() { - input('value').enter('6'); - expect(element('#link-6').attr('href')).toBe('6'); + element(by.model('value')).clear(); + element(by.model('value')).sendKeys('6'); + expect(element(by.id('link-6')).getAttribute('href')).toMatch(/\/6$/); - element('#link-6').click(); - expect(browser().location().url()).toEqual('/6'); + element(by.id('link-6')).click(); + expect(browser.getCurrentUrl()).toMatch(/\/6$/); }); - + */ @@ -24810,13 +24944,13 @@ var htmlAnchorDirective = valueFn({ Click me to toggle:
- + it('should toggle button', function() { - expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy(); - input('checked').check(); - expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy(); + expect(element(by.css('.doc-example-live button')).getAttribute('disabled')).toBeFalsy(); + element(by.model('checked')).click(); + expect(element(by.css('.doc-example-live button')).getAttribute('disabled')).toBeTruthy(); }); - + * * @element INPUT @@ -24845,13 +24979,13 @@ var htmlAnchorDirective = valueFn({ Check me to check both:
- + it('should check both checkBoxes', function() { - expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy(); - input('master').check(); - expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy(); + expect(element(by.id('checkSlave')).getAttribute('checked')).toBeFalsy(); + element(by.model('master')).click(); + expect(element(by.id('checkSlave')).getAttribute('checked')).toBeTruthy(); }); - + * * @element INPUT @@ -24880,13 +25014,13 @@ var htmlAnchorDirective = valueFn({ Check me to make text readonly:
- + it('should toggle readonly attr', function() { - expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy(); - input('checked').check(); - expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy(); + expect(element(by.css('.doc-example-live [type="text"]')).getAttribute('readonly')).toBeFalsy(); + element(by.model('checked')).click(); + expect(element(by.css('.doc-example-live [type="text"]')).getAttribute('readonly')).toBeTruthy(); }); - + * * @element INPUT @@ -24919,13 +25053,13 @@ var htmlAnchorDirective = valueFn({ - + it('should select Greetings!', function() { - expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy(); - input('selected').check(); - expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy(); + expect(element(by.id('greet')).getAttribute('selected')).toBeFalsy(); + element(by.model('selected')).click(); + expect(element(by.id('greet')).getAttribute('selected')).toBeTruthy(); }); - + * * @element OPTION @@ -24955,13 +25089,13 @@ var htmlAnchorDirective = valueFn({ Show/Hide me - + it('should toggle open', function() { - expect(element('#details').prop('open')).toBeFalsy(); - input('open').check(); - expect(element('#details').prop('open')).toBeTruthy(); + expect(element(by.id('details')).getAttribute('open')).toBeFalsy(); + element(by.model('open')).click(); + expect(element(by.id('details')).getAttribute('open')).toBeTruthy(); }); - + * * @element DETAILS @@ -25320,18 +25454,27 @@ function FormController(element, attrs) { myForm.$error.required = {{!!myForm.$error.required}}
- + it('should initialize to model', function() { - expect(binding('userType')).toEqual('guest'); - expect(binding('myForm.input.$valid')).toEqual('true'); + var userType = element(by.binding('userType')); + var valid = element(by.binding('myForm.input.$valid')); + + expect(userType.getText()).toContain('guest'); + expect(valid.getText()).toContain('true'); }); it('should be invalid if empty', function() { - input('userType').enter(''); - expect(binding('userType')).toEqual(''); - expect(binding('myForm.input.$valid')).toEqual('false'); + var userType = element(by.binding('userType')); + var valid = element(by.binding('myForm.input.$valid')); + var userInput = element(by.model('userType')); + + userInput.clear(); + userInput.sendKeys(''); + + expect(userType.getText()).toEqual('userType ='); + expect(valid.getText()).toContain('false'); }); - + */ var formDirectiveFactory = function(isNgForm) { @@ -25456,29 +25599,31 @@ var inputType = { myForm.$error.required = {{!!myForm.$error.required}}
- + + var text = element(by.binding('text')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('text')); + it('should initialize to model', function() { - expect(binding('text')).toEqual('guest'); - expect(binding('myForm.input.$valid')).toEqual('true'); + expect(text.getText()).toContain('guest'); + expect(valid.getText()).toContain('true'); }); it('should be invalid if empty', function() { - input('text').enter(''); - expect(binding('text')).toEqual(''); - expect(binding('myForm.input.$valid')).toEqual('false'); + input.clear(); + input.sendKeys(''); + + expect(text.getText()).toEqual('text ='); + expect(valid.getText()).toContain('false'); }); it('should be invalid if multi word', function() { - input('text').enter('hello world'); - expect(binding('myForm.input.$valid')).toEqual('false'); - }); + input.clear(); + input.sendKeys('hello world'); - it('should not be trimmed', function() { - input('text').enter('untrimmed '); - expect(binding('text')).toEqual('untrimmed '); - expect(binding('myForm.input.$valid')).toEqual('true'); + expect(valid.getText()).toContain('false'); }); - + */ 'text': textInputType, @@ -25532,24 +25677,30 @@ var inputType = { myForm.$error.required = {{!!myForm.$error.required}}
- + + var value = element(by.binding('value')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('value')); + it('should initialize to model', function() { - expect(binding('value')).toEqual('12'); - expect(binding('myForm.input.$valid')).toEqual('true'); + expect(value.getText()).toContain('12'); + expect(valid.getText()).toContain('true'); }); it('should be invalid if empty', function() { - input('value').enter(''); - expect(binding('value')).toEqual(''); - expect(binding('myForm.input.$valid')).toEqual('false'); + input.clear(); + input.sendKeys(''); + expect(value.getText()).toEqual('value ='); + expect(valid.getText()).toContain('false'); }); it('should be invalid if over max', function() { - input('value').enter('123'); - expect(binding('value')).toEqual(''); - expect(binding('myForm.input.$valid')).toEqual('false'); + input.clear(); + input.sendKeys('123'); + expect(value.getText()).toEqual('value ='); + expect(valid.getText()).toContain('false'); }); - + */ 'number': numberInputType, @@ -25601,23 +25752,31 @@ var inputType = { myForm.$error.url = {{!!myForm.$error.url}}
- + + var text = element(by.binding('text')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('text')); + it('should initialize to model', function() { - expect(binding('text')).toEqual('http://google.com'); - expect(binding('myForm.input.$valid')).toEqual('true'); + expect(text.getText()).toContain('http://google.com'); + expect(valid.getText()).toContain('true'); }); it('should be invalid if empty', function() { - input('text').enter(''); - expect(binding('text')).toEqual(''); - expect(binding('myForm.input.$valid')).toEqual('false'); + input.clear(); + input.sendKeys(''); + + expect(text.getText()).toEqual('text ='); + expect(valid.getText()).toContain('false'); }); it('should be invalid if not url', function() { - input('text').enter('xxx'); - expect(binding('myForm.input.$valid')).toEqual('false'); + input.clear(); + input.sendKeys('box'); + + expect(valid.getText()).toContain('false'); }); - + */ 'url': urlInputType, @@ -25669,23 +25828,30 @@ var inputType = { myForm.$error.email = {{!!myForm.$error.email}}
- + + var text = element(by.binding('text')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('text')); + it('should initialize to model', function() { - expect(binding('text')).toEqual('me@example.com'); - expect(binding('myForm.input.$valid')).toEqual('true'); + expect(text.getText()).toContain('me@example.com'); + expect(valid.getText()).toContain('true'); }); it('should be invalid if empty', function() { - input('text').enter(''); - expect(binding('text')).toEqual(''); - expect(binding('myForm.input.$valid')).toEqual('false'); + input.clear(); + input.sendKeys(''); + expect(text.getText()).toEqual('text ='); + expect(valid.getText()).toContain('false'); }); it('should be invalid if not email', function() { - input('text').enter('xxx'); - expect(binding('myForm.input.$valid')).toEqual('false'); + input.clear(); + input.sendKeys('xxx'); + + expect(valid.getText()).toContain('false'); }); - + */ 'email': emailInputType, @@ -25726,14 +25892,17 @@ var inputType = { 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"'); + var color = element(by.binding('color')); - input('color').select('red'); - expect(binding('color')).toEqual('"red"'); + expect(color.getText()).toContain('blue'); + + element.all(by.model('color')).get(0).click(); + + expect(color.getText()).toContain('red'); }); - + */ 'radio': radioInputType, @@ -25770,17 +25939,21 @@ var inputType = { value2 = {{value2}}
- + it('should change state', function() { - expect(binding('value1')).toEqual('true'); - expect(binding('value2')).toEqual('YES'); + var value1 = element(by.binding('value1')); + var value2 = element(by.binding('value2')); + + expect(value1.getText()).toContain('true'); + expect(value2.getText()).toContain('YES'); + + element(by.model('value1')).click(); + element(by.model('value2')).click(); - input('value1').check(); - input('value2').check(); - expect(binding('value1')).toEqual('false'); - expect(binding('value2')).toEqual('NO'); + expect(value1.getText()).toContain('false'); + expect(value2.getText()).toContain('NO'); }); - + */ 'checkbox': checkboxInputType, @@ -25788,7 +25961,8 @@ var inputType = { 'hidden': noop, 'button': noop, 'submit': noop, - 'reset': noop + 'reset': noop, + 'file': noop }; // A helper function to call $setValidity and return the value / undefined, @@ -25811,6 +25985,7 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) { element.on('compositionend', function() { composing = false; + listener(); }); } @@ -26133,44 +26308,59 @@ function checkboxInputType(scope, element, attr, ctrl) { myForm.$error.maxlength = {{!!myForm.$error.maxlength}}
- + + var user = element(by.binding('{{user}}')); + var userNameValid = element(by.binding('myForm.userName.$valid')); + var lastNameValid = element(by.binding('myForm.lastName.$valid')); + var lastNameError = element(by.binding('myForm.lastName.$error')); + var formValid = element(by.binding('myForm.$valid')); + var userNameInput = element(by.model('user.name')); + var userLastInput = element(by.model('user.last')); + it('should initialize to model', function() { - expect(binding('user')).toEqual('{"name":"guest","last":"visitor"}'); - expect(binding('myForm.userName.$valid')).toEqual('true'); - expect(binding('myForm.$valid')).toEqual('true'); + expect(user.getText()).toContain('{"name":"guest","last":"visitor"}'); + expect(userNameValid.getText()).toContain('true'); + expect(formValid.getText()).toContain('true'); }); it('should be invalid if empty when required', function() { - input('user.name').enter(''); - expect(binding('user')).toEqual('{"last":"visitor"}'); - expect(binding('myForm.userName.$valid')).toEqual('false'); - expect(binding('myForm.$valid')).toEqual('false'); + userNameInput.clear(); + userNameInput.sendKeys(''); + + expect(user.getText()).toContain('{"last":"visitor"}'); + expect(userNameValid.getText()).toContain('false'); + expect(formValid.getText()).toContain('false'); }); it('should be valid if empty when min length is set', function() { - input('user.last').enter(''); - expect(binding('user')).toEqual('{"name":"guest","last":""}'); - expect(binding('myForm.lastName.$valid')).toEqual('true'); - expect(binding('myForm.$valid')).toEqual('true'); + userLastInput.clear(); + userLastInput.sendKeys(''); + + expect(user.getText()).toContain('{"name":"guest","last":""}'); + expect(lastNameValid.getText()).toContain('true'); + expect(formValid.getText()).toContain('true'); }); it('should be invalid if less than required min length', function() { - input('user.last').enter('xx'); - expect(binding('user')).toEqual('{"name":"guest"}'); - expect(binding('myForm.lastName.$valid')).toEqual('false'); - expect(binding('myForm.lastName.$error')).toMatch(/minlength/); - expect(binding('myForm.$valid')).toEqual('false'); + userLastInput.clear(); + userLastInput.sendKeys('xx'); + + expect(user.getText()).toContain('{"name":"guest"}'); + expect(lastNameValid.getText()).toContain('false'); + expect(lastNameError.getText()).toContain('minlength'); + expect(formValid.getText()).toContain('false'); }); it('should be invalid if longer than max length', function() { - input('user.last').enter('some ridiculously long name'); - expect(binding('user')) - .toEqual('{"name":"guest"}'); - expect(binding('myForm.lastName.$valid')).toEqual('false'); - expect(binding('myForm.lastName.$error')).toMatch(/maxlength/); - expect(binding('myForm.$valid')).toEqual('false'); + userLastInput.clear(); + userLastInput.sendKeys('some ridiculously long name'); + + expect(user.getText()).toContain('{"name":"guest"}'); + expect(lastNameValid.getText()).toContain('false'); + expect(lastNameError.getText()).toContain('maxlength'); + expect(formValid.getText()).toContain('false'); }); - + */ var inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) { @@ -26302,14 +26492,23 @@ var VALID_CLASS = 'ng-valid',
- + it('should data-bind and become invalid', function() { - var contentEditable = element('[contenteditable]'); + if (browser.params.browser = 'safari') { + // SafariDriver can't handle contenteditable. + return; + }; + var contentEditable = element(by.css('.doc-example-live [contenteditable]')); + + expect(contentEditable.getText()).toEqual('Change me!'); + + // Firefox driver doesn't trigger the proper events on 'clear', so do this hack + contentEditable.click(); + contentEditable.sendKeys(protractor.Key.chord(protractor.Key.COMMAND, "a")); + contentEditable.sendKeys(protractor.Key.BACK_SPACE); - expect(contentEditable.text()).toEqual('Change me!'); - input('userContent').enter(''); - expect(contentEditable.text()).toEqual(''); - expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/); + expect(contentEditable.getText()).toEqual(''); + expect(contentEditable.getAttribute('class')).toMatch(/ng-invalid-required/); }); * @@ -26362,6 +26561,9 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$ * You can override this for input directives whose concept of being empty is different to the * default. The `checkboxInputType` directive does this because in its case a value of `false` * implies empty. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is empty. */ this.$isEmpty = function(value) { return isUndefined(value) || value === '' || value === null || value !== value; @@ -26616,24 +26818,30 @@ var ngModelDirective = function() { * * *
- * debug = {{confirmed}}
- * counter = {{counter}} + * debug = {{confirmed}}
+ * counter = {{counter}}
* * - * + * + * var counter = element(by.binding('counter')); + * var debug = element(by.binding('confirmed')); + * * it('should evaluate the expression if changing from view', function() { - * expect(binding('counter')).toEqual('0'); - * element('#ng-change-example1').click(); - * expect(binding('counter')).toEqual('1'); - * expect(binding('confirmed')).toEqual('true'); + * expect(counter.getText()).toContain('0'); + * + * element(by.id('ng-change-example1')).click(); + * + * expect(counter.getText()).toContain('1'); + * expect(debug.getText()).toContain('true'); * }); * * it('should not evaluate the expression if changing from model', function() { - * element('#ng-change-example2').click(); - * expect(binding('counter')).toEqual('0'); - * expect(binding('confirmed')).toEqual('true'); + * element(by.id('ng-change-example2')).click(); + + * expect(counter.getText()).toContain('0'); + * expect(debug.getText()).toContain('true'); * }); - * + * * */ var ngChangeDirective = valueFn({ @@ -26706,20 +26914,26 @@ var requiredDirective = function() { myForm.$error.required = {{!!myForm.$error.required}}
- + + var listInput = element(by.model('names')); + var names = element(by.binding('{{names}}')); + var valid = element(by.binding('myForm.namesInput.$valid')); + var error = element(by.css('span.error')); + it('should initialize to model', function() { - expect(binding('names')).toEqual('["igor","misko","vojta"]'); - expect(binding('myForm.namesInput.$valid')).toEqual('true'); - expect(element('span.error').css('display')).toBe('none'); + expect(names.getText()).toContain('["igor","misko","vojta"]'); + expect(valid.getText()).toContain('true'); + expect(error.getCssValue('display')).toBe('none'); }); it('should be invalid if empty', function() { - input('names').enter(''); - expect(binding('names')).toEqual(''); - expect(binding('myForm.namesInput.$valid')).toEqual('false'); - expect(element('span.error').css('display')).not().toBe('none'); - }); - + listInput.clear(); + listInput.sendKeys(''); + + expect(names.getText()).toContain(''); + expect(valid.getText()).toContain('false'); + expect(error.getCssValue('display')).not.toBe('none'); }); + */ var ngListDirective = function() { @@ -26801,15 +27015,17 @@ var CONSTANT_VALUE_REGEXP = /^(true|false|\d+)$/;
You chose {{my.favorite}}
- + + var favorite = element(by.binding('my.favorite')); + it('should initialize to model', function() { - expect(binding('my.favorite')).toEqual('unicorns'); + expect(favorite.getText()).toContain('unicorns'); }); it('should bind the values to the inputs', function() { - input('my.favorite').select('pizza'); - expect(binding('my.favorite')).toEqual('pizza'); + element.all(by.model('my.favorite')).get(0).click(); + expect(favorite.getText()).toContain('pizza'); }); - + */ var ngValueDirective = function() { @@ -26869,13 +27085,17 @@ var ngValueDirective = function() { Hello ! - + it('should check ng-bind', function() { - expect(using('.doc-example-live').binding('name')).toBe('Whirled'); - using('.doc-example-live').input('name').enter('world'); - expect(using('.doc-example-live').binding('name')).toBe('world'); + var exampleContainer = $('.doc-example-live'); + var nameInput = element(by.model('name')); + + expect(exampleContainer.findElement(by.binding('name')).getText()).toBe('Whirled'); + nameInput.clear(); + nameInput.sendKeys('world'); + expect(exampleContainer.findElement(by.binding('name')).getText()).toBe('world'); }); - + */ var ngBindDirective = ngDirective(function(scope, element, attr) { @@ -26921,20 +27141,22 @@ var ngBindDirective = ngDirective(function(scope, element, attr) {

        
      
-     
+     
        it('should check ng-bind', function() {
-         expect(using('.doc-example-live').binding('salutation')).
-           toBe('Hello');
-         expect(using('.doc-example-live').binding('name')).
-           toBe('World');
-         using('.doc-example-live').input('salutation').enter('Greetings');
-         using('.doc-example-live').input('name').enter('user');
-         expect(using('.doc-example-live').binding('salutation')).
-           toBe('Greetings');
-         expect(using('.doc-example-live').binding('name')).
-           toBe('user');
+         var salutationElem = element(by.binding('salutation'));
+         var salutationInput = element(by.model('salutation'));
+         var nameInput = element(by.model('name'));
+
+         expect(salutationElem.getText()).toBe('Hello World!');
+
+         salutationInput.clear();
+         salutationInput.sendKeys('Greetings');
+         nameInput.clear();
+         nameInput.sendKeys('user');
+
+         expect(salutationElem.getText()).toBe('Greetings user!');
        });
-     
+     
    
  */
 var ngBindTemplateDirective = ['$interpolate', function($interpolate) {
@@ -26987,12 +27209,10 @@ var ngBindTemplateDirective = ['$interpolate', function($interpolate) {
        }]);
      
- + it('should check ng-bind-html', function() { - expect(using('.doc-example-live').binding('myHTML')). - toBe( - 'I am an HTMLstring with links! and other stuff' - ); + expect(element(by.binding('myHTML')).getText()).toBe( + 'I am an HTMLstring with links! and other stuff'); }); @@ -27124,31 +27344,34 @@ function classDirective(name, selector) { color: red; } - + + var ps = element.all(by.css('.doc-example-live p')); + it('should let you toggle the class', function() { - expect(element('.doc-example-live p:first').prop('className')).not().toMatch(/bold/); - expect(element('.doc-example-live p:first').prop('className')).not().toMatch(/red/); + expect(ps.first().getAttribute('class')).not.toMatch(/bold/); + expect(ps.first().getAttribute('class')).not.toMatch(/red/); - input('important').check(); - expect(element('.doc-example-live p:first').prop('className')).toMatch(/bold/); + element(by.model('important')).click(); + expect(ps.first().getAttribute('class')).toMatch(/bold/); - input('error').check(); - expect(element('.doc-example-live p:first').prop('className')).toMatch(/red/); + element(by.model('error')).click(); + expect(ps.first().getAttribute('class')).toMatch(/red/); }); it('should let you toggle string example', function() { - expect(element('.doc-example-live p:nth-of-type(2)').prop('className')).toBe(''); - input('style').enter('red'); - expect(element('.doc-example-live p:nth-of-type(2)').prop('className')).toBe('red'); + expect(ps.get(1).getAttribute('class')).toBe(''); + element(by.model('style')).clear(); + element(by.model('style')).sendKeys('red'); + expect(ps.get(1).getAttribute('class')).toBe('red'); }); it('array example should have 3 classes', function() { - expect(element('.doc-example-live p:last').prop('className')).toBe(''); - input('style1').enter('bold'); - input('style2').enter('strike'); - input('style3').enter('red'); - expect(element('.doc-example-live p:last').prop('className')).toBe('bold strike red'); + expect(ps.last().getAttribute('class')).toBe(''); + element(by.model('style1')).sendKeys('bold'); + element(by.model('style2')).sendKeys('strike'); + element(by.model('style3')).sendKeys('red'); + expect(ps.last().getAttribute('class')).toBe('bold strike red'); }); @@ -27159,8 +27382,8 @@ function classDirective(name, selector) { - - + +
Sample Text
@@ -27175,19 +27398,19 @@ function classDirective(name, selector) { font-size:3em; }
- + it('should check ng-class', function() { - expect(element('.doc-example-live span').prop('className')).not(). + expect(element(by.css('.base-class')).getAttribute('class')).not. toMatch(/my-class/); - using('.doc-example-live').element(':button:first').click(); + element(by.id('setbtn')).click(); - expect(element('.doc-example-live span').prop('className')). + expect(element(by.css('.base-class')).getAttribute('class')). toMatch(/my-class/); - using('.doc-example-live').element(':button:last').click(); + element(by.id('clearbtn')).click(); - expect(element('.doc-example-live span').prop('className')).not(). + expect(element(by.css('.base-class')).getAttribute('class')).not. toMatch(/my-class/); }); @@ -27239,11 +27462,11 @@ var ngClassDirective = classDirective('', true); color: blue; } - + it('should check ng-class-odd and ng-class-even', function() { - expect(element('.doc-example-live li:first span').prop('className')). + expect(element(by.repeater('name in names').row(0).column('name')).getAttribute('class')). toMatch(/odd/); - expect(element('.doc-example-live li:last span').prop('className')). + expect(element(by.repeater('name in names').row(1).column('name')).getAttribute('class')). toMatch(/even/); }); @@ -27287,11 +27510,11 @@ var ngClassOddDirective = classDirective('Odd', 0); color: blue; } - + it('should check ng-class-odd and ng-class-even', function() { - expect(element('.doc-example-live li:first span').prop('className')). + expect(element(by.repeater('name in names').row(0).column('name')).getAttribute('class')). toMatch(/odd/); - expect(element('.doc-example-live li:last span').prop('className')). + expect(element(by.repeater('name in names').row(1).column('name')).getAttribute('class')). toMatch(/even/); }); @@ -27344,14 +27567,14 @@ var ngClassEvenDirective = classDirective('Even', 1);
{{ 'hello' }}
{{ 'hello IE7' }}
- + it('should remove the template directive and css class', function() { - expect(element('.doc-example-live #template1').attr('ng-cloak')). - not().toBeDefined(); - expect(element('.doc-example-live #template2').attr('ng-cloak')). - not().toBeDefined(); + expect($('.doc-example-live #template1').getAttribute('ng-cloak')). + toBeNull(); + expect($('.doc-example-live #template2').getAttribute('ng-cloak')). + toBeNull(); }); - + * */ @@ -27444,22 +27667,36 @@ var ngCloakDirective = ngDirective({ - + it('should check controller as', function() { - expect(element('#ctrl-as-exmpl>:input').val()).toBe('John Smith'); - expect(element('#ctrl-as-exmpl li:nth-child(1) input').val()) - .toBe('408 555 1212'); - expect(element('#ctrl-as-exmpl li:nth-child(2) input').val()) - .toBe('john.smith@example.org'); - - element('#ctrl-as-exmpl li:first a:contains("clear")').click(); - expect(element('#ctrl-as-exmpl li:first input').val()).toBe(''); - - element('#ctrl-as-exmpl li:last a:contains("add")').click(); - expect(element('#ctrl-as-exmpl li:nth-child(3) input').val()) - .toBe('yourname@example.org'); + var container = element(by.id('ctrl-as-exmpl')); + + expect(container.findElement(by.model('settings.name')) + .getAttribute('value')).toBe('John Smith'); + + var firstRepeat = + container.findElement(by.repeater('contact in settings.contacts').row(0)); + var secondRepeat = + container.findElement(by.repeater('contact in settings.contacts').row(1)); + + expect(firstRepeat.findElement(by.model('contact.value')).getAttribute('value')) + .toBe('408 555 1212'); + expect(secondRepeat.findElement(by.model('contact.value')).getAttribute('value')) + .toBe('john.smith@example.org'); + + firstRepeat.findElement(by.linkText('clear')).click() + + expect(firstRepeat.findElement(by.model('contact.value')).getAttribute('value')) + .toBe(''); + + container.findElement(by.linkText('add')).click(); + + expect(container.findElement(by.repeater('contact in settings.contacts').row(2)) + .findElement(by.model('contact.value')) + .getAttribute('value')) + .toBe('yourname@example.org'); }); - + @@ -27507,22 +27744,36 @@ var ngCloakDirective = ngDirective({ - + it('should check controller', function() { - expect(element('#ctrl-exmpl>:input').val()).toBe('John Smith'); - expect(element('#ctrl-exmpl li:nth-child(1) input').val()) - .toBe('408 555 1212'); - expect(element('#ctrl-exmpl li:nth-child(2) input').val()) - .toBe('john.smith@example.org'); - - element('#ctrl-exmpl li:first a:contains("clear")').click(); - expect(element('#ctrl-exmpl li:first input').val()).toBe(''); - - element('#ctrl-exmpl li:last a:contains("add")').click(); - expect(element('#ctrl-exmpl li:nth-child(3) input').val()) - .toBe('yourname@example.org'); + var container = element(by.id('ctrl-exmpl')); + + expect(container.findElement(by.model('name')) + .getAttribute('value')).toBe('John Smith'); + + var firstRepeat = + container.findElement(by.repeater('contact in contacts').row(0)); + var secondRepeat = + container.findElement(by.repeater('contact in contacts').row(1)); + + expect(firstRepeat.findElement(by.model('contact.value')).getAttribute('value')) + .toBe('408 555 1212'); + expect(secondRepeat.findElement(by.model('contact.value')).getAttribute('value')) + .toBe('john.smith@example.org'); + + firstRepeat.findElement(by.linkText('clear')).click() + + expect(firstRepeat.findElement(by.model('contact.value')).getAttribute('value')) + .toBe(''); + + container.findElement(by.linkText('add')).click(); + + expect(container.findElement(by.repeater('contact in contacts').row(2)) + .findElement(by.model('contact.value')) + .getAttribute('value')) + .toBe('yourname@example.org'); }); - + */ @@ -27874,8 +28125,8 @@ forEach( * Enables binding angular expressions to onsubmit events. * * Additionally it prevents the default action (which for form means sending the request to the - * server and reloading the current page) **but only if the form does not contain an `action` - * attribute**. + * server and reloading the current page), but only if the form does not contain `action`, + * `data-action`, or `x-action` attributes. * * @element form * @priority 0 @@ -27903,20 +28154,20 @@ forEach(
list={{list}}
- + it('should check ng-submit', function() { - expect(binding('list')).toBe('[]'); - element('.doc-example-live #submit').click(); - expect(binding('list')).toBe('["hello"]'); - expect(input('text').val()).toBe(''); + expect(element(by.binding('list')).getText()).toBe('list=[]'); + element(by.css('.doc-example-live #submit')).click(); + expect(element(by.binding('list')).getText()).toContain('hello'); + expect(element(by.input('text')).getAttribute('value')).toBe(''); }); it('should ignore empty strings', function() { - expect(binding('list')).toBe('[]'); - element('.doc-example-live #submit').click(); - element('.doc-example-live #submit').click(); - expect(binding('list')).toBe('["hello"]'); - }); - + expect(element(by.binding('list')).getText()).toBe('list=[]'); + element(by.css('.doc-example-live #submit')).click(); + element(by.css('.doc-example-live #submit')).click(); + expect(element(by.binding('list')).getText()).toContain('hello'); + }); + */ @@ -28243,19 +28494,33 @@ var ngIfDirective = ['$animate', function($animate) { top:50px; }
- + + var templateSelect = element(by.model('template')); + var includeElem = element(by.css('.doc-example-live [ng-include]')); + it('should load template1.html', function() { - expect(element('.doc-example-live [ng-include]').text()). - toMatch(/Content of template1.html/); + expect(includeElem.getText()).toMatch(/Content of template1.html/); }); + it('should load template2.html', function() { - select('template').option('1'); - expect(element('.doc-example-live [ng-include]').text()). - toMatch(/Content of template2.html/); + if (browser.params.browser == 'firefox') { + // Firefox can't handle using selects + // See https://github.com/angular/protractor/issues/480 + return; + } + templateSelect.click(); + templateSelect.element.all(by.css('option')).get(2).click(); + expect(includeElem.getText()).toMatch(/Content of template2.html/); }); + it('should change to blank', function() { - select('template').option(''); - expect(element('.doc-example-live [ng-include]')).toBe(undefined); + if (browser.params.browser == 'firefox') { + // Firefox can't handle using selects + return; + } + templateSelect.click(); + templateSelect.element.all(by.css('option')).get(0).click(); + expect(includeElem.isPresent()).toBe(false); }); @@ -28415,15 +28680,15 @@ var ngIncludeFillContentDirective = ['$compile', - + it('should alias index positions', function() { - expect(element('.example-init').text()) - .toBe('list[ 0 ][ 0 ] = a;' + - 'list[ 0 ][ 1 ] = b;' + - 'list[ 1 ][ 0 ] = c;' + - 'list[ 1 ][ 1 ] = d;'); + var elements = element.all(by.css('.example-init')); + expect(elements.get(0).getText()).toBe('list[ 0 ][ 0 ] = a;'); + expect(elements.get(1).getText()).toBe('list[ 0 ][ 1 ] = b;'); + expect(elements.get(2).getText()).toBe('list[ 1 ][ 0 ] = c;'); + expect(elements.get(3).getText()).toBe('list[ 1 ][ 1 ] = d;'); }); - + */ var ngInitDirective = ngDirective({ @@ -28461,13 +28726,12 @@ var ngInitDirective = ngDirective({
Normal: {{1 + 2}}
Ignored: {{1 + 2}}
- + it('should check ng-non-bindable', function() { - expect(using('.doc-example-live').binding('1 + 2')).toBe('3'); - expect(using('.doc-example-live').element('div:last').text()). - toMatch(/1 \+ 2/); + expect(element(by.binding('1 + 2')).getText()).toContain('3'); + expect(element.all(by.css('.doc-example-live div')).last().getText()).toMatch(/1 \+ 2/); }); - + */ var ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 }); @@ -28595,49 +28859,53 @@ var ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 }); - + it('should show correct pluralized string', function() { - expect(element('.doc-example-live ng-pluralize:first').text()). - toBe('1 person is viewing.'); - expect(element('.doc-example-live ng-pluralize:last').text()). - toBe('Igor is viewing.'); - - using('.doc-example-live').input('personCount').enter('0'); - expect(element('.doc-example-live ng-pluralize:first').text()). - toBe('Nobody is viewing.'); - expect(element('.doc-example-live ng-pluralize:last').text()). - toBe('Nobody is viewing.'); - - using('.doc-example-live').input('personCount').enter('2'); - expect(element('.doc-example-live ng-pluralize:first').text()). - toBe('2 people are viewing.'); - expect(element('.doc-example-live ng-pluralize:last').text()). - toBe('Igor and Misko are viewing.'); - - using('.doc-example-live').input('personCount').enter('3'); - expect(element('.doc-example-live ng-pluralize:first').text()). - toBe('3 people are viewing.'); - expect(element('.doc-example-live ng-pluralize:last').text()). - toBe('Igor, Misko and one other person are viewing.'); - - using('.doc-example-live').input('personCount').enter('4'); - expect(element('.doc-example-live ng-pluralize:first').text()). - toBe('4 people are viewing.'); - expect(element('.doc-example-live ng-pluralize:last').text()). - toBe('Igor, Misko and 2 other people are viewing.'); - }); + var withoutOffset = element.all(by.css('ng-pluralize')).get(0); + var withOffset = element.all(by.css('ng-pluralize')).get(1); + var countInput = element(by.model('personCount')); - it('should show data-binded names', function() { - using('.doc-example-live').input('personCount').enter('4'); - expect(element('.doc-example-live ng-pluralize:last').text()). - toBe('Igor, Misko and 2 other people are viewing.'); + expect(withoutOffset.getText()).toEqual('1 person is viewing.'); + expect(withOffset.getText()).toEqual('Igor is viewing.'); - using('.doc-example-live').input('person1').enter('Di'); - using('.doc-example-live').input('person2').enter('Vojta'); - expect(element('.doc-example-live ng-pluralize:last').text()). - toBe('Di, Vojta and 2 other people are viewing.'); + countInput.clear(); + countInput.sendKeys('0'); + + expect(withoutOffset.getText()).toEqual('Nobody is viewing.'); + expect(withOffset.getText()).toEqual('Nobody is viewing.'); + + countInput.clear(); + countInput.sendKeys('2'); + + expect(withoutOffset.getText()).toEqual('2 people are viewing.'); + expect(withOffset.getText()).toEqual('Igor and Misko are viewing.'); + + countInput.clear(); + countInput.sendKeys('3'); + + expect(withoutOffset.getText()).toEqual('3 people are viewing.'); + expect(withOffset.getText()).toEqual('Igor, Misko and one other person are viewing.'); + + countInput.clear(); + countInput.sendKeys('4'); + + expect(withoutOffset.getText()).toEqual('4 people are viewing.'); + expect(withOffset.getText()).toEqual('Igor, Misko and 2 other people are viewing.'); + }); + it('should show data-bound names', function() { + var withOffset = element.all(by.css('ng-pluralize')).get(1); + var personCount = element(by.model('personCount')); + var person1 = element(by.model('person1')); + var person2 = element(by.model('person2')); + personCount.clear(); + personCount.sendKeys('4'); + person1.clear(); + person1.sendKeys('Di'); + person2.clear(); + person2.sendKeys('Vojta'); + expect(withOffset.getText()).toEqual('Di, Vojta and 2 other people are viewing.'); }); - + */ var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) { @@ -28856,25 +29124,27 @@ var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interp max-height:40px; }
- - it('should render initial data set', function() { - var r = using('.doc-example-live').repeater('ul li'); - expect(r.count()).toBe(10); - expect(r.row(0)).toEqual(["1","John","25"]); - expect(r.row(1)).toEqual(["2","Jessie","30"]); - expect(r.row(9)).toEqual(["10","Samantha","60"]); - expect(binding('friends.length')).toBe("10"); - }); + + var friends = element(by.css('.doc-example-live')) + .element.all(by.repeater('friend in friends')); + + it('should render initial data set', function() { + expect(friends.count()).toBe(10); + expect(friends.get(0).getText()).toEqual('[1] John who is 25 years old.'); + expect(friends.get(1).getText()).toEqual('[2] Jessie who is 30 years old.'); + expect(friends.last().getText()).toEqual('[10] Samantha who is 60 years old.'); + expect(element(by.binding('friends.length')).getText()) + .toMatch("I have 10 friends. They are:"); + }); it('should update repeater when filter predicate changes', function() { - var r = using('.doc-example-live').repeater('ul li'); - expect(r.count()).toBe(10); + expect(friends.count()).toBe(10); - input('q').enter('ma'); + element(by.css('.doc-example-live')).element(by.model('q')).sendKeys('ma'); - expect(r.count()).toBe(2); - expect(r.row(0)).toEqual(["1","Mary","28"]); - expect(r.row(1)).toEqual(["2","Samantha","60"]); + expect(friends.count()).toBe(2); + expect(friends.get(0).getText()).toEqual('[1] Mary who is 28 years old.'); + expect(friends.last().getText()).toEqual('[2] Samantha who is 60 years old.'); }); @@ -29208,16 +29478,19 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) { background:white; } - - it('should check ng-show / ng-hide', function() { - expect(element('.doc-example-live span:first:hidden').count()).toEqual(1); - expect(element('.doc-example-live span:last:visible').count()).toEqual(1); + + var thumbsUp = element(by.css('.doc-example-live span.icon-thumbs-up')); + var thumbsDown = element(by.css('.doc-example-live span.icon-thumbs-down')); - input('checked').check(); + it('should check ng-show / ng-hide', function() { + expect(thumbsUp.isDisplayed()).toBeFalsy(); + expect(thumbsDown.isDisplayed()).toBeTruthy(); - expect(element('.doc-example-live span:first:visible').count()).toEqual(1); - expect(element('.doc-example-live span:last:hidden').count()).toEqual(1); - }); + element(by.model('checked')).click(); + + expect(thumbsUp.isDisplayed()).toBeTruthy(); + expect(thumbsDown.isDisplayed()).toBeFalsy(); + }); */ @@ -29362,16 +29635,19 @@ var ngShowDirective = ['$animate', function($animate) { background:white; } - - it('should check ng-show / ng-hide', function() { - expect(element('.doc-example-live .check-element:first:hidden').count()).toEqual(1); - expect(element('.doc-example-live .check-element:last:visible').count()).toEqual(1); + + var thumbsUp = element(by.css('.doc-example-live span.icon-thumbs-up')); + var thumbsDown = element(by.css('.doc-example-live span.icon-thumbs-down')); - input('checked').check(); + it('should check ng-show / ng-hide', function() { + expect(thumbsUp.isDisplayed()).toBeFalsy(); + expect(thumbsDown.isDisplayed()).toBeTruthy(); - expect(element('.doc-example-live .check-element:first:visible').count()).toEqual(1); - expect(element('.doc-example-live .check-element:last:hidden').count()).toEqual(1); - }); + element(by.model('checked')).click(); + + expect(thumbsUp.isDisplayed()).toBeTruthy(); + expect(thumbsDown.isDisplayed()).toBeFalsy(); + }); */ @@ -29410,13 +29686,15 @@ var ngHideDirective = ['$animate', function($animate) { color: black; } - + + var colorSpan = element(by.css('.doc-example-live span')); + it('should check ng-style', function() { - expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)'); - element('.doc-example-live :button[value=set]').click(); - expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)'); - element('.doc-example-live :button[value=clear]').click(); - expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)'); + expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)'); + element(by.css('.doc-example-live input[value=set]')).click(); + expect(colorSpan.getCssValue('color')).toBe('rgba(255, 0, 0, 1)'); + element(by.css('.doc-example-live input[value=clear]')).click(); + expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)'); }); @@ -29441,7 +29719,7 @@ var ngStyleDirective = ngDirective(function(scope, element, attr) { * as specified in the template. * * The directive itself works similar to ngInclude, however, instead of downloading template code (or loading it - * from the template cache), `ngSwitch` simply choses one of the nested elements and makes it visible based on which element + * from the template cache), `ngSwitch` simply chooses one of the nested elements and makes it visible based on which element * matches the value obtained from the evaluated expression. In other words, you define a container element * (where you place the directive), place an expression on the **`on="..."` attribute** * (or the **`ng-switch="..."` attribute**), define any inner elements inside of the directive and place @@ -29537,17 +29815,20 @@ var ngStyleDirective = ngDirective(function(scope, element, attr) { top:0; } - + + var switchElem = element(by.css('.doc-example-live [ng-switch]')); + var select = element(by.model('selection')); + it('should start in settings', function() { - expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/); + expect(switchElem.getText()).toMatch(/Settings Div/); }); it('should change to home', function() { - select('selection').option('home'); - expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/); + select.element.all(by.css('option')).get(1).click(); + expect(switchElem.getText()).toMatch(/Home Span/); }); it('should select default', function() { - select('selection').option('other'); - expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/); + select.element.all(by.css('option')).get(2).click(); + expect(switchElem.getText()).toMatch(/default/); }); @@ -29654,35 +29935,32 @@ var ngSwitchDefaultDirective = ngDirective({ {{text}} - + it('should have transcluded', function() { - input('title').enter('TITLE'); - input('text').enter('TEXT'); - expect(binding('title')).toEqual('TITLE'); - expect(binding('text')).toEqual('TEXT'); + var titleElement = element(by.model('title')); + titleElement.clear(); + titleElement.sendKeys('TITLE'); + var textElement = element(by.model('text')); + textElement.clear(); + textElement.sendKeys('TEXT'); + expect(element(by.binding('title')).getText()).toEqual('TITLE'); + expect(element(by.binding('text')).getText()).toEqual('TEXT'); }); - + * */ var ngTranscludeDirective = ngDirective({ - controller: ['$element', '$transclude', function($element, $transclude) { + link: function($scope, $element, $attrs, controller, $transclude) { if (!$transclude) { throw minErr('ngTransclude')('orphan', - 'Illegal use of ngTransclude directive in the template! ' + - 'No parent directive that requires a transclusion found. ' + - 'Element: {0}', - startingTag($element)); + 'Illegal use of ngTransclude directive in the template! ' + + 'No parent directive that requires a transclusion found. ' + + 'Element: {0}', + startingTag($element)); } - - // remember the transclusion fn but call it during linking so that we don't process transclusion before directives on - // the parent element even when the transclusion replaces the current element. (we can't use priority here because - // that applies only to compile fns and not controllers - this.$transclude = $transclude; - }], - - link: function($scope, $element, $attrs, controller) { - controller.$transclude(function(clone) { + + $transclude(function(clone) { $element.empty(); $element.append(clone); }); @@ -29714,12 +29992,12 @@ var ngTranscludeDirective = ngDirective({ Load inlined template
- + it('should load template defined inside script tag', function() { - element('#tpl-link').click(); - expect(element('#tpl-content').text()).toMatch(/Content of the template/); + element(by.css('#tpl-link')).click(); + expect(element(by.css('#tpl-content')).getText()).toMatch(/Content of the template/); }); - + */ var scriptDirective = ['$templateCache', function($templateCache) { @@ -29767,7 +30045,7 @@ var ngOptionsMinErr = minErr('ngOptions'); * option. See example below for demonstration. * *
- * **Note:** `ngOptions` provides iterator facility for `
- + it('should check ng-options', function() { - expect(binding('{selected_color:color}')).toMatch('red'); - select('color').option('0'); - expect(binding('{selected_color:color}')).toMatch('black'); - using('.nullable').select('color').option(''); - expect(binding('{selected_color:color}')).toMatch('null'); + expect(element(by.binding('{selected_color:color}')).getText()).toMatch('red'); + element.all(by.select('color')).first().click(); + element.all(by.css('select[ng-model="color"] option')).first().click(); + expect(element(by.binding('{selected_color:color}')).getText()).toMatch('black'); + element(by.css('.nullable select[ng-model="color"]')).click(); + element.all(by.css('.nullable select[ng-model="color"] option')).first().click(); + expect(element(by.binding('{selected_color:color}')).getText()).toMatch('null'); }); - + */ @@ -32596,5 +32876,5 @@ if (config.autotest) { })(window, document); -!angular.$$csp() && angular.element(document).find('head').prepend(''); -!angular.$$csp() && angular.element(document).find('head').prepend(''); +!angular.$$csp() && angular.element(document).find('head').prepend(''); +!angular.$$csp() && angular.element(document).find('head').prepend(''); \ No newline at end of file diff --git a/config/lib/js/angular/angular.js b/config/lib/js/angular/angular.js index c9b7cbed31c..d67c9eee692 100755 --- a/config/lib/js/angular/angular.js +++ b/config/lib/js/angular/angular.js @@ -1,5 +1,5 @@ /** - * @license AngularJS v1.2.10 + * @license AngularJS v1.2.13 * (c) 2010-2014 Google, Inc. http://angularjs.org * License: MIT */ @@ -68,7 +68,7 @@ function minErr(module) { return match; }); - message = message + '\nhttp://errors.angularjs.org/1.2.10/' + + message = message + '\nhttp://errors.angularjs.org/1.2.13/' + (module ? module + '/' : '') + code; for (i = 2; i < arguments.length; i++) { message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' + @@ -160,6 +160,7 @@ function minErr(module) { -assertNotHasOwnProperty, -getter, -getBlockElements, + -hasOwnProperty, */ @@ -175,7 +176,7 @@ function minErr(module) { * @returns {string} Lowercased string. */ var lowercase = function(string){return isString(string) ? string.toLowerCase() : string;}; - +var hasOwnProperty = Object.prototype.hasOwnProperty; /** * @ngdoc function @@ -271,7 +272,7 @@ function isArrayLike(obj) { * is the value of an object property or an array element and `key` is the object property key or * array element index. Specifying a `context` for the function is optional. * - * It is worth nothing that `.forEach` does not iterate over inherited properties because it filters + * It is worth noting that `.forEach` does not iterate over inherited properties because it filters * using the `hasOwnProperty` method. *
@@ -280,7 +281,7 @@ function isArrayLike(obj) {
      angular.forEach(values, function(value, key){
        this.push(key + ': ' + value);
      }, log);
-     expect(log).toEqual(['name: misko', 'gender:male']);
+     expect(log).toEqual(['name: misko', 'gender: male']);
    
* * @param {Object|Array} obj Object to iterate over. @@ -851,7 +852,7 @@ function shallowCopy(src, dst) { for(var key in src) { // shallowCopy is only ever called by $compile nodeLinkFn, which has control over src // so we don't need to worry about using our custom hasOwnProperty here - if (src.hasOwnProperty(key) && key.charAt(0) !== '$' && key.charAt(1) !== '$') { + if (src.hasOwnProperty(key) && !(key.charAt(0) === '$' && key.charAt(1) === '$')) { dst[key] = src[key]; } } @@ -1210,6 +1211,7 @@ function encodeUriQuery(val, pctEncodeSpaces) {
I can add: {{a}} + {{b}} = {{ a+b }} +
angular.module('ngAppDemo', []).controller('ngAppDemoController', function($scope) { @@ -1834,11 +1836,11 @@ function setupModuleLoader(window) { * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat". */ var version = { - full: '1.2.10', // all of these placeholder strings will be replaced by grunt's + full: '1.2.13', // all of these placeholder strings will be replaced by grunt's major: 1, // package task minor: 2, - dot: 10, - codeName: 'augmented-serendipity' + dot: 13, + codeName: 'romantic-transclusion' }; @@ -2000,7 +2002,7 @@ function publishExternalAPI(angular){ * - [`after()`](http://api.jquery.com/after/) * - [`append()`](http://api.jquery.com/append/) * - [`attr()`](http://api.jquery.com/attr/) - * - [`bind()`](http://api.jquery.com/on/) - Does not support namespaces, selectors or eventData + * - [`bind()`](http://api.jquery.com/bind/) - Does not support namespaces, selectors or eventData * - [`children()`](http://api.jquery.com/children/) - Does not support selectors * - [`clone()`](http://api.jquery.com/clone/) * - [`contents()`](http://api.jquery.com/contents/) @@ -2027,7 +2029,7 @@ function publishExternalAPI(angular){ * - [`text()`](http://api.jquery.com/text/) * - [`toggleClass()`](http://api.jquery.com/toggleClass/) * - [`triggerHandler()`](http://api.jquery.com/triggerHandler/) - Passes a dummy event object to handlers. - * - [`unbind()`](http://api.jquery.com/off/) - Does not support namespaces + * - [`unbind()`](http://api.jquery.com/unbind/) - Does not support namespaces * - [`val()`](http://api.jquery.com/val/) * - [`wrap()`](http://api.jquery.com/wrap/) * @@ -2067,6 +2069,14 @@ var jqCache = JQLite.cache = {}, ? function(element, type, fn) {element.removeEventListener(type, fn, false); } : function(element, type, fn) {element.detachEvent('on' + type, fn); }); +/* + * !!! This is an undocumented "private" function !!! + */ +var jqData = JQLite._data = function(node) { + //jQuery always returns an object on cache miss + return this.cache[node[this.expando]] || {}; +}; + function jqNextId() { return ++jqId; } @@ -2135,6 +2145,9 @@ function JQLite(element) { if (element instanceof JQLite) { return element; } + if (isString(element)) { + element = trim(element); + } if (!(this instanceof JQLite)) { if (isString(element) && element.charAt(0) != '<') { throw jqLiteMinErr('nosel', 'Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element'); @@ -3408,17 +3421,16 @@ function annotate(fn) { * Here is an example of registering a service using * {@link AUTO.$provide#methods_service $provide.service(class)}. *
- *   $provide.service('ping', ['$http', function($http) {
- *     var Ping = function() {
- *       this.$http = $http;
- *     };
- *   
- *     Ping.prototype.send = function() {
- *       return this.$http.get('/ping');
- *     }; 
+ *   var Ping = function($http) {
+ *     this.$http = $http;
+ *   };
+ * 
+ *   Ping.$inject = ['$http'];
  *   
- *     return Ping;
- *   }]);
+ *   Ping.prototype.send = function() {
+ *     return this.$http.get('/ping');
+ *   };
+ *   $provide.service('ping', Ping);
  * 
* You would then inject and use this service like this: *
@@ -3516,7 +3528,7 @@ function annotate(fn) {
  * Here we decorate the {@link ng.$log $log} service to convert warnings to errors by intercepting
  * calls to {@link ng.$log#error $log.warn()}.
  * 
- *   $provider.decorator('$log', ['$delegate', function($delegate) {
+ *   $provide.decorator('$log', ['$delegate', function($delegate) {
  *     $delegate.warn = $delegate.error;
  *     return $delegate;
  *   }]);
@@ -4055,6 +4067,29 @@ var $AnimateProvider = ['$provide', function($provide) {
         done && $timeout(done, 0, false);
       },
 
+      /**
+       *
+       * @ngdoc function
+       * @name ng.$animate#setClass
+       * @methodOf ng.$animate
+       * @function
+       * @description Adds and/or removes the given CSS classes to and from the element.
+       * Once complete, the done() callback will be fired (if provided).
+       * @param {jQuery/jqLite element} element the element which will it's CSS classes changed
+       *   removed from it
+       * @param {string} add the CSS classes which will be added to the element
+       * @param {string} remove the CSS class which will be removed from the element
+       * @param {function=} done the callback function (if provided) that will be fired after the
+       *   CSS classes have been set on the element
+       */
+      setClass : function(element, add, remove, done) {
+        forEach(element, function (element) {
+          jqLiteAddClass(element, add);
+          jqLiteRemoveClass(element, remove);
+        });
+        done && $timeout(done, 0, false);
+      },
+
       enabled : noop
     };
   }];
@@ -5119,13 +5154,17 @@ function $TemplateCacheProvider() {
       
- + it('should auto compile', function() { - expect(element('div[compile]').text()).toBe('Hello Angular'); - input('html').enter('{{name}}!'); - expect(element('div[compile]').text()).toBe('Angular!'); + var textarea = $('textarea'); + var output = $('div[compile]'); + // The initial state reads 'Hello Angular'. + expect(output.getText()).toBe('Hello Angular'); + textarea.clear(); + textarea.sendKeys('{{name}}!'); + expect(output.getText()).toBe('Angular!'); }); - + * @@ -5193,7 +5232,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { var hasDirectives = {}, Suffix = 'Directive', COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\d\w\-_]+)\s+(.*)$/, - CLASS_DIRECTIVE_REGEXP = /(([\d\w\-_]+)(?:\:([^;]+))?;?)/; + CLASS_DIRECTIVE_REGEXP = /(([\d\w\-_]+)(?:\:([^;]+))?;?)/, + TABLE_CONTENT_REGEXP = /^<\s*(tr|th|td|tbody)(\s+[^>]*)?>/i; // Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes // The assumption is that future DOM event attribute names will begin with @@ -5380,8 +5420,16 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { * @param {string} oldClasses The former CSS className value */ $updateClass : function(newClasses, oldClasses) { - this.$removeClass(tokenDifference(oldClasses, newClasses)); - this.$addClass(tokenDifference(newClasses, oldClasses)); + var toAdd = tokenDifference(newClasses, oldClasses); + var toRemove = tokenDifference(oldClasses, newClasses); + + if(toAdd.length === 0) { + $animate.removeClass(this.$$element, toRemove); + } else if(toRemove.length === 0) { + $animate.addClass(this.$$element, toAdd); + } else { + $animate.setClass(this.$$element, toAdd, toRemove); + } }, /** @@ -5833,7 +5881,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { templateDirective = previousCompileContext.templateDirective, nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective, hasTranscludeDirective = false, - hasElementTranscludeDirective = false, + hasElementTranscludeDirective = previousCompileContext.hasElementTranscludeDirective, $compileNode = templateAttrs.$$element = jqLite(compileNode), directive, directiveName, @@ -5887,7 +5935,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { hasTranscludeDirective = true; // Special case ngIf and ngRepeat so that we don't complain about duplicate transclusion. - // This option should only be used by directives that know how to how to safely handle element transclusion, + // This option should only be used by directives that know how to safely handle element transclusion, // where the transcluded nodes are added or replaced after linking. if (!directive.$$tlb) { assertNoDuplicate('transclusion', nonTlbTranscludeDirective, directive, $compileNode); @@ -5934,9 +5982,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { if (directive.replace) { replaceDirective = directive; - $template = jqLite('
' + - trim(directiveValue) + - '
').contents(); + $template = directiveTemplateContents(directiveValue); compileNode = $template[0]; if ($template.length != 1 || compileNode.nodeType !== 1) { @@ -6007,6 +6053,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true; nodeLinkFn.transclude = hasTranscludeDirective && childTranscludeFn; + previousCompileContext.hasElementTranscludeDirective = hasElementTranscludeDirective; // might be normal or delayed nodeLinkFn depending on if templateUrl is present return nodeLinkFn; @@ -6334,6 +6381,28 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { } + function directiveTemplateContents(template) { + var type; + template = trim(template); + if ((type = TABLE_CONTENT_REGEXP.exec(template))) { + type = type[1].toLowerCase(); + var table = jqLite('' + template + '
'), + tbody = table.children('tbody'), + leaf = /(td|th)/.test(type) && table.find('tr'); + if (tbody.length && type !== 'tbody') { + table = tbody; + } + if (leaf && leaf.length) { + table = leaf; + } + return table.contents(); + } + return jqLite('
' + + template + + '
').contents(); + } + + function compileTemplateUrl(directives, $compileNode, tAttrs, $rootElement, childTranscludeFn, preLinkFns, postLinkFns, previousCompileContext) { var linkQueue = [], @@ -6358,7 +6427,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { content = denormalizeTemplate(content); if (origAsyncDirective.replace) { - $template = jqLite('
' + trim(content) + '
').contents(); + $template = directiveTemplateContents(content); compileNode = $template[0]; if ($template.length != 1 || compileNode.nodeType !== 1) { @@ -6402,9 +6471,18 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { linkNode = $compileNode[0]; if (beforeTemplateLinkNode !== beforeTemplateCompileNode) { - // it was cloned therefore we have to clone as well. - linkNode = jqLiteClone(compileNode); + var oldClasses = beforeTemplateLinkNode.className; + + if (!(previousCompileContext.hasElementTranscludeDirective && + origAsyncDirective.replace)) { + // it was cloned therefore we have to clone as well. + linkNode = jqLiteClone(compileNode); + } + replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode); + + // Copy in CSS classes from original node + safeAddClass(jqLite(linkNode), oldClasses); } if (afterTemplateNodeLinkFn.transclude) { childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude); @@ -7425,14 +7503,14 @@ function $HttpProvider() { -
- -
+ + - @@ -7469,27 +7547,34 @@ function $HttpProvider() { Hello, $http! - + + var status = element(by.binding('status')); + var data = element(by.binding('data')); + var fetchBtn = element(by.id('fetchbtn')); + var sampleGetBtn = element(by.id('samplegetbtn')); + var sampleJsonpBtn = element(by.id('samplejsonpbtn')); + var invalidJsonpBtn = element(by.id('invalidjsonpbtn')); + it('should make an xhr GET request', function() { - element(':button:contains("Sample GET")').click(); - element(':button:contains("fetch")').click(); - expect(binding('status')).toBe('200'); - expect(binding('data')).toMatch(/Hello, \$http!/); + sampleGetBtn.click(); + fetchBtn.click(); + expect(status.getText()).toMatch('200'); + expect(data.getText()).toMatch(/Hello, \$http!/) }); it('should make a JSONP request to angularjs.org', function() { - element(':button:contains("Sample JSONP")').click(); - element(':button:contains("fetch")').click(); - expect(binding('status')).toBe('200'); - expect(binding('data')).toMatch(/Super Hero!/); + sampleJsonpBtn.click(); + fetchBtn.click(); + expect(status.getText()).toMatch('200'); + expect(data.getText()).toMatch(/Super Hero!/); }); it('should make JSONP request to invalid URL and invoke the error handler', function() { - element(':button:contains("Invalid JSONP")').click(); - element(':button:contains("fetch")').click(); - expect(binding('status')).toBe('0'); - expect(binding('data')).toBe('Request failed'); + invalidJsonpBtn.click(); + fetchBtn.click(); + expect(status.getText()).toMatch('0'); + expect(data.getText()).toMatch('Request failed'); }); @@ -7871,13 +7956,18 @@ function $HttpProvider() { } function createXhr(method) { - // IE8 doesn't support PATCH method, but the ActiveX object does - /* global ActiveXObject */ - return (msie <= 8 && lowercase(method) === 'patch') - ? new ActiveXObject('Microsoft.XMLHTTP') - : new window.XMLHttpRequest(); -} + //if IE and the method is not RFC2616 compliant, or if XMLHttpRequest + //is not available, try getting an ActiveXObject. Otherwise, use XMLHttpRequest + //if it is available + if (msie <= 8 && (!method.match(/^(get|post|head|put|delete|options)$/i) || + !window.XMLHttpRequest)) { + return new window.ActiveXObject("Microsoft.XMLHTTP"); + } else if (window.XMLHttpRequest) { + return new window.XMLHttpRequest(); + } + throw minErr('$httpBackend')('noxhr', "This browser does not support XMLHttpRequest."); +} /** * @ngdoc object @@ -7972,7 +8062,20 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc } if (responseType) { - xhr.responseType = responseType; + try { + xhr.responseType = responseType; + } catch (e) { + // WebKit added support for the json responseType value on 09/03/2013 + // https://bugs.webkit.org/show_bug.cgi?id=73648. Versions of Safari prior to 7 are + // known to throw when setting the value "json" as the response type. Other older + // browsers implementing the responseType + // + // The json response type can be ignored if not supported, because JSON payloads are + // parsed on the client-side regardless. + if (responseType !== 'json') { + throw e; + } + } } xhr.send(post || null); @@ -8071,11 +8174,11 @@ var $interpolateMinErr = minErr('$interpolate'); //demo.label// - - it('should interpolate binding with custom symbols', function() { - expect(binding('demo.label')).toBe('This binding is brought you by // interpolation symbols.'); - }); - + + it('should interpolate binding with custom symbols', function() { + expect(element(by.binding('demo.label')).getText()).toBe('This binding is brought you by // interpolation symbols.'); + }); + */ function $InterpolateProvider() { @@ -8267,7 +8370,7 @@ function $InterpolateProvider() { * @description * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`. * - * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change + * Use {@link ng.$interpolateProvider#methods_endSymbol $interpolateProvider#endSymbol} to change * the symbol. * * @returns {string} start symbol. @@ -9111,7 +9214,7 @@ function $LocationProvider(){ * @eventType broadcast on root scope * @description * Broadcasted before a URL will change. This change can be prevented by calling - * `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on} for more + * `preventDefault` method of the event. See {@link ng.$rootScope.Scope#methods_$on} for more * details about event object. Upon successful change * {@link ng.$location#events_$locationChangeSuccess $locationChangeSuccess} is fired. * @@ -9294,7 +9397,7 @@ function $LogProvider(){ * @name ng.$logProvider#debugEnabled * @methodOf ng.$logProvider * @description - * @param {string=} flag enable or disable debug level messages + * @param {boolean=} flag enable or disable debug level messages * @returns {*} current value if used as getter or itself (chaining) if used as setter */ this.debugEnabled = function(flag) { @@ -10750,7 +10853,7 @@ function $ParseProvider() { * constructed via `$q.reject`, the promise will be rejected instead. * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to * resolving it with a rejection constructed via `$q.reject`. - * - `notify(value)` - provides updates on the status of the promises execution. This may be called + * - `notify(value)` - provides updates on the status of the promise's execution. This may be called * multiple times before the promise is either resolved or rejected. * * **Properties** @@ -10900,7 +11003,7 @@ function qFactory(nextTick, exceptionHandler) { reject: function(reason) { - deferred.resolve(reject(reason)); + deferred.resolve(createInternalRejectedPromise(reason)); }, @@ -11057,6 +11160,12 @@ function qFactory(nextTick, exceptionHandler) { * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`. */ var reject = function(reason) { + var result = defer(); + result.reject(reason); + return result.promise; + }; + + var createInternalRejectedPromise = function(reason) { return { then: function(callback, errback) { var result = defer(); @@ -12117,7 +12226,7 @@ function $RootScopeProvider(){ * onto the {@link ng.$exceptionHandler $exceptionHandler} service. * * @param {string} name Event name to emit. - * @param {...*} args Optional set of arguments which will be passed onto the event listeners. + * @param {...*} args Optional one or more arguments which will be passed onto the event listeners. * @return {Object} Event object (see {@link ng.$rootScope.Scope#methods_$on}). */ $emit: function(name, args) { @@ -12185,7 +12294,7 @@ function $RootScopeProvider(){ * onto the {@link ng.$exceptionHandler $exceptionHandler} service. * * @param {string} name Event name to broadcast. - * @param {...*} args Optional set of arguments which will be passed onto the event listeners. + * @param {...*} args Optional one or more arguments which will be passed onto the event listeners. * @return {Object} Event object, see {@link ng.$rootScope.Scope#methods_$on} */ $broadcast: function(name, args) { @@ -12977,13 +13086,15 @@ function $SceDelegateProvider() { ] - + describe('SCE doc demo', function() { it('should sanitize untrusted values', function() { - expect(element('.htmlComment').html()).toBe('Is anyone reading this?'); + expect(element(by.css('.htmlComment')).getInnerHtml()) + .toBe('Is anyone reading this?'); }); + it('should NOT sanitize explicitly trusted values', function() { - expect(element('#explicitlyTrustedHtml').html()).toBe( + expect(element(by.id('explicitlyTrustedHtml')).getInnerHtml()).toBe( 'Hover over this text.'); }); @@ -13742,13 +13853,13 @@ function urlIsSameOrigin(requestUrl) { - + it('should display the greeting in the input box', function() { - input('greeting').enter('Hello, E2E Tests'); + element(by.model('greeting')).sendKeys('Hello, E2E Tests'); // If we click the button it will block the test runner // element(':button').click(); }); - + */ function $WindowProvider(){ @@ -13957,35 +14068,47 @@ function $FilterProvider($provide) { Equality
- - - + + +
NamePhone
{{friend.name}}{{friend.phone}}
{{friendObj.name}}{{friendObj.phone}}
- - it('should search across all fields when filtering with a string', function() { - input('searchText').enter('m'); - expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')). - toEqual(['Mary', 'Mike', 'Adam']); + + var expectFriendNames = function(expectedNames, key) { + element.all(by.repeater(key + ' in friends').column(key + '.name')).then(function(arr) { + arr.forEach(function(wd, i) { + expect(wd.getText()).toMatch(expectedNames[i]); + }); + }); + }; - input('searchText').enter('76'); - expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')). - toEqual(['John', 'Julie']); + it('should search across all fields when filtering with a string', function() { + var searchText = element(by.model('searchText')); + searchText.clear(); + searchText.sendKeys('m'); + expectFriendNames(['Mary', 'Mike', 'Adam'], 'friend'); + + searchText.clear(); + searchText.sendKeys('76'); + expectFriendNames(['John', 'Julie'], 'friend'); }); it('should search in specific fields when filtering with a predicate object', function() { - input('search.$').enter('i'); - expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')). - toEqual(['Mary', 'Mike', 'Julie', 'Juliette']); + var searchAny = element(by.model('search.$')); + searchAny.clear(); + searchAny.sendKeys('i'); + expectFriendNames(['Mary', 'Mike', 'Julie', 'Juliette'], 'friendObj'); }); it('should use a equal comparison when comparator is true', function() { - input('search.name').enter('Julie'); - input('strict').check(); - expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')). - toEqual(['Julie']); + var searchName = element(by.model('search.name')); + var strict = element(by.model('strict')); + searchName.clear(); + searchName.sendKeys('Julie'); + strict.click(); + expectFriendNames(['Julie'], 'friendObj'); }); - + */ function filterFilter() { @@ -14011,6 +14134,15 @@ function filterFilter() { }; } else { comparator = function(obj, text) { + if (obj && text && typeof obj === 'object' && typeof text === 'object') { + for (var objKey in obj) { + if (objKey.charAt(0) !== '$' && hasOwnProperty.call(obj, objKey) && + comparator(obj[objKey], text[objKey])) { + return true; + } + } + return false; + } text = (''+text).toLowerCase(); return (''+obj).toLowerCase().indexOf(text) > -1; }; @@ -14063,7 +14195,7 @@ function filterFilter() { (function(path) { if (typeof expression[path] == 'undefined') return; predicates.push(function(value) { - return search(path == '$' ? value : getter(value, path), expression[path]); + return search(path == '$' ? value : (value && value[path]), expression[path]); }); })(key); } @@ -14109,21 +14241,27 @@ function filterFilter() {

- default currency symbol ($): {{amount | currency}}
- custom currency identifier (USD$): {{amount | currency:"USD$"}} + default currency symbol ($): {{amount | currency}}
+ custom currency identifier (USD$): {{amount | currency:"USD$"}}
- + it('should init with 1234.56', function() { - expect(binding('amount | currency')).toBe('$1,234.56'); - expect(binding('amount | currency:"USD$"')).toBe('USD$1,234.56'); + expect(element(by.id('currency-default')).getText()).toBe('$1,234.56'); + expect(element(by.binding('amount | currency:"USD$"')).getText()).toBe('USD$1,234.56'); }); it('should update', function() { - input('amount').enter('-1234'); - expect(binding('amount | currency')).toBe('($1,234.00)'); - expect(binding('amount | currency:"USD$"')).toBe('(USD$1,234.00)'); + if (browser.params.browser == 'safari') { + // Safari does not understand the minus key. See + // https://github.com/angular/protractor/issues/481 + return; + } + element(by.model('amount')).clear(); + element(by.model('amount')).sendKeys('-1234'); + expect(element(by.id('currency-default')).getText()).toBe('($1,234.00)'); + expect(element(by.binding('amount | currency:"USD$"')).getText()).toBe('(USD$1,234.00)'); }); - + */ currencyFilter.$inject = ['$locale']; @@ -14162,25 +14300,26 @@ function currencyFilter($locale) {
Enter number:
- Default formatting: {{val | number}}
- No fractions: {{val | number:0}}
- Negative number: {{-val | number:4}} + Default formatting: {{val | number}}
+ No fractions: {{val | number:0}}
+ Negative number: {{-val | number:4}}
- + it('should format numbers', function() { - expect(binding('val | number')).toBe('1,234.568'); - expect(binding('val | number:0')).toBe('1,235'); - expect(binding('-val | number:4')).toBe('-1,234.5679'); + expect(element(by.id('number-default')).getText()).toBe('1,234.568'); + expect(element(by.binding('val | number:0')).getText()).toBe('1,235'); + expect(element(by.binding('-val | number:4')).getText()).toBe('-1,234.5679'); }); it('should update', function() { - input('val').enter('3374.333'); - expect(binding('val | number')).toBe('3,374.333'); - expect(binding('val | number:0')).toBe('3,374'); - expect(binding('-val | number:4')).toBe('-3,374.3330'); - }); - + element(by.model('val')).clear(); + element(by.model('val')).sendKeys('3374.333'); + expect(element(by.id('number-default')).getText()).toBe('3,374.333'); + expect(element(by.binding('val | number:0')).getText()).toBe('3,374'); + expect(element(by.binding('-val | number:4')).getText()).toBe('-3,374.3330'); + }); + */ @@ -14410,22 +14549,22 @@ var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+ {{1288323623006 | date:'medium'}}: - {{1288323623006 | date:'medium'}}
+ {{1288323623006 | date:'medium'}}
{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}: - {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}
+ {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}
{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}: - {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}
+ {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}
- + it('should format date', function() { - expect(binding("1288323623006 | date:'medium'")). + expect(element(by.binding("1288323623006 | date:'medium'")).getText()). toMatch(/Oct 2\d, 2010 \d{1,2}:\d{2}:\d{2} (AM|PM)/); - expect(binding("1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'")). + expect(element(by.binding("1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'")).getText()). toMatch(/2010\-10\-2\d \d{2}:\d{2}:\d{2} (\-|\+)?\d{4}/); - expect(binding("'1288323623006' | date:'MM/dd/yyyy @ h:mma'")). + expect(element(by.binding("'1288323623006' | date:'MM/dd/yyyy @ h:mma'")).getText()). toMatch(/10\/2\d\/2010 @ \d{1,2}:\d{2}(AM|PM)/); }); - +
*/ dateFilter.$inject = ['$locale']; @@ -14524,11 +14663,11 @@ function dateFilter($locale) {
{{ {'name':'value'} | json }}
- + it('should jsonify filtered objects', function() { - expect(binding("{'name':'value'}")).toMatch(/\{\n "name": ?"value"\n}/); + expect(element(by.binding("{'name':'value'}")).getText()).toMatch(/\{\n "name": ?"value"\n}/); }); - + * */ @@ -14596,28 +14735,37 @@ var uppercaseFilter = valueFn(uppercase);

Output letters: {{ letters | limitTo:letterLimit }}

- + + var numLimitInput = element(by.model('numLimit')); + var letterLimitInput = element(by.model('letterLimit')); + var limitedNumbers = element(by.binding('numbers | limitTo:numLimit')); + var limitedLetters = element(by.binding('letters | limitTo:letterLimit')); + it('should limit the number array to first three items', function() { - expect(element('.doc-example-live input[ng-model=numLimit]').val()).toBe('3'); - expect(element('.doc-example-live input[ng-model=letterLimit]').val()).toBe('3'); - expect(binding('numbers | limitTo:numLimit')).toEqual('[1,2,3]'); - expect(binding('letters | limitTo:letterLimit')).toEqual('abc'); + expect(numLimitInput.getAttribute('value')).toBe('3'); + expect(letterLimitInput.getAttribute('value')).toBe('3'); + expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3]'); + expect(limitedLetters.getText()).toEqual('Output letters: abc'); }); it('should update the output when -3 is entered', function() { - input('numLimit').enter(-3); - input('letterLimit').enter(-3); - expect(binding('numbers | limitTo:numLimit')).toEqual('[7,8,9]'); - expect(binding('letters | limitTo:letterLimit')).toEqual('ghi'); + numLimitInput.clear(); + numLimitInput.sendKeys('-3'); + letterLimitInput.clear(); + letterLimitInput.sendKeys('-3'); + expect(limitedNumbers.getText()).toEqual('Output numbers: [7,8,9]'); + expect(limitedLetters.getText()).toEqual('Output letters: ghi'); }); it('should not exceed the maximum size of input array', function() { - input('numLimit').enter(100); - input('letterLimit').enter(100); - expect(binding('numbers | limitTo:numLimit')).toEqual('[1,2,3,4,5,6,7,8,9]'); - expect(binding('letters | limitTo:letterLimit')).toEqual('abcdefghi'); + numLimitInput.clear(); + numLimitInput.sendKeys('100'); + letterLimitInput.clear(); + letterLimitInput.sendKeys('100'); + expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3,4,5,6,7,8,9]'); + expect(limitedLetters.getText()).toEqual('Output letters: abcdefghi'); }); - + */ function limitToFilter(){ @@ -14718,29 +14866,6 @@ function limitToFilter(){ - - it('should be reverse ordered by aged', function() { - expect(binding('predicate')).toBe('-age'); - expect(repeater('table.friend', 'friend in friends').column('friend.age')). - toEqual(['35', '29', '21', '19', '10']); - expect(repeater('table.friend', 'friend in friends').column('friend.name')). - toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']); - }); - - it('should reorder the table when user selects different predicate', function() { - element('.doc-example-live a:contains("Name")').click(); - expect(repeater('table.friend', 'friend in friends').column('friend.name')). - toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']); - expect(repeater('table.friend', 'friend in friends').column('friend.age')). - toEqual(['35', '10', '29', '19', '21']); - - element('.doc-example-live a:contains("Phone")').click(); - expect(repeater('table.friend', 'friend in friends').column('friend.phone')). - toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']); - expect(repeater('table.friend', 'friend in friends').column('friend.name')). - toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']); - }); - */ orderByFilter.$inject = ['$parse']; @@ -14894,46 +15019,55 @@ var htmlAnchorDirective = valueFn({ anchor (no link)
link (link, change location) - + it('should execute ng-click but not reload when href without value', function() { - element('#link-1').click(); - expect(input('value').val()).toEqual('1'); - expect(element('#link-1').attr('href')).toBe(""); + element(by.id('link-1')).click(); + expect(element(by.model('value')).getAttribute('value')).toEqual('1'); + expect(element(by.id('link-1')).getAttribute('href')).toBe(''); }); it('should execute ng-click but not reload when href empty string', function() { - element('#link-2').click(); - expect(input('value').val()).toEqual('2'); - expect(element('#link-2').attr('href')).toBe(""); + element(by.id('link-2')).click(); + expect(element(by.model('value')).getAttribute('value')).toEqual('2'); + expect(element(by.id('link-2')).getAttribute('href')).toBe(''); }); it('should execute ng-click and change url when ng-href specified', function() { - expect(element('#link-3').attr('href')).toBe("/123"); + expect(element(by.id('link-3')).getAttribute('href')).toMatch(/\/123$/); - element('#link-3').click(); - expect(browser().window().path()).toEqual('/123'); + element(by.id('link-3')).click(); + + // At this point, we navigate away from an Angular page, so we need + // to use browser.driver to get the base webdriver. + + browser.wait(function() { + return browser.driver.getCurrentUrl().then(function(url) { + return url.match(/\/123$/); + }); + }, 1000, 'page should navigate to /123'); }); it('should execute ng-click but not reload when href empty string and name specified', function() { - element('#link-4').click(); - expect(input('value').val()).toEqual('4'); - expect(element('#link-4').attr('href')).toBe(''); + element(by.id('link-4')).click(); + expect(element(by.model('value')).getAttribute('value')).toEqual('4'); + expect(element(by.id('link-4')).getAttribute('href')).toBe(''); }); it('should execute ng-click but not reload when no href but name specified', function() { - element('#link-5').click(); - expect(input('value').val()).toEqual('5'); - expect(element('#link-5').attr('href')).toBe(undefined); + element(by.id('link-5')).click(); + expect(element(by.model('value')).getAttribute('value')).toEqual('5'); + expect(element(by.id('link-5')).getAttribute('href')).toBe(null); }); it('should only change url when only ng-href', function() { - input('value').enter('6'); - expect(element('#link-6').attr('href')).toBe('6'); + element(by.model('value')).clear(); + element(by.model('value')).sendKeys('6'); + expect(element(by.id('link-6')).getAttribute('href')).toMatch(/\/6$/); - element('#link-6').click(); - expect(browser().location().url()).toEqual('/6'); + element(by.id('link-6')).click(); + expect(browser.getCurrentUrl()).toMatch(/\/6$/); }); - + */ @@ -15018,13 +15152,13 @@ var htmlAnchorDirective = valueFn({ Click me to toggle:
- + it('should toggle button', function() { - expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy(); - input('checked').check(); - expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy(); + expect(element(by.css('.doc-example-live button')).getAttribute('disabled')).toBeFalsy(); + element(by.model('checked')).click(); + expect(element(by.css('.doc-example-live button')).getAttribute('disabled')).toBeTruthy(); }); - + * * @element INPUT @@ -15053,13 +15187,13 @@ var htmlAnchorDirective = valueFn({ Check me to check both:
- + it('should check both checkBoxes', function() { - expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy(); - input('master').check(); - expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy(); + expect(element(by.id('checkSlave')).getAttribute('checked')).toBeFalsy(); + element(by.model('master')).click(); + expect(element(by.id('checkSlave')).getAttribute('checked')).toBeTruthy(); }); - + * * @element INPUT @@ -15088,13 +15222,13 @@ var htmlAnchorDirective = valueFn({ Check me to make text readonly:
- + it('should toggle readonly attr', function() { - expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy(); - input('checked').check(); - expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy(); + expect(element(by.css('.doc-example-live [type="text"]')).getAttribute('readonly')).toBeFalsy(); + element(by.model('checked')).click(); + expect(element(by.css('.doc-example-live [type="text"]')).getAttribute('readonly')).toBeTruthy(); }); - + * * @element INPUT @@ -15127,13 +15261,13 @@ var htmlAnchorDirective = valueFn({ - + it('should select Greetings!', function() { - expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy(); - input('selected').check(); - expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy(); + expect(element(by.id('greet')).getAttribute('selected')).toBeFalsy(); + element(by.model('selected')).click(); + expect(element(by.id('greet')).getAttribute('selected')).toBeTruthy(); }); - + * * @element OPTION @@ -15163,13 +15297,13 @@ var htmlAnchorDirective = valueFn({ Show/Hide me - + it('should toggle open', function() { - expect(element('#details').prop('open')).toBeFalsy(); - input('open').check(); - expect(element('#details').prop('open')).toBeTruthy(); + expect(element(by.id('details')).getAttribute('open')).toBeFalsy(); + element(by.model('open')).click(); + expect(element(by.id('details')).getAttribute('open')).toBeTruthy(); }); - + * * @element DETAILS @@ -15528,18 +15662,27 @@ function FormController(element, attrs) { myForm.$error.required = {{!!myForm.$error.required}}
- + it('should initialize to model', function() { - expect(binding('userType')).toEqual('guest'); - expect(binding('myForm.input.$valid')).toEqual('true'); + var userType = element(by.binding('userType')); + var valid = element(by.binding('myForm.input.$valid')); + + expect(userType.getText()).toContain('guest'); + expect(valid.getText()).toContain('true'); }); it('should be invalid if empty', function() { - input('userType').enter(''); - expect(binding('userType')).toEqual(''); - expect(binding('myForm.input.$valid')).toEqual('false'); + var userType = element(by.binding('userType')); + var valid = element(by.binding('myForm.input.$valid')); + var userInput = element(by.model('userType')); + + userInput.clear(); + userInput.sendKeys(''); + + expect(userType.getText()).toEqual('userType ='); + expect(valid.getText()).toContain('false'); }); - + */ var formDirectiveFactory = function(isNgForm) { @@ -15664,29 +15807,31 @@ var inputType = { myForm.$error.required = {{!!myForm.$error.required}}
- + + var text = element(by.binding('text')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('text')); + it('should initialize to model', function() { - expect(binding('text')).toEqual('guest'); - expect(binding('myForm.input.$valid')).toEqual('true'); + expect(text.getText()).toContain('guest'); + expect(valid.getText()).toContain('true'); }); it('should be invalid if empty', function() { - input('text').enter(''); - expect(binding('text')).toEqual(''); - expect(binding('myForm.input.$valid')).toEqual('false'); + input.clear(); + input.sendKeys(''); + + expect(text.getText()).toEqual('text ='); + expect(valid.getText()).toContain('false'); }); it('should be invalid if multi word', function() { - input('text').enter('hello world'); - expect(binding('myForm.input.$valid')).toEqual('false'); - }); + input.clear(); + input.sendKeys('hello world'); - it('should not be trimmed', function() { - input('text').enter('untrimmed '); - expect(binding('text')).toEqual('untrimmed '); - expect(binding('myForm.input.$valid')).toEqual('true'); + expect(valid.getText()).toContain('false'); }); - + */ 'text': textInputType, @@ -15740,24 +15885,30 @@ var inputType = { myForm.$error.required = {{!!myForm.$error.required}}
- + + var value = element(by.binding('value')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('value')); + it('should initialize to model', function() { - expect(binding('value')).toEqual('12'); - expect(binding('myForm.input.$valid')).toEqual('true'); + expect(value.getText()).toContain('12'); + expect(valid.getText()).toContain('true'); }); it('should be invalid if empty', function() { - input('value').enter(''); - expect(binding('value')).toEqual(''); - expect(binding('myForm.input.$valid')).toEqual('false'); + input.clear(); + input.sendKeys(''); + expect(value.getText()).toEqual('value ='); + expect(valid.getText()).toContain('false'); }); it('should be invalid if over max', function() { - input('value').enter('123'); - expect(binding('value')).toEqual(''); - expect(binding('myForm.input.$valid')).toEqual('false'); + input.clear(); + input.sendKeys('123'); + expect(value.getText()).toEqual('value ='); + expect(valid.getText()).toContain('false'); }); - + */ 'number': numberInputType, @@ -15809,23 +15960,31 @@ var inputType = { myForm.$error.url = {{!!myForm.$error.url}}
- + + var text = element(by.binding('text')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('text')); + it('should initialize to model', function() { - expect(binding('text')).toEqual('http://google.com'); - expect(binding('myForm.input.$valid')).toEqual('true'); + expect(text.getText()).toContain('http://google.com'); + expect(valid.getText()).toContain('true'); }); it('should be invalid if empty', function() { - input('text').enter(''); - expect(binding('text')).toEqual(''); - expect(binding('myForm.input.$valid')).toEqual('false'); + input.clear(); + input.sendKeys(''); + + expect(text.getText()).toEqual('text ='); + expect(valid.getText()).toContain('false'); }); it('should be invalid if not url', function() { - input('text').enter('xxx'); - expect(binding('myForm.input.$valid')).toEqual('false'); + input.clear(); + input.sendKeys('box'); + + expect(valid.getText()).toContain('false'); }); - + */ 'url': urlInputType, @@ -15877,23 +16036,30 @@ var inputType = { myForm.$error.email = {{!!myForm.$error.email}}
- + + var text = element(by.binding('text')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('text')); + it('should initialize to model', function() { - expect(binding('text')).toEqual('me@example.com'); - expect(binding('myForm.input.$valid')).toEqual('true'); + expect(text.getText()).toContain('me@example.com'); + expect(valid.getText()).toContain('true'); }); it('should be invalid if empty', function() { - input('text').enter(''); - expect(binding('text')).toEqual(''); - expect(binding('myForm.input.$valid')).toEqual('false'); + input.clear(); + input.sendKeys(''); + expect(text.getText()).toEqual('text ='); + expect(valid.getText()).toContain('false'); }); it('should be invalid if not email', function() { - input('text').enter('xxx'); - expect(binding('myForm.input.$valid')).toEqual('false'); + input.clear(); + input.sendKeys('xxx'); + + expect(valid.getText()).toContain('false'); }); - + */ 'email': emailInputType, @@ -15934,14 +16100,17 @@ var inputType = { 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"'); + var color = element(by.binding('color')); - input('color').select('red'); - expect(binding('color')).toEqual('"red"'); + expect(color.getText()).toContain('blue'); + + element.all(by.model('color')).get(0).click(); + + expect(color.getText()).toContain('red'); }); - + */ 'radio': radioInputType, @@ -15978,17 +16147,21 @@ var inputType = { value2 = {{value2}}
- + it('should change state', function() { - expect(binding('value1')).toEqual('true'); - expect(binding('value2')).toEqual('YES'); + var value1 = element(by.binding('value1')); + var value2 = element(by.binding('value2')); + + expect(value1.getText()).toContain('true'); + expect(value2.getText()).toContain('YES'); + + element(by.model('value1')).click(); + element(by.model('value2')).click(); - input('value1').check(); - input('value2').check(); - expect(binding('value1')).toEqual('false'); - expect(binding('value2')).toEqual('NO'); + expect(value1.getText()).toContain('false'); + expect(value2.getText()).toContain('NO'); }); - + */ 'checkbox': checkboxInputType, @@ -15996,7 +16169,8 @@ var inputType = { 'hidden': noop, 'button': noop, 'submit': noop, - 'reset': noop + 'reset': noop, + 'file': noop }; // A helper function to call $setValidity and return the value / undefined, @@ -16019,6 +16193,7 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) { element.on('compositionend', function() { composing = false; + listener(); }); } @@ -16341,44 +16516,59 @@ function checkboxInputType(scope, element, attr, ctrl) { myForm.$error.maxlength = {{!!myForm.$error.maxlength}}
- + + var user = element(by.binding('{{user}}')); + var userNameValid = element(by.binding('myForm.userName.$valid')); + var lastNameValid = element(by.binding('myForm.lastName.$valid')); + var lastNameError = element(by.binding('myForm.lastName.$error')); + var formValid = element(by.binding('myForm.$valid')); + var userNameInput = element(by.model('user.name')); + var userLastInput = element(by.model('user.last')); + it('should initialize to model', function() { - expect(binding('user')).toEqual('{"name":"guest","last":"visitor"}'); - expect(binding('myForm.userName.$valid')).toEqual('true'); - expect(binding('myForm.$valid')).toEqual('true'); + expect(user.getText()).toContain('{"name":"guest","last":"visitor"}'); + expect(userNameValid.getText()).toContain('true'); + expect(formValid.getText()).toContain('true'); }); it('should be invalid if empty when required', function() { - input('user.name').enter(''); - expect(binding('user')).toEqual('{"last":"visitor"}'); - expect(binding('myForm.userName.$valid')).toEqual('false'); - expect(binding('myForm.$valid')).toEqual('false'); + userNameInput.clear(); + userNameInput.sendKeys(''); + + expect(user.getText()).toContain('{"last":"visitor"}'); + expect(userNameValid.getText()).toContain('false'); + expect(formValid.getText()).toContain('false'); }); it('should be valid if empty when min length is set', function() { - input('user.last').enter(''); - expect(binding('user')).toEqual('{"name":"guest","last":""}'); - expect(binding('myForm.lastName.$valid')).toEqual('true'); - expect(binding('myForm.$valid')).toEqual('true'); + userLastInput.clear(); + userLastInput.sendKeys(''); + + expect(user.getText()).toContain('{"name":"guest","last":""}'); + expect(lastNameValid.getText()).toContain('true'); + expect(formValid.getText()).toContain('true'); }); it('should be invalid if less than required min length', function() { - input('user.last').enter('xx'); - expect(binding('user')).toEqual('{"name":"guest"}'); - expect(binding('myForm.lastName.$valid')).toEqual('false'); - expect(binding('myForm.lastName.$error')).toMatch(/minlength/); - expect(binding('myForm.$valid')).toEqual('false'); + userLastInput.clear(); + userLastInput.sendKeys('xx'); + + expect(user.getText()).toContain('{"name":"guest"}'); + expect(lastNameValid.getText()).toContain('false'); + expect(lastNameError.getText()).toContain('minlength'); + expect(formValid.getText()).toContain('false'); }); it('should be invalid if longer than max length', function() { - input('user.last').enter('some ridiculously long name'); - expect(binding('user')) - .toEqual('{"name":"guest"}'); - expect(binding('myForm.lastName.$valid')).toEqual('false'); - expect(binding('myForm.lastName.$error')).toMatch(/maxlength/); - expect(binding('myForm.$valid')).toEqual('false'); + userLastInput.clear(); + userLastInput.sendKeys('some ridiculously long name'); + + expect(user.getText()).toContain('{"name":"guest"}'); + expect(lastNameValid.getText()).toContain('false'); + expect(lastNameError.getText()).toContain('maxlength'); + expect(formValid.getText()).toContain('false'); }); - + */ var inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) { @@ -16510,14 +16700,23 @@ var VALID_CLASS = 'ng-valid',
- + it('should data-bind and become invalid', function() { - var contentEditable = element('[contenteditable]'); + if (browser.params.browser = 'safari') { + // SafariDriver can't handle contenteditable. + return; + }; + var contentEditable = element(by.css('.doc-example-live [contenteditable]')); + + expect(contentEditable.getText()).toEqual('Change me!'); + + // Firefox driver doesn't trigger the proper events on 'clear', so do this hack + contentEditable.click(); + contentEditable.sendKeys(protractor.Key.chord(protractor.Key.COMMAND, "a")); + contentEditable.sendKeys(protractor.Key.BACK_SPACE); - expect(contentEditable.text()).toEqual('Change me!'); - input('userContent').enter(''); - expect(contentEditable.text()).toEqual(''); - expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/); + expect(contentEditable.getText()).toEqual(''); + expect(contentEditable.getAttribute('class')).toMatch(/ng-invalid-required/); }); * @@ -16570,6 +16769,9 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$ * You can override this for input directives whose concept of being empty is different to the * default. The `checkboxInputType` directive does this because in its case a value of `false` * implies empty. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is empty. */ this.$isEmpty = function(value) { return isUndefined(value) || value === '' || value === null || value !== value; @@ -16824,24 +17026,30 @@ var ngModelDirective = function() { * * *
- * debug = {{confirmed}}
- * counter = {{counter}} + * debug = {{confirmed}}
+ * counter = {{counter}}
* * - * + * + * var counter = element(by.binding('counter')); + * var debug = element(by.binding('confirmed')); + * * it('should evaluate the expression if changing from view', function() { - * expect(binding('counter')).toEqual('0'); - * element('#ng-change-example1').click(); - * expect(binding('counter')).toEqual('1'); - * expect(binding('confirmed')).toEqual('true'); + * expect(counter.getText()).toContain('0'); + * + * element(by.id('ng-change-example1')).click(); + * + * expect(counter.getText()).toContain('1'); + * expect(debug.getText()).toContain('true'); * }); * * it('should not evaluate the expression if changing from model', function() { - * element('#ng-change-example2').click(); - * expect(binding('counter')).toEqual('0'); - * expect(binding('confirmed')).toEqual('true'); + * element(by.id('ng-change-example2')).click(); + + * expect(counter.getText()).toContain('0'); + * expect(debug.getText()).toContain('true'); * }); - * + * * */ var ngChangeDirective = valueFn({ @@ -16914,20 +17122,26 @@ var requiredDirective = function() { myForm.$error.required = {{!!myForm.$error.required}}
- + + var listInput = element(by.model('names')); + var names = element(by.binding('{{names}}')); + var valid = element(by.binding('myForm.namesInput.$valid')); + var error = element(by.css('span.error')); + it('should initialize to model', function() { - expect(binding('names')).toEqual('["igor","misko","vojta"]'); - expect(binding('myForm.namesInput.$valid')).toEqual('true'); - expect(element('span.error').css('display')).toBe('none'); + expect(names.getText()).toContain('["igor","misko","vojta"]'); + expect(valid.getText()).toContain('true'); + expect(error.getCssValue('display')).toBe('none'); }); it('should be invalid if empty', function() { - input('names').enter(''); - expect(binding('names')).toEqual(''); - expect(binding('myForm.namesInput.$valid')).toEqual('false'); - expect(element('span.error').css('display')).not().toBe('none'); - }); - + listInput.clear(); + listInput.sendKeys(''); + + expect(names.getText()).toContain(''); + expect(valid.getText()).toContain('false'); + expect(error.getCssValue('display')).not.toBe('none'); }); + */ var ngListDirective = function() { @@ -17009,15 +17223,17 @@ var CONSTANT_VALUE_REGEXP = /^(true|false|\d+)$/;
You chose {{my.favorite}}
- + + var favorite = element(by.binding('my.favorite')); + it('should initialize to model', function() { - expect(binding('my.favorite')).toEqual('unicorns'); + expect(favorite.getText()).toContain('unicorns'); }); it('should bind the values to the inputs', function() { - input('my.favorite').select('pizza'); - expect(binding('my.favorite')).toEqual('pizza'); + element.all(by.model('my.favorite')).get(0).click(); + expect(favorite.getText()).toContain('pizza'); }); - + */ var ngValueDirective = function() { @@ -17077,13 +17293,17 @@ var ngValueDirective = function() { Hello ! - + it('should check ng-bind', function() { - expect(using('.doc-example-live').binding('name')).toBe('Whirled'); - using('.doc-example-live').input('name').enter('world'); - expect(using('.doc-example-live').binding('name')).toBe('world'); + var exampleContainer = $('.doc-example-live'); + var nameInput = element(by.model('name')); + + expect(exampleContainer.findElement(by.binding('name')).getText()).toBe('Whirled'); + nameInput.clear(); + nameInput.sendKeys('world'); + expect(exampleContainer.findElement(by.binding('name')).getText()).toBe('world'); }); - + */ var ngBindDirective = ngDirective(function(scope, element, attr) { @@ -17129,20 +17349,22 @@ var ngBindDirective = ngDirective(function(scope, element, attr) {

        
      
-     
+     
        it('should check ng-bind', function() {
-         expect(using('.doc-example-live').binding('salutation')).
-           toBe('Hello');
-         expect(using('.doc-example-live').binding('name')).
-           toBe('World');
-         using('.doc-example-live').input('salutation').enter('Greetings');
-         using('.doc-example-live').input('name').enter('user');
-         expect(using('.doc-example-live').binding('salutation')).
-           toBe('Greetings');
-         expect(using('.doc-example-live').binding('name')).
-           toBe('user');
+         var salutationElem = element(by.binding('salutation'));
+         var salutationInput = element(by.model('salutation'));
+         var nameInput = element(by.model('name'));
+
+         expect(salutationElem.getText()).toBe('Hello World!');
+
+         salutationInput.clear();
+         salutationInput.sendKeys('Greetings');
+         nameInput.clear();
+         nameInput.sendKeys('user');
+
+         expect(salutationElem.getText()).toBe('Greetings user!');
        });
-     
+     
    
  */
 var ngBindTemplateDirective = ['$interpolate', function($interpolate) {
@@ -17195,12 +17417,10 @@ var ngBindTemplateDirective = ['$interpolate', function($interpolate) {
        }]);
      
- + it('should check ng-bind-html', function() { - expect(using('.doc-example-live').binding('myHTML')). - toBe( - 'I am an HTMLstring with links! and other stuff' - ); + expect(element(by.binding('myHTML')).getText()).toBe( + 'I am an HTMLstring with links! and other stuff'); }); @@ -17332,31 +17552,34 @@ function classDirective(name, selector) { color: red; } - + + var ps = element.all(by.css('.doc-example-live p')); + it('should let you toggle the class', function() { - expect(element('.doc-example-live p:first').prop('className')).not().toMatch(/bold/); - expect(element('.doc-example-live p:first').prop('className')).not().toMatch(/red/); + expect(ps.first().getAttribute('class')).not.toMatch(/bold/); + expect(ps.first().getAttribute('class')).not.toMatch(/red/); - input('important').check(); - expect(element('.doc-example-live p:first').prop('className')).toMatch(/bold/); + element(by.model('important')).click(); + expect(ps.first().getAttribute('class')).toMatch(/bold/); - input('error').check(); - expect(element('.doc-example-live p:first').prop('className')).toMatch(/red/); + element(by.model('error')).click(); + expect(ps.first().getAttribute('class')).toMatch(/red/); }); it('should let you toggle string example', function() { - expect(element('.doc-example-live p:nth-of-type(2)').prop('className')).toBe(''); - input('style').enter('red'); - expect(element('.doc-example-live p:nth-of-type(2)').prop('className')).toBe('red'); + expect(ps.get(1).getAttribute('class')).toBe(''); + element(by.model('style')).clear(); + element(by.model('style')).sendKeys('red'); + expect(ps.get(1).getAttribute('class')).toBe('red'); }); it('array example should have 3 classes', function() { - expect(element('.doc-example-live p:last').prop('className')).toBe(''); - input('style1').enter('bold'); - input('style2').enter('strike'); - input('style3').enter('red'); - expect(element('.doc-example-live p:last').prop('className')).toBe('bold strike red'); + expect(ps.last().getAttribute('class')).toBe(''); + element(by.model('style1')).sendKeys('bold'); + element(by.model('style2')).sendKeys('strike'); + element(by.model('style3')).sendKeys('red'); + expect(ps.last().getAttribute('class')).toBe('bold strike red'); }); @@ -17367,8 +17590,8 @@ function classDirective(name, selector) { - - + +
Sample Text
@@ -17383,19 +17606,19 @@ function classDirective(name, selector) { font-size:3em; }
- + it('should check ng-class', function() { - expect(element('.doc-example-live span').prop('className')).not(). + expect(element(by.css('.base-class')).getAttribute('class')).not. toMatch(/my-class/); - using('.doc-example-live').element(':button:first').click(); + element(by.id('setbtn')).click(); - expect(element('.doc-example-live span').prop('className')). + expect(element(by.css('.base-class')).getAttribute('class')). toMatch(/my-class/); - using('.doc-example-live').element(':button:last').click(); + element(by.id('clearbtn')).click(); - expect(element('.doc-example-live span').prop('className')).not(). + expect(element(by.css('.base-class')).getAttribute('class')).not. toMatch(/my-class/); }); @@ -17447,11 +17670,11 @@ var ngClassDirective = classDirective('', true); color: blue; } - + it('should check ng-class-odd and ng-class-even', function() { - expect(element('.doc-example-live li:first span').prop('className')). + expect(element(by.repeater('name in names').row(0).column('name')).getAttribute('class')). toMatch(/odd/); - expect(element('.doc-example-live li:last span').prop('className')). + expect(element(by.repeater('name in names').row(1).column('name')).getAttribute('class')). toMatch(/even/); }); @@ -17495,11 +17718,11 @@ var ngClassOddDirective = classDirective('Odd', 0); color: blue; } - + it('should check ng-class-odd and ng-class-even', function() { - expect(element('.doc-example-live li:first span').prop('className')). + expect(element(by.repeater('name in names').row(0).column('name')).getAttribute('class')). toMatch(/odd/); - expect(element('.doc-example-live li:last span').prop('className')). + expect(element(by.repeater('name in names').row(1).column('name')).getAttribute('class')). toMatch(/even/); }); @@ -17552,14 +17775,14 @@ var ngClassEvenDirective = classDirective('Even', 1);
{{ 'hello' }}
{{ 'hello IE7' }}
- + it('should remove the template directive and css class', function() { - expect(element('.doc-example-live #template1').attr('ng-cloak')). - not().toBeDefined(); - expect(element('.doc-example-live #template2').attr('ng-cloak')). - not().toBeDefined(); + expect($('.doc-example-live #template1').getAttribute('ng-cloak')). + toBeNull(); + expect($('.doc-example-live #template2').getAttribute('ng-cloak')). + toBeNull(); }); - + * */ @@ -17652,22 +17875,36 @@ var ngCloakDirective = ngDirective({ - + it('should check controller as', function() { - expect(element('#ctrl-as-exmpl>:input').val()).toBe('John Smith'); - expect(element('#ctrl-as-exmpl li:nth-child(1) input').val()) - .toBe('408 555 1212'); - expect(element('#ctrl-as-exmpl li:nth-child(2) input').val()) - .toBe('john.smith@example.org'); - - element('#ctrl-as-exmpl li:first a:contains("clear")').click(); - expect(element('#ctrl-as-exmpl li:first input').val()).toBe(''); - - element('#ctrl-as-exmpl li:last a:contains("add")').click(); - expect(element('#ctrl-as-exmpl li:nth-child(3) input').val()) - .toBe('yourname@example.org'); + var container = element(by.id('ctrl-as-exmpl')); + + expect(container.findElement(by.model('settings.name')) + .getAttribute('value')).toBe('John Smith'); + + var firstRepeat = + container.findElement(by.repeater('contact in settings.contacts').row(0)); + var secondRepeat = + container.findElement(by.repeater('contact in settings.contacts').row(1)); + + expect(firstRepeat.findElement(by.model('contact.value')).getAttribute('value')) + .toBe('408 555 1212'); + expect(secondRepeat.findElement(by.model('contact.value')).getAttribute('value')) + .toBe('john.smith@example.org'); + + firstRepeat.findElement(by.linkText('clear')).click() + + expect(firstRepeat.findElement(by.model('contact.value')).getAttribute('value')) + .toBe(''); + + container.findElement(by.linkText('add')).click(); + + expect(container.findElement(by.repeater('contact in settings.contacts').row(2)) + .findElement(by.model('contact.value')) + .getAttribute('value')) + .toBe('yourname@example.org'); }); - + @@ -17715,22 +17952,36 @@ var ngCloakDirective = ngDirective({ - + it('should check controller', function() { - expect(element('#ctrl-exmpl>:input').val()).toBe('John Smith'); - expect(element('#ctrl-exmpl li:nth-child(1) input').val()) - .toBe('408 555 1212'); - expect(element('#ctrl-exmpl li:nth-child(2) input').val()) - .toBe('john.smith@example.org'); - - element('#ctrl-exmpl li:first a:contains("clear")').click(); - expect(element('#ctrl-exmpl li:first input').val()).toBe(''); - - element('#ctrl-exmpl li:last a:contains("add")').click(); - expect(element('#ctrl-exmpl li:nth-child(3) input').val()) - .toBe('yourname@example.org'); + var container = element(by.id('ctrl-exmpl')); + + expect(container.findElement(by.model('name')) + .getAttribute('value')).toBe('John Smith'); + + var firstRepeat = + container.findElement(by.repeater('contact in contacts').row(0)); + var secondRepeat = + container.findElement(by.repeater('contact in contacts').row(1)); + + expect(firstRepeat.findElement(by.model('contact.value')).getAttribute('value')) + .toBe('408 555 1212'); + expect(secondRepeat.findElement(by.model('contact.value')).getAttribute('value')) + .toBe('john.smith@example.org'); + + firstRepeat.findElement(by.linkText('clear')).click() + + expect(firstRepeat.findElement(by.model('contact.value')).getAttribute('value')) + .toBe(''); + + container.findElement(by.linkText('add')).click(); + + expect(container.findElement(by.repeater('contact in contacts').row(2)) + .findElement(by.model('contact.value')) + .getAttribute('value')) + .toBe('yourname@example.org'); }); - + */ @@ -18082,8 +18333,8 @@ forEach( * Enables binding angular expressions to onsubmit events. * * Additionally it prevents the default action (which for form means sending the request to the - * server and reloading the current page) **but only if the form does not contain an `action` - * attribute**. + * server and reloading the current page), but only if the form does not contain `action`, + * `data-action`, or `x-action` attributes. * * @element form * @priority 0 @@ -18111,20 +18362,20 @@ forEach(
list={{list}}
- + it('should check ng-submit', function() { - expect(binding('list')).toBe('[]'); - element('.doc-example-live #submit').click(); - expect(binding('list')).toBe('["hello"]'); - expect(input('text').val()).toBe(''); + expect(element(by.binding('list')).getText()).toBe('list=[]'); + element(by.css('.doc-example-live #submit')).click(); + expect(element(by.binding('list')).getText()).toContain('hello'); + expect(element(by.input('text')).getAttribute('value')).toBe(''); }); it('should ignore empty strings', function() { - expect(binding('list')).toBe('[]'); - element('.doc-example-live #submit').click(); - element('.doc-example-live #submit').click(); - expect(binding('list')).toBe('["hello"]'); - }); - + expect(element(by.binding('list')).getText()).toBe('list=[]'); + element(by.css('.doc-example-live #submit')).click(); + element(by.css('.doc-example-live #submit')).click(); + expect(element(by.binding('list')).getText()).toContain('hello'); + }); + */ @@ -18451,19 +18702,33 @@ var ngIfDirective = ['$animate', function($animate) { top:50px; }
- + + var templateSelect = element(by.model('template')); + var includeElem = element(by.css('.doc-example-live [ng-include]')); + it('should load template1.html', function() { - expect(element('.doc-example-live [ng-include]').text()). - toMatch(/Content of template1.html/); + expect(includeElem.getText()).toMatch(/Content of template1.html/); }); + it('should load template2.html', function() { - select('template').option('1'); - expect(element('.doc-example-live [ng-include]').text()). - toMatch(/Content of template2.html/); + if (browser.params.browser == 'firefox') { + // Firefox can't handle using selects + // See https://github.com/angular/protractor/issues/480 + return; + } + templateSelect.click(); + templateSelect.element.all(by.css('option')).get(2).click(); + expect(includeElem.getText()).toMatch(/Content of template2.html/); }); + it('should change to blank', function() { - select('template').option(''); - expect(element('.doc-example-live [ng-include]')).toBe(undefined); + if (browser.params.browser == 'firefox') { + // Firefox can't handle using selects + return; + } + templateSelect.click(); + templateSelect.element.all(by.css('option')).get(0).click(); + expect(includeElem.isPresent()).toBe(false); }); @@ -18623,15 +18888,15 @@ var ngIncludeFillContentDirective = ['$compile', - + it('should alias index positions', function() { - expect(element('.example-init').text()) - .toBe('list[ 0 ][ 0 ] = a;' + - 'list[ 0 ][ 1 ] = b;' + - 'list[ 1 ][ 0 ] = c;' + - 'list[ 1 ][ 1 ] = d;'); + var elements = element.all(by.css('.example-init')); + expect(elements.get(0).getText()).toBe('list[ 0 ][ 0 ] = a;'); + expect(elements.get(1).getText()).toBe('list[ 0 ][ 1 ] = b;'); + expect(elements.get(2).getText()).toBe('list[ 1 ][ 0 ] = c;'); + expect(elements.get(3).getText()).toBe('list[ 1 ][ 1 ] = d;'); }); - + */ var ngInitDirective = ngDirective({ @@ -18669,13 +18934,12 @@ var ngInitDirective = ngDirective({
Normal: {{1 + 2}}
Ignored: {{1 + 2}}
- + it('should check ng-non-bindable', function() { - expect(using('.doc-example-live').binding('1 + 2')).toBe('3'); - expect(using('.doc-example-live').element('div:last').text()). - toMatch(/1 \+ 2/); + expect(element(by.binding('1 + 2')).getText()).toContain('3'); + expect(element.all(by.css('.doc-example-live div')).last().getText()).toMatch(/1 \+ 2/); }); - + */ var ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 }); @@ -18803,49 +19067,53 @@ var ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 }); - + it('should show correct pluralized string', function() { - expect(element('.doc-example-live ng-pluralize:first').text()). - toBe('1 person is viewing.'); - expect(element('.doc-example-live ng-pluralize:last').text()). - toBe('Igor is viewing.'); - - using('.doc-example-live').input('personCount').enter('0'); - expect(element('.doc-example-live ng-pluralize:first').text()). - toBe('Nobody is viewing.'); - expect(element('.doc-example-live ng-pluralize:last').text()). - toBe('Nobody is viewing.'); - - using('.doc-example-live').input('personCount').enter('2'); - expect(element('.doc-example-live ng-pluralize:first').text()). - toBe('2 people are viewing.'); - expect(element('.doc-example-live ng-pluralize:last').text()). - toBe('Igor and Misko are viewing.'); - - using('.doc-example-live').input('personCount').enter('3'); - expect(element('.doc-example-live ng-pluralize:first').text()). - toBe('3 people are viewing.'); - expect(element('.doc-example-live ng-pluralize:last').text()). - toBe('Igor, Misko and one other person are viewing.'); - - using('.doc-example-live').input('personCount').enter('4'); - expect(element('.doc-example-live ng-pluralize:first').text()). - toBe('4 people are viewing.'); - expect(element('.doc-example-live ng-pluralize:last').text()). - toBe('Igor, Misko and 2 other people are viewing.'); - }); + var withoutOffset = element.all(by.css('ng-pluralize')).get(0); + var withOffset = element.all(by.css('ng-pluralize')).get(1); + var countInput = element(by.model('personCount')); - it('should show data-binded names', function() { - using('.doc-example-live').input('personCount').enter('4'); - expect(element('.doc-example-live ng-pluralize:last').text()). - toBe('Igor, Misko and 2 other people are viewing.'); + expect(withoutOffset.getText()).toEqual('1 person is viewing.'); + expect(withOffset.getText()).toEqual('Igor is viewing.'); - using('.doc-example-live').input('person1').enter('Di'); - using('.doc-example-live').input('person2').enter('Vojta'); - expect(element('.doc-example-live ng-pluralize:last').text()). - toBe('Di, Vojta and 2 other people are viewing.'); + countInput.clear(); + countInput.sendKeys('0'); + + expect(withoutOffset.getText()).toEqual('Nobody is viewing.'); + expect(withOffset.getText()).toEqual('Nobody is viewing.'); + + countInput.clear(); + countInput.sendKeys('2'); + + expect(withoutOffset.getText()).toEqual('2 people are viewing.'); + expect(withOffset.getText()).toEqual('Igor and Misko are viewing.'); + + countInput.clear(); + countInput.sendKeys('3'); + + expect(withoutOffset.getText()).toEqual('3 people are viewing.'); + expect(withOffset.getText()).toEqual('Igor, Misko and one other person are viewing.'); + + countInput.clear(); + countInput.sendKeys('4'); + + expect(withoutOffset.getText()).toEqual('4 people are viewing.'); + expect(withOffset.getText()).toEqual('Igor, Misko and 2 other people are viewing.'); + }); + it('should show data-bound names', function() { + var withOffset = element.all(by.css('ng-pluralize')).get(1); + var personCount = element(by.model('personCount')); + var person1 = element(by.model('person1')); + var person2 = element(by.model('person2')); + personCount.clear(); + personCount.sendKeys('4'); + person1.clear(); + person1.sendKeys('Di'); + person2.clear(); + person2.sendKeys('Vojta'); + expect(withOffset.getText()).toEqual('Di, Vojta and 2 other people are viewing.'); }); - + */ var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) { @@ -19064,25 +19332,27 @@ var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interp max-height:40px; }
- - it('should render initial data set', function() { - var r = using('.doc-example-live').repeater('ul li'); - expect(r.count()).toBe(10); - expect(r.row(0)).toEqual(["1","John","25"]); - expect(r.row(1)).toEqual(["2","Jessie","30"]); - expect(r.row(9)).toEqual(["10","Samantha","60"]); - expect(binding('friends.length')).toBe("10"); - }); + + var friends = element(by.css('.doc-example-live')) + .element.all(by.repeater('friend in friends')); + + it('should render initial data set', function() { + expect(friends.count()).toBe(10); + expect(friends.get(0).getText()).toEqual('[1] John who is 25 years old.'); + expect(friends.get(1).getText()).toEqual('[2] Jessie who is 30 years old.'); + expect(friends.last().getText()).toEqual('[10] Samantha who is 60 years old.'); + expect(element(by.binding('friends.length')).getText()) + .toMatch("I have 10 friends. They are:"); + }); it('should update repeater when filter predicate changes', function() { - var r = using('.doc-example-live').repeater('ul li'); - expect(r.count()).toBe(10); + expect(friends.count()).toBe(10); - input('q').enter('ma'); + element(by.css('.doc-example-live')).element(by.model('q')).sendKeys('ma'); - expect(r.count()).toBe(2); - expect(r.row(0)).toEqual(["1","Mary","28"]); - expect(r.row(1)).toEqual(["2","Samantha","60"]); + expect(friends.count()).toBe(2); + expect(friends.get(0).getText()).toEqual('[1] Mary who is 28 years old.'); + expect(friends.last().getText()).toEqual('[2] Samantha who is 60 years old.'); }); @@ -19416,16 +19686,19 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) { background:white; } - - it('should check ng-show / ng-hide', function() { - expect(element('.doc-example-live span:first:hidden').count()).toEqual(1); - expect(element('.doc-example-live span:last:visible').count()).toEqual(1); + + var thumbsUp = element(by.css('.doc-example-live span.icon-thumbs-up')); + var thumbsDown = element(by.css('.doc-example-live span.icon-thumbs-down')); - input('checked').check(); + it('should check ng-show / ng-hide', function() { + expect(thumbsUp.isDisplayed()).toBeFalsy(); + expect(thumbsDown.isDisplayed()).toBeTruthy(); - expect(element('.doc-example-live span:first:visible').count()).toEqual(1); - expect(element('.doc-example-live span:last:hidden').count()).toEqual(1); - }); + element(by.model('checked')).click(); + + expect(thumbsUp.isDisplayed()).toBeTruthy(); + expect(thumbsDown.isDisplayed()).toBeFalsy(); + }); */ @@ -19570,16 +19843,19 @@ var ngShowDirective = ['$animate', function($animate) { background:white; } - - it('should check ng-show / ng-hide', function() { - expect(element('.doc-example-live .check-element:first:hidden').count()).toEqual(1); - expect(element('.doc-example-live .check-element:last:visible').count()).toEqual(1); + + var thumbsUp = element(by.css('.doc-example-live span.icon-thumbs-up')); + var thumbsDown = element(by.css('.doc-example-live span.icon-thumbs-down')); - input('checked').check(); + it('should check ng-show / ng-hide', function() { + expect(thumbsUp.isDisplayed()).toBeFalsy(); + expect(thumbsDown.isDisplayed()).toBeTruthy(); - expect(element('.doc-example-live .check-element:first:visible').count()).toEqual(1); - expect(element('.doc-example-live .check-element:last:hidden').count()).toEqual(1); - }); + element(by.model('checked')).click(); + + expect(thumbsUp.isDisplayed()).toBeTruthy(); + expect(thumbsDown.isDisplayed()).toBeFalsy(); + }); */ @@ -19618,13 +19894,15 @@ var ngHideDirective = ['$animate', function($animate) { color: black; } - + + var colorSpan = element(by.css('.doc-example-live span')); + it('should check ng-style', function() { - expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)'); - element('.doc-example-live :button[value=set]').click(); - expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)'); - element('.doc-example-live :button[value=clear]').click(); - expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)'); + expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)'); + element(by.css('.doc-example-live input[value=set]')).click(); + expect(colorSpan.getCssValue('color')).toBe('rgba(255, 0, 0, 1)'); + element(by.css('.doc-example-live input[value=clear]')).click(); + expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)'); }); @@ -19649,7 +19927,7 @@ var ngStyleDirective = ngDirective(function(scope, element, attr) { * as specified in the template. * * The directive itself works similar to ngInclude, however, instead of downloading template code (or loading it - * from the template cache), `ngSwitch` simply choses one of the nested elements and makes it visible based on which element + * from the template cache), `ngSwitch` simply chooses one of the nested elements and makes it visible based on which element * matches the value obtained from the evaluated expression. In other words, you define a container element * (where you place the directive), place an expression on the **`on="..."` attribute** * (or the **`ng-switch="..."` attribute**), define any inner elements inside of the directive and place @@ -19745,17 +20023,20 @@ var ngStyleDirective = ngDirective(function(scope, element, attr) { top:0; } - + + var switchElem = element(by.css('.doc-example-live [ng-switch]')); + var select = element(by.model('selection')); + it('should start in settings', function() { - expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/); + expect(switchElem.getText()).toMatch(/Settings Div/); }); it('should change to home', function() { - select('selection').option('home'); - expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/); + select.element.all(by.css('option')).get(1).click(); + expect(switchElem.getText()).toMatch(/Home Span/); }); it('should select default', function() { - select('selection').option('other'); - expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/); + select.element.all(by.css('option')).get(2).click(); + expect(switchElem.getText()).toMatch(/default/); }); @@ -19862,35 +20143,32 @@ var ngSwitchDefaultDirective = ngDirective({ {{text}} - + it('should have transcluded', function() { - input('title').enter('TITLE'); - input('text').enter('TEXT'); - expect(binding('title')).toEqual('TITLE'); - expect(binding('text')).toEqual('TEXT'); + var titleElement = element(by.model('title')); + titleElement.clear(); + titleElement.sendKeys('TITLE'); + var textElement = element(by.model('text')); + textElement.clear(); + textElement.sendKeys('TEXT'); + expect(element(by.binding('title')).getText()).toEqual('TITLE'); + expect(element(by.binding('text')).getText()).toEqual('TEXT'); }); - + * */ var ngTranscludeDirective = ngDirective({ - controller: ['$element', '$transclude', function($element, $transclude) { + link: function($scope, $element, $attrs, controller, $transclude) { if (!$transclude) { throw minErr('ngTransclude')('orphan', - 'Illegal use of ngTransclude directive in the template! ' + - 'No parent directive that requires a transclusion found. ' + - 'Element: {0}', - startingTag($element)); + 'Illegal use of ngTransclude directive in the template! ' + + 'No parent directive that requires a transclusion found. ' + + 'Element: {0}', + startingTag($element)); } - - // remember the transclusion fn but call it during linking so that we don't process transclusion before directives on - // the parent element even when the transclusion replaces the current element. (we can't use priority here because - // that applies only to compile fns and not controllers - this.$transclude = $transclude; - }], - - link: function($scope, $element, $attrs, controller) { - controller.$transclude(function(clone) { + + $transclude(function(clone) { $element.empty(); $element.append(clone); }); @@ -19922,12 +20200,12 @@ var ngTranscludeDirective = ngDirective({ Load inlined template
- + it('should load template defined inside script tag', function() { - element('#tpl-link').click(); - expect(element('#tpl-content').text()).toMatch(/Content of the template/); + element(by.css('#tpl-link')).click(); + expect(element(by.css('#tpl-content')).getText()).toMatch(/Content of the template/); }); - + */ var scriptDirective = ['$templateCache', function($templateCache) { @@ -19975,7 +20253,7 @@ var ngOptionsMinErr = minErr('ngOptions'); * option. See example below for demonstration. * *
- * **Note:** `ngOptions` provides iterator facility for `
- + it('should check ng-options', function() { - expect(binding('{selected_color:color}')).toMatch('red'); - select('color').option('0'); - expect(binding('{selected_color:color}')).toMatch('black'); - using('.nullable').select('color').option(''); - expect(binding('{selected_color:color}')).toMatch('null'); + expect(element(by.binding('{selected_color:color}')).getText()).toMatch('red'); + element.all(by.select('color')).first().click(); + element.all(by.css('select[ng-model="color"] option')).first().click(); + expect(element(by.binding('{selected_color:color}')).getText()).toMatch('black'); + element(by.css('.nullable select[ng-model="color"]')).click(); + element.all(by.css('.nullable select[ng-model="color"] option')).first().click(); + expect(element(by.binding('{selected_color:color}')).getText()).toMatch('null'); }); - + */ @@ -20591,4 +20871,4 @@ var styleDirective = valueFn({ })(window, document); -!angular.$$csp() && angular.element(document).find('head').prepend(''); +!angular.$$csp() && angular.element(document).find('head').prepend(''); \ No newline at end of file diff --git a/config/lib/js/angular/angular.min.js b/config/lib/js/angular/angular.min.js index e121c5b183b..8e7bb502882 100755 --- a/config/lib/js/angular/angular.min.js +++ b/config/lib/js/angular/angular.min.js @@ -1,202 +1,204 @@ /* - AngularJS v1.2.10 + AngularJS v1.2.13 (c) 2010-2014 Google, Inc. http://angularjs.org License: MIT */ -(function(Z,Q,r){'use strict';function F(b){return function(){var a=arguments[0],c,a="["+(b?b+":":"")+a+"] http://errors.angularjs.org/1.2.10/"+(b?b+"/":"")+a;for(c=1;c").append(b).html();try{return 3===b[0].nodeType?x(c):c.match(/^(<[^>]+>)/)[1].replace(/^<([\w\-]+)/, -function(a,b){return"<"+x(b)})}catch(d){return x(c)}}function Wb(b){try{return decodeURIComponent(b)}catch(a){}}function Xb(b){var a={},c,d;q((b||"").split("&"),function(b){b&&(c=b.split("="),d=Wb(c[0]),B(d)&&(b=B(c[1])?Wb(c[1]):!0,a[d]?K(a[d])?a[d].push(b):a[d]=[a[d],b]:a[d]=b))});return a}function Yb(b){var a=[];q(b,function(b,d){K(b)?q(b,function(b){a.push(wa(d,!0)+(!0===b?"":"="+wa(b,!0)))}):a.push(wa(d,!0)+(!0===b?"":"="+wa(b,!0)))});return a.length?a.join("&"):""}function tb(b){return wa(b, -!0).replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+")}function wa(b,a){return encodeURIComponent(b).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,a?"%20":"+")}function Tc(b,a){function c(a){a&&d.push(a)}var d=[b],e,g,f=["ng:app","ng-app","x-ng-app","data-ng-app"],h=/\sng[:\-]app(:\s*([\w\d_]+);?)?\s/;q(f,function(a){f[a]=!0;c(Q.getElementById(a));a=a.replace(":","\\:");b.querySelectorAll&&(q(b.querySelectorAll("."+a),c),q(b.querySelectorAll("."+ -a+"\\:"),c),q(b.querySelectorAll("["+a+"]"),c))});q(d,function(a){if(!e){var b=h.exec(" "+a.className+" ");b?(e=a,g=(b[2]||"").replace(/\s+/g,",")):q(a.attributes,function(b){!e&&f[b.name]&&(e=a,g=b.value)})}});e&&a(e,g?[g]:[])}function Zb(b,a){var c=function(){b=A(b);if(b.injector()){var c=b[0]===Q?"document":ga(b);throw Oa("btstrpd",c);}a=a||[];a.unshift(["$provide",function(a){a.value("$rootElement",b)}]);a.unshift("ng");c=$b(a);c.invoke(["$rootScope","$rootElement","$compile","$injector","$animate", -function(a,b,c,d,e){a.$apply(function(){b.data("$injector",d);c(b)(a)})}]);return c},d=/^NG_DEFER_BOOTSTRAP!/;if(Z&&!d.test(Z.name))return c();Z.name=Z.name.replace(d,"");Ca.resumeBootstrap=function(b){q(b,function(b){a.push(b)});c()}}function db(b,a){a=a||"_";return b.replace(Uc,function(b,d){return(d?a:"")+b.toLowerCase()})}function ub(b,a,c){if(!b)throw Oa("areq",a||"?",c||"required");return b}function Qa(b,a,c){c&&K(b)&&(b=b[b.length-1]);ub(L(b),a,"not a function, got "+(b&&"object"==typeof b? -b.constructor.name||"Object":typeof b));return b}function xa(b,a){if("hasOwnProperty"===b)throw Oa("badname",a);}function vb(b,a,c){if(!a)return b;a=a.split(".");for(var d,e=b,g=a.length,f=0;f "+b;a.removeChild(a.firstChild);zb(this,a.childNodes);A(Q.createDocumentFragment()).append(this)}else zb(this, -b)}function Ab(b){return b.cloneNode(!0)}function Ea(b){ac(b);var a=0;for(b=b.childNodes||[];a=M?(c.preventDefault=null,c.stopPropagation=null,c.isDefaultPrevented=null):(delete c.preventDefault,delete c.stopPropagation,delete c.isDefaultPrevented)};c.elem=b;return c}function Fa(b){var a=typeof b,c;"object"==a&&null!==b?"function"==typeof(c=b.$$hashKey)?c=b.$$hashKey():c=== -r&&(c=b.$$hashKey=$a()):c=b;return a+":"+c}function Ta(b){q(b,this.put,this)}function hc(b){var a,c;"function"==typeof b?(a=b.$inject)||(a=[],b.length&&(c=b.toString().replace($c,""),c=c.match(ad),q(c[1].split(bd),function(b){b.replace(cd,function(b,c,d){a.push(d)})})),b.$inject=a):K(b)?(c=b.length-1,Qa(b[c],"fn"),a=b.slice(0,c)):Qa(b,"fn",!0);return a}function $b(b){function a(a){return function(b,c){if(X(b))q(b,Qb(a));else return a(b,c)}}function c(a,b){xa(a,"service");if(L(b)||K(b))b=n.instantiate(b); -if(!b.$get)throw Ua("pget",a);return l[a+h]=b}function d(a,b){return c(a,{$get:b})}function e(a){var b=[],c,d,g,h;q(a,function(a){if(!k.get(a)){k.put(a,!0);try{if(D(a))for(c=Va(a),b=b.concat(e(c.requires)).concat(c._runBlocks),d=c._invokeQueue,g=0,h=d.length;g 4096 bytes)!"));else{if(m.cookie!==J)for(J=m.cookie,d=J.split("; "),V={},g=0;gk&&this.remove(p.key),b},get:function(a){var b=l[a];if(b)return e(b),m[a]},remove:function(a){var b=l[a];b&&(b==n&&(n=b.p),b==p&&(p=b.n),g(b.n,b.p),delete l[a],delete m[a],f--)},removeAll:function(){m={};f=0;l={};n=p=null},destroy:function(){l=h=m=null;delete a[b]},info:function(){return t({},h,{size:f})}}}var a={};b.info=function(){var b={};q(a,function(a,e){b[e]=a.info()});return b};b.get=function(b){return a[b]}; -return b}}function hd(){this.$get=["$cacheFactory",function(b){return b("templates")}]}function jc(b,a){var c={},d="Directive",e=/^\s*directive\:\s*([\d\w\-_]+)\s+(.*)$/,g=/(([\d\w\-_]+)(?:\:([^;]+))?;?)/,f=/^(on[a-z]+|formaction)$/;this.directive=function m(a,e){xa(a,"directive");D(a)?(ub(e,"directiveFactory"),c.hasOwnProperty(a)||(c[a]=[],b.factory(a+d,["$injector","$exceptionHandler",function(b,d){var e=[];q(c[a],function(c,g){try{var f=b.invoke(c);L(f)?f={compile:$(f)}:!f.compile&&f.link&&(f.compile= -$(f.link));f.priority=f.priority||0;f.index=g;f.name=f.name||a;f.require=f.require||f.controller&&f.name;f.restrict=f.restrict||"A";e.push(f)}catch(m){d(m)}});return e}])),c[a].push(e)):q(a,Qb(m));return this};this.aHrefSanitizationWhitelist=function(b){return B(b)?(a.aHrefSanitizationWhitelist(b),this):a.aHrefSanitizationWhitelist()};this.imgSrcSanitizationWhitelist=function(b){return B(b)?(a.imgSrcSanitizationWhitelist(b),this):a.imgSrcSanitizationWhitelist()};this.$get=["$injector","$interpolate", -"$exceptionHandler","$http","$templateCache","$parse","$controller","$rootScope","$document","$sce","$animate","$$sanitizeUri",function(a,b,l,n,p,s,C,y,E,u,R,H){function v(a,b,c,d,e){a instanceof A||(a=A(a));q(a,function(b,c){3==b.nodeType&&b.nodeValue.match(/\S+/)&&(a[c]=A(b).wrap("").parent()[0])});var g=N(a,b,a,c,d,e);ha(a,"ng-scope");return function(b,c,d){ub(b,"scope");var e=c?Ga.clone.call(a):a;q(d,function(a,b){e.data("$"+b+"Controller",a)});d=0;for(var f=e.length;darguments.length&&(b=a, -a=r);z&&(c=ca);return p(a,b,c)}var I,v,N,u,P,J,ca={},hb;I=c===g?d:Tb(d,new Fb(A(g),d.$attr));v=I.$$element;if(H){var T=/^\s*([@=&])(\??)\s*(\w*)\s*$/;f=A(g);J=e.$new(!0);ia&&ia===H.$$originalDirective?f.data("$isolateScope",J):f.data("$isolateScopeNoTemplate",J);ha(f,"ng-isolate-scope");q(H.scope,function(a,c){var d=a.match(T)||[],g=d[3]||c,f="?"==d[2],d=d[1],m,l,n,p;J.$$isolateBindings[c]=d+g;switch(d){case "@":I.$observe(g,function(a){J[c]=a});I.$$observers[g].$$scope=e;I[g]&&(J[c]=b(I[g])(e)); -break;case "=":if(f&&!I[g])break;l=s(I[g]);p=l.literal?ua:function(a,b){return a===b};n=l.assign||function(){m=J[c]=l(e);throw ja("nonassign",I[g],H.name);};m=J[c]=l(e);J.$watch(function(){var a=l(e);p(a,J[c])||(p(a,m)?n(e,a=J[c]):J[c]=a);return m=a},null,l.literal);break;case "&":l=s(I[g]);J[c]=function(a){return l(e,a)};break;default:throw ja("iscp",H.name,c,a);}})}hb=p&&y;V&&q(V,function(a){var b={$scope:a===H||a.$$isolateScope?J:e,$element:v,$attrs:I,$transclude:hb},c;P=a.controller;"@"==P&&(P= -I[a.name]);c=C(P,b);ca[a.name]=c;z||v.data("$"+a.name+"Controller",c);a.controllerAs&&(b.$scope[a.controllerAs]=c)});f=0;for(N=m.length;fG.priority)break;if(U=G.scope)u=u||G,G.templateUrl||(x("new/isolated scope",H,G,t),X(U)&&(H=G));da=G.name;!G.templateUrl&&G.controller&&(U=G.controller,V=V||{},x("'"+da+"' controller",V[da],G,t),V[da]=G);if(U=G.transclude)T=!0,G.$$tlb||(x("transclusion",p,G,t),p=G),"element"==U?(z=!0,N=G.priority,U=ca(c,Wa,S), -t=d.$$element=A(Q.createComment(" "+da+": "+d[da]+" ")),c=t[0],ib(g,A(va.call(U,0)),c),F=v(U,e,N,f&&f.name,{nonTlbTranscludeDirective:p})):(U=A(Ab(c)).contents(),t.empty(),F=v(U,e));if(G.template)if(x("template",ia,G,t),ia=G,U=L(G.template)?G.template(t,d):G.template,U=Y(U),G.replace){f=G;U=A("
"+ba(U)+"
").contents();c=U[0];if(1!=U.length||1!==c.nodeType)throw ja("tplrt",da,"");ib(g,t,c);na={$attr:{}};U=J(c,[],na);var W=a.splice(M+1,a.length-(M+1));H&&ic(U);a=a.concat(U).concat(W);B(d,na); -na=a.length}else t.html(U);if(G.templateUrl)x("template",ia,G,t),ia=G,G.replace&&(f=G),E=w(a.splice(M,a.length-M),t,d,g,F,m,n,{controllerDirectives:V,newIsolateScopeDirective:H,templateDirective:ia,nonTlbTranscludeDirective:p}),na=a.length;else if(G.compile)try{O=G.compile(t,d,F),L(O)?y(null,O,Wa,S):O&&y(O.pre,O.post,Wa,S)}catch(Z){l(Z,ga(t))}G.terminal&&(E.terminal=!0,N=Math.max(N,G.priority))}E.scope=u&&!0===u.scope;E.transclude=T&&F;return E}function ic(a){for(var b=0,c=a.length;bp.priority)&&-1!=p.restrict.indexOf(g)&&(s&&(p=Sb(p,{$$start:s,$$end:n})),b.push(p),k=p)}catch(v){l(v)}}return k}function B(a,b){var c=b.$attr,d=a.$attr,e=a.$$element;q(a,function(d,e){"$"!=e.charAt(0)&&(b[e]&&(d+=("style"===e?";":" ")+b[e]),a.$set(e,d,!0,c[e]))});q(b,function(b,g){"class"==g?(ha(e,b),a["class"]=(a["class"]?a["class"]+ -" ":"")+b):"style"==g?(e.attr("style",e.attr("style")+";"+b),a.style=(a.style?a.style+";":"")+b):"$"==g.charAt(0)||a.hasOwnProperty(g)||(a[g]=b,d[g]=c[g])})}function w(a,b,c,d,e,g,f,m){var k=[],s,l,C=b[0],y=a.shift(),v=t({},y,{templateUrl:null,transclude:null,replace:null,$$originalDirective:y}),R=L(y.templateUrl)?y.templateUrl(b,c):y.templateUrl;b.empty();n.get(u.getTrustedResourceUrl(R),{cache:p}).success(function(n){var p,E;n=Y(n);if(y.replace){n=A("
"+ba(n)+"
").contents();p=n[0];if(1!= -n.length||1!==p.nodeType)throw ja("tplrt",y.name,R);n={$attr:{}};ib(d,b,p);var u=J(p,[],n);X(y.scope)&&ic(u);a=u.concat(a);B(c,n)}else p=C,b.html(n);a.unshift(v);s=ia(a,p,c,e,b,y,g,f,m);q(d,function(a,c){a==p&&(d[c]=b[0])});for(l=N(b[0].childNodes,e);k.length;){n=k.shift();E=k.shift();var H=k.shift(),ha=k.shift(),u=b[0];E!==C&&(u=Ab(p),ib(H,A(E),u));E=s.transclude?V(n,s.transclude):ha;s(l,n,u,d,E)}k=null}).error(function(a,b,c,d){throw ja("tpload",d.url);});return function(a,b,c,d,e){k?(k.push(b), -k.push(c),k.push(d),k.push(e)):s(l,b,c,d,e)}}function z(a,b){var c=b.priority-a.priority;return 0!==c?c:a.name!==b.name?a.namea.status?b:n.reject(b)}var d={transformRequest:e.transformRequest,transformResponse:e.transformResponse},g=function(a){function b(a){var c;q(a,function(b, -d){L(b)&&(c=b(),null!=c?a[d]=c:delete a[d])})}var c=e.headers,d=t({},a.headers),g,f,c=t({},c.common,c[x(a.method)]);b(c);b(d);a:for(g in c){a=x(g);for(f in d)if(x(f)===a)continue a;d[g]=c[g]}return d}(a);t(d,a);d.headers=g;d.method=Ia(d.method);(a=Gb(d.url)?b.cookies()[d.xsrfCookieName||e.xsrfCookieName]:r)&&(g[d.xsrfHeaderName||e.xsrfHeaderName]=a);var f=[function(a){g=a.headers;var b=oc(a.data,nc(g),a.transformRequest);z(a.data)&&q(g,function(a,b){"content-type"===x(b)&&delete g[b]});z(a.withCredentials)&& -!z(e.withCredentials)&&(a.withCredentials=e.withCredentials);return C(a,b,g).then(c,c)},r],h=n.when(d);for(q(u,function(a){(a.request||a.requestError)&&f.unshift(a.request,a.requestError);(a.response||a.responseError)&&f.push(a.response,a.responseError)});f.length;){a=f.shift();var k=f.shift(),h=h.then(a,k)}h.success=function(a){h.then(function(b){a(b.data,b.status,b.headers,d)});return h};h.error=function(a){h.then(null,function(b){a(b.data,b.status,b.headers,d)});return h};return h}function C(b, -c,g){function f(a,b,c){u&&(200<=a&&300>a?u.put(r,[a,b,mc(c)]):u.remove(r));m(b,a,c);d.$$phase||d.$apply()}function m(a,c,d){c=Math.max(c,0);(200<=c&&300>c?p.resolve:p.reject)({data:a,status:c,headers:nc(d),config:b})}function k(){var a=bb(s.pendingRequests,b);-1!==a&&s.pendingRequests.splice(a,1)}var p=n.defer(),C=p.promise,u,q,r=y(b.url,b.params);s.pendingRequests.push(b);C.then(k,k);(b.cache||e.cache)&&(!1!==b.cache&&"GET"==b.method)&&(u=X(b.cache)?b.cache:X(e.cache)?e.cache:E);if(u)if(q=u.get(r), -B(q)){if(q.then)return q.then(k,k),q;K(q)?m(q[1],q[0],aa(q[2])):m(q,200,{})}else u.put(r,C);z(q)&&a(b.method,r,c,f,g,b.timeout,b.withCredentials,b.responseType);return C}function y(a,b){if(!b)return a;var c=[];Pc(b,function(a,b){null===a||z(a)||(K(a)||(a=[a]),q(a,function(a){X(a)&&(a=qa(a));c.push(wa(b)+"="+wa(a))}))});return a+(-1==a.indexOf("?")?"?":"&")+c.join("&")}var E=c("$http"),u=[];q(g,function(a){u.unshift(D(a)?p.get(a):p.invoke(a))});q(f,function(a,b){var c=D(a)?p.get(a):p.invoke(a);u.splice(b, -0,{response:function(a){return c(n.when(a))},responseError:function(a){return c(n.reject(a))}})});s.pendingRequests=[];(function(a){q(arguments,function(a){s[a]=function(b,c){return s(t(c||{},{method:a,url:b}))}})})("get","delete","head","jsonp");(function(a){q(arguments,function(a){s[a]=function(b,c,d){return s(t(d||{},{method:a,url:b,data:c}))}})})("post","put");s.defaults=e;return s}]}function nd(b){return 8>=M&&"patch"===x(b)?new ActiveXObject("Microsoft.XMLHTTP"):new Z.XMLHttpRequest}function od(){this.$get= -["$browser","$window","$document",function(b,a,c){return pd(b,nd,b.defer,a.angular.callbacks,c[0])}]}function pd(b,a,c,d,e){function g(a,b){var c=e.createElement("script"),d=function(){c.onreadystatechange=c.onload=c.onerror=null;e.body.removeChild(c);b&&b()};c.type="text/javascript";c.src=a;M&&8>=M?c.onreadystatechange=function(){/loaded|complete/.test(c.readyState)&&d()}:c.onload=c.onerror=function(){d()};e.body.appendChild(c);return d}var f=-1;return function(e,m,k,l,n,p,s,C){function y(){u=f; -H&&H();v&&v.abort()}function E(a,d,e,g){r&&c.cancel(r);H=v=null;d=0===d?e?200:404:d;a(1223==d?204:d,e,g);b.$$completeOutstandingRequest(w)}var u;b.$$incOutstandingRequestCount();m=m||b.url();if("jsonp"==x(e)){var R="_"+(d.counter++).toString(36);d[R]=function(a){d[R].data=a};var H=g(m.replace("JSON_CALLBACK","angular.callbacks."+R),function(){d[R].data?E(l,200,d[R].data):E(l,u||-2);d[R]=Ca.noop})}else{var v=a(e);v.open(e,m,!0);q(n,function(a,b){B(a)&&v.setRequestHeader(b,a)});v.onreadystatechange= -function(){if(v&&4==v.readyState){var a=null,b=null;u!==f&&(a=v.getAllResponseHeaders(),b="response"in v?v.response:v.responseText);E(l,u||v.status,b,a)}};s&&(v.withCredentials=!0);C&&(v.responseType=C);v.send(k||null)}if(0=h&&(n.resolve(s),l(p.$$intervalId),delete e[p.$$intervalId]);C||b.$apply()},f);e[p.$$intervalId]=n;return p} -var e={};d.cancel=function(a){return a&&a.$$intervalId in e?(e[a.$$intervalId].reject("canceled"),clearInterval(a.$$intervalId),delete e[a.$$intervalId],!0):!1};return d}]}function sd(){this.$get=function(){return{id:"en-us",NUMBER_FORMATS:{DECIMAL_SEP:".",GROUP_SEP:",",PATTERNS:[{minInt:1,minFrac:0,maxFrac:3,posPre:"",posSuf:"",negPre:"-",negSuf:"",gSize:3,lgSize:3},{minInt:1,minFrac:2,maxFrac:2,posPre:"\u00a4",posSuf:"",negPre:"(\u00a4",negSuf:")",gSize:3,lgSize:3}],CURRENCY_SYM:"$"},DATETIME_FORMATS:{MONTH:"January February March April May June July August September October November December".split(" "), -SHORTMONTH:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),DAY:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),SHORTDAY:"Sun Mon Tue Wed Thu Fri Sat".split(" "),AMPMS:["AM","PM"],medium:"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a",fullDate:"EEEE, MMMM d, y",longDate:"MMMM d, y",mediumDate:"MMM d, y",shortDate:"M/d/yy",mediumTime:"h:mm:ss a",shortTime:"h:mm a"},pluralCat:function(b){return 1===b?"one":"other"}}}}function qc(b){b=b.split("/");for(var a=b.length;a--;)b[a]= -tb(b[a]);return b.join("/")}function rc(b,a,c){b=ya(b,c);a.$$protocol=b.protocol;a.$$host=b.hostname;a.$$port=S(b.port)||td[b.protocol]||null}function sc(b,a,c){var d="/"!==b.charAt(0);d&&(b="/"+b);b=ya(b,c);a.$$path=decodeURIComponent(d&&"/"===b.pathname.charAt(0)?b.pathname.substring(1):b.pathname);a.$$search=Xb(b.search);a.$$hash=decodeURIComponent(b.hash);a.$$path&&"/"!=a.$$path.charAt(0)&&(a.$$path="/"+a.$$path)}function oa(b,a){if(0===a.indexOf(b))return a.substr(b.length)}function Xa(b){var a= -b.indexOf("#");return-1==a?b:b.substr(0,a)}function Hb(b){return b.substr(0,Xa(b).lastIndexOf("/")+1)}function tc(b,a){this.$$html5=!0;a=a||"";var c=Hb(b);rc(b,this,b);this.$$parse=function(a){var e=oa(c,a);if(!D(e))throw Ib("ipthprfx",a,c);sc(e,this,b);this.$$path||(this.$$path="/");this.$$compose()};this.$$compose=function(){var a=Yb(this.$$search),b=this.$$hash?"#"+tb(this.$$hash):"";this.$$url=qc(this.$$path)+(a?"?"+a:"")+b;this.$$absUrl=c+this.$$url.substr(1)};this.$$rewrite=function(d){var e; -if((e=oa(b,d))!==r)return d=e,(e=oa(a,e))!==r?c+(oa("/",e)||e):b+d;if((e=oa(c,d))!==r)return c+e;if(c==d+"/")return c}}function Jb(b,a){var c=Hb(b);rc(b,this,b);this.$$parse=function(d){var e=oa(b,d)||oa(c,d),e="#"==e.charAt(0)?oa(a,e):this.$$html5?e:"";if(!D(e))throw Ib("ihshprfx",d,a);sc(e,this,b);d=this.$$path;var g=/^\/?.*?:(\/.*)/;0===e.indexOf(b)&&(e=e.replace(b,""));g.exec(e)||(d=(e=g.exec(d))?e[1]:d);this.$$path=d;this.$$compose()};this.$$compose=function(){var c=Yb(this.$$search),e=this.$$hash? -"#"+tb(this.$$hash):"";this.$$url=qc(this.$$path)+(c?"?"+c:"")+e;this.$$absUrl=b+(this.$$url?a+this.$$url:"")};this.$$rewrite=function(a){if(Xa(b)==Xa(a))return a}}function uc(b,a){this.$$html5=!0;Jb.apply(this,arguments);var c=Hb(b);this.$$rewrite=function(d){var e;if(b==Xa(d))return d;if(e=oa(c,d))return b+a+e;if(c===d+"/")return c}}function jb(b){return function(){return this[b]}}function vc(b,a){return function(c){if(z(c))return this[b];this[b]=a(c);this.$$compose();return this}}function ud(){var b= -"",a=!1;this.hashPrefix=function(a){return B(a)?(b=a,this):b};this.html5Mode=function(b){return B(b)?(a=b,this):a};this.$get=["$rootScope","$browser","$sniffer","$rootElement",function(c,d,e,g){function f(a){c.$broadcast("$locationChangeSuccess",h.absUrl(),a)}var h,m=d.baseHref(),k=d.url();a?(m=k.substring(0,k.indexOf("/",k.indexOf("//")+2))+(m||"/"),e=e.history?tc:uc):(m=Xa(k),e=Jb);h=new e(m,"#"+b);h.$$parse(h.$$rewrite(k));g.on("click",function(a){if(!a.ctrlKey&&!a.metaKey&&2!=a.which){for(var b= -A(a.target);"a"!==x(b[0].nodeName);)if(b[0]===g[0]||!(b=b.parent())[0])return;var e=b.prop("href");X(e)&&"[object SVGAnimatedString]"===e.toString()&&(e=ya(e.animVal).href);var f=h.$$rewrite(e);e&&(!b.attr("target")&&f&&!a.isDefaultPrevented())&&(a.preventDefault(),f!=d.url()&&(h.$$parse(f),c.$apply(),Z.angular["ff-684208-preventDefault"]=!0))}});h.absUrl()!=k&&d.url(h.absUrl(),!0);d.onUrlChange(function(a){h.absUrl()!=a&&(c.$evalAsync(function(){var b=h.absUrl();h.$$parse(a);c.$broadcast("$locationChangeStart", -a,b).defaultPrevented?(h.$$parse(b),d.url(b)):f(b)}),c.$$phase||c.$digest())});var l=0;c.$watch(function(){var a=d.url(),b=h.$$replace;l&&a==h.absUrl()||(l++,c.$evalAsync(function(){c.$broadcast("$locationChangeStart",h.absUrl(),a).defaultPrevented?h.$$parse(a):(d.url(h.absUrl(),b),f(a))}));h.$$replace=!1;return l});return h}]}function vd(){var b=!0,a=this;this.debugEnabled=function(a){return B(a)?(b=a,this):b};this.$get=["$window",function(c){function d(a){a instanceof Error&&(a.stack?a=a.message&& --1===a.stack.indexOf(a.message)?"Error: "+a.message+"\n"+a.stack:a.stack:a.sourceURL&&(a=a.message+"\n"+a.sourceURL+":"+a.line));return a}function e(a){var b=c.console||{},e=b[a]||b.log||w;a=!1;try{a=!!e.apply}catch(m){}return a?function(){var a=[];q(arguments,function(b){a.push(d(b))});return e.apply(b,a)}:function(a,b){e(a,null==b?"":b)}}return{log:e("log"),info:e("info"),warn:e("warn"),error:e("error"),debug:function(){var c=e("debug");return function(){b&&c.apply(a,arguments)}}()}}]}function ea(b, -a){if("constructor"===b)throw za("isecfld",a);return b}function Ya(b,a){if(b){if(b.constructor===b)throw za("isecfn",a);if(b.document&&b.location&&b.alert&&b.setInterval)throw za("isecwindow",a);if(b.children&&(b.nodeName||b.on&&b.find))throw za("isecdom",a);}return b}function kb(b,a,c,d,e){e=e||{};a=a.split(".");for(var g,f=0;1e?wc(d[0],d[1],d[2],d[3],d[4],c,a):function(b,g){var f=0,h;do h=wc(d[f++],d[f++],d[f++],d[f++],d[f++],c,a)(b,g),g=r,b=h;while(fa)for(b in f++,d)d.hasOwnProperty(b)&&!e.hasOwnProperty(b)&&(l--,delete d[b])}else d!==e&&(d=e,f++);return f},function(){b(e,d,c)})},$digest:function(){var d,f,g,h,k=this.$$asyncQueue,l=this.$$postDigestQueue,q,v,r=b,N,V=[],J,A,P;m("$digest");c=null;do{v= -!1;for(N=this;k.length;){try{P=k.shift(),P.scope.$eval(P.expression)}catch(B){p.$$phase=null,e(B)}c=null}a:do{if(h=N.$$watchers)for(q=h.length;q--;)try{if(d=h[q])if((f=d.get(N))!==(g=d.last)&&!(d.eq?ua(f,g):"number"==typeof f&&"number"==typeof g&&isNaN(f)&&isNaN(g)))v=!0,c=d,d.last=d.eq?aa(f):f,d.fn(f,g===n?f:g,N),5>r&&(J=4-r,V[J]||(V[J]=[]),A=L(d.exp)?"fn: "+(d.exp.name||d.exp.toString()):d.exp,A+="; newVal: "+qa(f)+"; oldVal: "+qa(g),V[J].push(A));else if(d===c){v=!1;break a}}catch(t){p.$$phase= -null,e(t)}if(!(h=N.$$childHead||N!==this&&N.$$nextSibling))for(;N!==this&&!(h=N.$$nextSibling);)N=N.$parent}while(N=h);if((v||k.length)&&!r--)throw p.$$phase=null,a("infdig",b,qa(V));}while(v||k.length);for(p.$$phase=null;l.length;)try{l.shift()()}catch(z){e(z)}},$destroy:function(){if(!this.$$destroyed){var a=this.$parent;this.$broadcast("$destroy");this.$$destroyed=!0;this!==p&&(q(this.$$listenerCount,cb(null,l,this)),a.$$childHead==this&&(a.$$childHead=this.$$nextSibling),a.$$childTail==this&& -(a.$$childTail=this.$$prevSibling),this.$$prevSibling&&(this.$$prevSibling.$$nextSibling=this.$$nextSibling),this.$$nextSibling&&(this.$$nextSibling.$$prevSibling=this.$$prevSibling),this.$parent=this.$$nextSibling=this.$$prevSibling=this.$$childHead=this.$$childTail=null)}},$eval:function(a,b){return g(a)(this,b)},$evalAsync:function(a){p.$$phase||p.$$asyncQueue.length||f.defer(function(){p.$$asyncQueue.length&&p.$digest()});this.$$asyncQueue.push({scope:this,expression:a})},$$postDigest:function(a){this.$$postDigestQueue.push(a)}, -$apply:function(a){try{return m("$apply"),this.$eval(a)}catch(b){e(b)}finally{p.$$phase=null;try{p.$digest()}catch(c){throw e(c),c;}}},$on:function(a,b){var c=this.$$listeners[a];c||(this.$$listeners[a]=c=[]);c.push(b);var d=this;do d.$$listenerCount[a]||(d.$$listenerCount[a]=0),d.$$listenerCount[a]++;while(d=d.$parent);var e=this;return function(){c[bb(c,b)]=null;l(e,1,a)}},$emit:function(a,b){var c=[],d,f=this,g=!1,h={name:a,targetScope:f,stopPropagation:function(){g=!0},preventDefault:function(){h.defaultPrevented= -!0},defaultPrevented:!1},m=[h].concat(va.call(arguments,1)),k,l;do{d=f.$$listeners[a]||c;h.currentScope=f;k=0;for(l=d.length;kc.msieDocumentMode)throw sa("iequirks"); -var e=aa(fa);e.isEnabled=function(){return b};e.trustAs=d.trustAs;e.getTrusted=d.getTrusted;e.valueOf=d.valueOf;b||(e.trustAs=e.getTrusted=function(a,b){return b},e.valueOf=Ba);e.parseAs=function(b,c){var d=a(c);return d.literal&&d.constant?d:function(a,c){return e.getTrusted(b,d(a,c))}};var g=e.parseAs,f=e.getTrusted,h=e.trustAs;q(fa,function(a,b){var c=x(b);e[Ra("parse_as_"+c)]=function(b){return g(a,b)};e[Ra("get_trusted_"+c)]=function(b){return f(a,b)};e[Ra("trust_as_"+c)]=function(b){return h(a, -b)}});return e}]}function Gd(){this.$get=["$window","$document",function(b,a){var c={},d=S((/android (\d+)/.exec(x((b.navigator||{}).userAgent))||[])[1]),e=/Boxee/i.test((b.navigator||{}).userAgent),g=a[0]||{},f=g.documentMode,h,m=/^(Moz|webkit|O|ms)(?=[A-Z])/,k=g.body&&g.body.style,l=!1,n=!1;if(k){for(var p in k)if(l=m.exec(p)){h=l[0];h=h.substr(0,1).toUpperCase()+h.substr(1);break}h||(h="WebkitOpacity"in k&&"webkit");l=!!("transition"in k||h+"Transition"in k);n=!!("animation"in k||h+"Animation"in -k);!d||l&&n||(l=D(g.body.style.webkitTransition),n=D(g.body.style.webkitAnimation))}return{history:!(!b.history||!b.history.pushState||4>d||e),hashchange:"onhashchange"in b&&(!f||7b;b=Math.abs(b); -var f=b+"",h="",m=[],k=!1;if(-1!==f.indexOf("e")){var l=f.match(/([\d\.]+)e(-?)(\d+)/);l&&"-"==l[2]&&l[3]>e+1?f="0":(h=f,k=!0)}if(k)0b)&&(h=b.toFixed(e));else{f=(f.split(Hc)[1]||"").length;z(e)&&(e=Math.min(Math.max(a.minFrac,f),a.maxFrac));f=Math.pow(10,e);b=Math.round(b*f)/f;b=(""+b).split(Hc);f=b[0];b=b[1]||"";var l=0,n=a.lgSize,p=a.gSize;if(f.length>=n+p)for(l=f.length-n,k=0;kb&&(d="-",b=-b);for(b=""+b;b.length-c)e+=c;0===e&&-12==c&&(e=12);return Mb(e,a,d)}}function lb(b,a){return function(c,d){var e=c["get"+b](),g=Ia(a?"SHORT"+b:b);return d[g][e]}}function Dc(b){function a(a){var b; -if(b=a.match(c)){a=new Date(0);var g=0,f=0,h=b[8]?a.setUTCFullYear:a.setFullYear,m=b[8]?a.setUTCHours:a.setHours;b[9]&&(g=S(b[9]+b[10]),f=S(b[9]+b[11]));h.call(a,S(b[1]),S(b[2])-1,S(b[3]));g=S(b[4]||0)-g;f=S(b[5]||0)-f;h=S(b[6]||0);b=Math.round(1E3*parseFloat("0."+(b[7]||0)));m.call(a,g,f,h,b)}return a}var c=/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;return function(c,e){var g="",f=[],h,m;e=e||"mediumDate";e=b.DATETIME_FORMATS[e]||e;D(c)&& -(c=Od.test(c)?S(c):a(c));sb(c)&&(c=new Date(c));if(!La(c))return c;for(;e;)(m=Pd.exec(e))?(f=f.concat(va.call(m,1)),e=f.pop()):(f.push(e),e=null);q(f,function(a){h=Qd[a];g+=h?h(c,b.DATETIME_FORMATS):a.replace(/(^'|'$)/g,"").replace(/''/g,"'")});return g}}function Kd(){return function(b){return qa(b,!0)}}function Ld(){return function(b,a){if(!K(b)&&!D(b))return b;a=S(a);if(D(b))return a?0<=a?b.slice(0,a):b.slice(a,b.length):"";var c=[],d,e;a>b.length?a=b.length:a<-b.length&&(a=-b.length);0a||37<=a&&40>=a)||k()});if(e.hasEvent("paste"))a.on("paste cut",k)}a.on("change",h);d.$render=function(){a.val(d.$isEmpty(d.$viewValue)?"":d.$viewValue)};var l=c.ngPattern;l&&((e=l.match(/^\/(.*)\/([gim]*)$/))?(l=RegExp(e[1],e[2]),e=function(a){return pa(d,"pattern",d.$isEmpty(a)||l.test(a),a)}):e=function(c){var e=b.$eval(l);if(!e||!e.test)throw F("ngPattern")("noregexp", -l,e,ga(a));return pa(d,"pattern",d.$isEmpty(c)||e.test(c),c)},d.$formatters.push(e),d.$parsers.push(e));if(c.ngMinlength){var n=S(c.ngMinlength);e=function(a){return pa(d,"minlength",d.$isEmpty(a)||a.length>=n,a)};d.$parsers.push(e);d.$formatters.push(e)}if(c.ngMaxlength){var p=S(c.ngMaxlength);e=function(a){return pa(d,"maxlength",d.$isEmpty(a)||a.length<=p,a)};d.$parsers.push(e);d.$formatters.push(e)}}function Nb(b,a){b="ngClass"+b;return function(){return{restrict:"AC",link:function(c,d,e){function g(b){if(!0=== -a||c.$index%2===a){var d=f(b||"");h?ua(b,h)||e.$updateClass(d,f(h)):e.$addClass(d)}h=aa(b)}function f(a){if(K(a))return a.join(" ");if(X(a)){var b=[];q(a,function(a,c){a&&b.push(c)});return b.join(" ")}return a}var h;c.$watch(e[b],g,!0);e.$observe("class",function(a){g(c.$eval(e[b]))});"ngClass"!==b&&c.$watch("$index",function(d,g){var h=d&1;if(h!==g&1){var n=f(c.$eval(e[b]));h===a?e.$addClass(n):e.$removeClass(n)}})}}}}var x=function(b){return D(b)?b.toLowerCase():b},Ia=function(b){return D(b)?b.toUpperCase(): -b},M,A,Da,va=[].slice,Rd=[].push,Ma=Object.prototype.toString,Oa=F("ng"),Ca=Z.angular||(Z.angular={}),Va,Ha,ka=["0","0","0"];M=S((/msie (\d+)/.exec(x(navigator.userAgent))||[])[1]);isNaN(M)&&(M=S((/trident\/.*; rv:(\d+)/.exec(x(navigator.userAgent))||[])[1]));w.$inject=[];Ba.$inject=[];var ba=function(){return String.prototype.trim?function(b){return D(b)?b.trim():b}:function(b){return D(b)?b.replace(/^\s\s*/,"").replace(/\s\s*$/,""):b}}();Ha=9>M?function(b){b=b.nodeName?b:b[0];return b.scopeName&& -"HTML"!=b.scopeName?Ia(b.scopeName+":"+b.nodeName):b.nodeName}:function(b){return b.nodeName?b.nodeName:b[0].nodeName};var Uc=/[A-Z]/g,Sd={full:"1.2.10",major:1,minor:2,dot:10,codeName:"augmented-serendipity"},Sa=O.cache={},eb=O.expando="ng-"+(new Date).getTime(),Yc=1,Jc=Z.document.addEventListener?function(b,a,c){b.addEventListener(a,c,!1)}:function(b,a,c){b.attachEvent("on"+a,c)},Bb=Z.document.removeEventListener?function(b,a,c){b.removeEventListener(a,c,!1)}:function(b,a,c){b.detachEvent("on"+ -a,c)},Wc=/([\:\-\_]+(.))/g,Xc=/^moz([A-Z])/,yb=F("jqLite"),Ga=O.prototype={ready:function(b){function a(){c||(c=!0,b())}var c=!1;"complete"===Q.readyState?setTimeout(a):(this.on("DOMContentLoaded",a),O(Z).on("load",a))},toString:function(){var b=[];q(this,function(a){b.push(""+a)});return"["+b.join(", ")+"]"},eq:function(b){return 0<=b?A(this[b]):A(this[this.length+b])},length:0,push:Rd,sort:[].sort,splice:[].splice},gb={};q("multiple selected checked disabled readOnly required open".split(" "),function(b){gb[x(b)]= -b});var gc={};q("input select option textarea button form details".split(" "),function(b){gc[Ia(b)]=!0});q({data:cc,inheritedData:fb,scope:function(b){return A(b).data("$scope")||fb(b.parentNode||b,["$isolateScope","$scope"])},isolateScope:function(b){return A(b).data("$isolateScope")||A(b).data("$isolateScopeNoTemplate")},controller:dc,injector:function(b){return fb(b,"$injector")},removeAttr:function(b,a){b.removeAttribute(a)},hasClass:Cb,css:function(b,a,c){a=Ra(a);if(B(c))b.style[a]=c;else{var d; -8>=M&&(d=b.currentStyle&&b.currentStyle[a],""===d&&(d="auto"));d=d||b.style[a];8>=M&&(d=""===d?r:d);return d}},attr:function(b,a,c){var d=x(a);if(gb[d])if(B(c))c?(b[a]=!0,b.setAttribute(a,d)):(b[a]=!1,b.removeAttribute(d));else return b[a]||(b.attributes.getNamedItem(a)||w).specified?d:r;else if(B(c))b.setAttribute(a,c);else if(b.getAttribute)return b=b.getAttribute(a,2),null===b?r:b},prop:function(b,a,c){if(B(c))b[a]=c;else return b[a]},text:function(){function b(b,d){var e=a[b.nodeType];if(z(d))return e? -b[e]:"";b[e]=d}var a=[];9>M?(a[1]="innerText",a[3]="nodeValue"):a[1]=a[3]="textContent";b.$dv="";return b}(),val:function(b,a){if(z(a)){if("SELECT"===Ha(b)&&b.multiple){var c=[];q(b.options,function(a){a.selected&&c.push(a.value||a.text)});return 0===c.length?null:c}return b.value}b.value=a},html:function(b,a){if(z(a))return b.innerHTML;for(var c=0,d=b.childNodes;c":function(a,c,d,e){return d(a,c)>e(a,c)},"<=":function(a,c,d,e){return d(a,c)<=e(a,c)},">=":function(a,c,d,e){return d(a,c)>=e(a,c)},"&&":function(a,c,d,e){return d(a,c)&&e(a,c)},"||":function(a,c,d,e){return d(a,c)||e(a,c)},"&":function(a,c,d,e){return d(a,c)&e(a,c)},"|":function(a,c,d,e){return e(a,c)(a,c,d(a,c))}, -"!":function(a,c,d){return!d(a,c)}},Wd={n:"\n",f:"\f",r:"\r",t:"\t",v:"\v","'":"'",'"':'"'},Lb=function(a){this.options=a};Lb.prototype={constructor:Lb,lex:function(a){this.text=a;this.index=0;this.ch=r;this.lastCh=":";this.tokens=[];var c;for(a=[];this.index=a},isWhitespace:function(a){return" "=== -a||"\r"===a||"\t"===a||"\n"===a||"\v"===a||"\u00a0"===a},isIdent:function(a){return"a"<=a&&"z">=a||"A"<=a&&"Z">=a||"_"===a||"$"===a},isExpOperator:function(a){return"-"===a||"+"===a||this.isNumber(a)},throwError:function(a,c,d){d=d||this.index;c=B(c)?"s "+c+"-"+this.index+" ["+this.text.substring(c,d)+"]":" "+d;throw za("lexerr",a,c,this.text);},readNumber:function(){for(var a="",c=this.index;this.index").append(b).html();try{return 3===b[0].nodeType?O(c):c.match(/^(<[^>]+>)/)[1].replace(/^<([\w\-]+)/, +function(a,b){return"<"+O(b)})}catch(d){return O(c)}}function Xb(b){try{return decodeURIComponent(b)}catch(a){}}function Yb(b){var a={},c,d;r((b||"").split("&"),function(b){b&&(c=b.split("="),d=Xb(c[0]),v(d)&&(b=v(c[1])?Xb(c[1]):!0,a[d]?H(a[d])?a[d].push(b):a[d]=[a[d],b]:a[d]=b))});return a}function Zb(b){var a=[];r(b,function(b,d){H(b)?r(b,function(b){a.push(va(d,!0)+(!0===b?"":"="+va(b,!0)))}):a.push(va(d,!0)+(!0===b?"":"="+va(b,!0)))});return a.length?a.join("&"):""}function xb(b){return va(b, +!0).replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+")}function va(b,a){return encodeURIComponent(b).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,a?"%20":"+")}function Uc(b,a){function c(a){a&&d.push(a)}var d=[b],e,f,g=["ng:app","ng-app","x-ng-app","data-ng-app"],h=/\sng[:\-]app(:\s*([\w\d_]+);?)?\s/;r(g,function(a){g[a]=!0;c(T.getElementById(a));a=a.replace(":","\\:");b.querySelectorAll&&(r(b.querySelectorAll("."+a),c),r(b.querySelectorAll("."+ +a+"\\:"),c),r(b.querySelectorAll("["+a+"]"),c))});r(d,function(a){if(!e){var b=h.exec(" "+a.className+" ");b?(e=a,f=(b[2]||"").replace(/\s+/g,",")):r(a.attributes,function(b){!e&&g[b.name]&&(e=a,f=b.value)})}});e&&a(e,f?[f]:[])}function $b(b,a){var c=function(){b=z(b);if(b.injector()){var c=b[0]===T?"document":ga(b);throw Oa("btstrpd",c);}a=a||[];a.unshift(["$provide",function(a){a.value("$rootElement",b)}]);a.unshift("ng");c=ac(a);c.invoke(["$rootScope","$rootElement","$compile","$injector","$animate", +function(a,b,c,d,e){a.$apply(function(){b.data("$injector",d);c(b)(a)})}]);return c},d=/^NG_DEFER_BOOTSTRAP!/;if(C&&!d.test(C.name))return c();C.name=C.name.replace(d,"");Ba.resumeBootstrap=function(b){r(b,function(b){a.push(b)});c()}}function db(b,a){a=a||"_";return b.replace(Vc,function(b,d){return(d?a:"")+b.toLowerCase()})}function yb(b,a,c){if(!b)throw Oa("areq",a||"?",c||"required");return b}function Qa(b,a,c){c&&H(b)&&(b=b[b.length-1]);yb(N(b),a,"not a function, got "+(b&&"object"==typeof b? +b.constructor.name||"Object":typeof b));return b}function wa(b,a){if("hasOwnProperty"===b)throw Oa("badname",a);}function bc(b,a,c){if(!a)return b;a=a.split(".");for(var d,e=b,f=a.length,g=0;g "+b;a.removeChild(a.firstChild);Cb(this,a.childNodes);z(T.createDocumentFragment()).append(this)}else Cb(this, +b)}function Db(b){return b.cloneNode(!0)}function Da(b){cc(b);var a=0;for(b=b.childNodes||[];a=P?(c.preventDefault=null,c.stopPropagation=null,c.isDefaultPrevented=null):(delete c.preventDefault,delete c.stopPropagation,delete c.isDefaultPrevented)};c.elem=b;return c}function Ea(b){var a=typeof b,c;"object"==a&&null!==b?"function"==typeof(c=b.$$hashKey)?c=b.$$hashKey():c=== +s&&(c=b.$$hashKey=$a()):c=b;return a+":"+c}function Ta(b){r(b,this.put,this)}function jc(b){var a,c;"function"==typeof b?(a=b.$inject)||(a=[],b.length&&(c=b.toString().replace(ad,""),c=c.match(bd),r(c[1].split(cd),function(b){b.replace(dd,function(b,c,d){a.push(d)})})),b.$inject=a):H(b)?(c=b.length-1,Qa(b[c],"fn"),a=b.slice(0,c)):Qa(b,"fn",!0);return a}function ac(b){function a(a){return function(b,c){if(Z(b))r(b,Rb(a));else return a(b,c)}}function c(a,b){wa(a,"service");if(N(b)||H(b))b=m.instantiate(b); +if(!b.$get)throw Ua("pget",a);return l[a+h]=b}function d(a,b){return c(a,{$get:b})}function e(a){var b=[],c,d,f,h;r(a,function(a){if(!k.get(a)){k.put(a,!0);try{if(D(a))for(c=Va(a),b=b.concat(e(c.requires)).concat(c._runBlocks),d=c._invokeQueue,f=0,h=d.length;f 4096 bytes)!"));else{if(n.cookie!==ba)for(ba=n.cookie,d=ba.split("; "),L={},f=0;fk&&this.remove(p.key),b},get:function(a){var b=l[a];if(b)return e(b),n[a]},remove:function(a){var b=l[a];b&&(b==m&&(m=b.p),b==p&&(p=b.n),f(b.n,b.p),delete l[a],delete n[a],g--)},removeAll:function(){n={};g=0;l={};m=p=null},destroy:function(){l=h=n=null;delete a[b]},info:function(){return t({},h,{size:g})}}}var a={};b.info=function(){var b={};r(a,function(a,e){b[e]=a.info()});return b};b.get=function(b){return a[b]}; +return b}}function id(){this.$get=["$cacheFactory",function(b){return b("templates")}]}function kc(b,a){var c={},d="Directive",e=/^\s*directive\:\s*([\d\w\-_]+)\s+(.*)$/,f=/(([\d\w\-_]+)(?:\:([^;]+))?;?)/,g=/^<\s*(tr|th|td|tbody)(\s+[^>]*)?>/i,h=/^(on[a-z]+|formaction)$/;this.directive=function k(a,e){wa(a,"directive");D(a)?(yb(e,"directiveFactory"),c.hasOwnProperty(a)||(c[a]=[],b.factory(a+d,["$injector","$exceptionHandler",function(b,d){var e=[];r(c[a],function(c,f){try{var h=b.invoke(c);N(h)?h= +{compile:aa(h)}:!h.compile&&h.link&&(h.compile=aa(h.link));h.priority=h.priority||0;h.index=f;h.name=h.name||a;h.require=h.require||h.controller&&h.name;h.restrict=h.restrict||"A";e.push(h)}catch(g){d(g)}});return e}])),c[a].push(e)):r(a,Rb(k));return this};this.aHrefSanitizationWhitelist=function(b){return v(b)?(a.aHrefSanitizationWhitelist(b),this):a.aHrefSanitizationWhitelist()};this.imgSrcSanitizationWhitelist=function(b){return v(b)?(a.imgSrcSanitizationWhitelist(b),this):a.imgSrcSanitizationWhitelist()}; +this.$get=["$injector","$interpolate","$exceptionHandler","$http","$templateCache","$parse","$controller","$rootScope","$document","$sce","$animate","$$sanitizeUri",function(a,b,m,p,q,A,B,I,u,G,W,y){function Y(a,b,c,d,e){a instanceof z||(a=z(a));r(a,function(b,c){3==b.nodeType&&b.nodeValue.match(/\S+/)&&(a[c]=z(b).wrap("").parent()[0])});var f=L(a,b,a,c,d,e);S(a,"ng-scope");return function(b,c,d){yb(b,"scope");var e=c?Fa.clone.call(a):a;r(d,function(a,b){e.data("$"+b+"Controller",a)}); +d=0;for(var h=e.length;darguments.length&&(b=a,a=s);Ha&&(c=lb);return q(a,b,c)}var K,y,u,Y,M,U,lb={},v;K=c===f?d:Ub(d,new Gb(z(f),d.$attr));y=K.$$element;if(L){var t=/^\s*([@=&])(\??)\s*(\w*)\s*$/;h=z(f);U=e.$new(!0);ba&&ba===L.$$originalDirective?h.data("$isolateScope",U):h.data("$isolateScopeNoTemplate",U);S(h,"ng-isolate-scope");r(L.scope,function(a,c){var d=a.match(t)||[],f=d[3]||c,h="?"==d[2],d=d[1],g,k,q,m;U.$$isolateBindings[c]=d+f;switch(d){case "@":K.$observe(f,function(a){U[c]= +a});K.$$observers[f].$$scope=e;K[f]&&(U[c]=b(K[f])(e));break;case "=":if(h&&!K[f])break;k=A(K[f]);m=k.literal?ta:function(a,b){return a===b};q=k.assign||function(){g=U[c]=k(e);throw ia("nonassign",K[f],L.name);};g=U[c]=k(e);U.$watch(function(){var a=k(e);m(a,U[c])||(m(a,g)?q(e,a=U[c]):U[c]=a);return g=a},null,k.literal);break;case "&":k=A(K[f]);U[c]=function(a){return k(e,a)};break;default:throw ia("iscp",L.name,c,a);}})}v=q&&p;W&&r(W,function(a){var b={$scope:a===L||a.$$isolateScope?U:e,$element:y, +$attrs:K,$transclude:v},c;M=a.controller;"@"==M&&(M=K[a.name]);c=B(M,b);lb[a.name]=c;Ha||y.data("$"+a.name+"Controller",c);a.controllerAs&&(b.$scope[a.controllerAs]=c)});h=0;for(u=g.length;hF.priority)break;if(t=F.scope)u=u||F,F.templateUrl||(R("new/isolated scope",L,F,J),Z(t)&&(L=F));ha=F.name;!F.templateUrl&&F.controller&&(t=F.controller,W=W||{},R("'"+ha+"' controller",W[ha],F,J),W[ha]=F);if(t=F.transclude)Wa=!0,F.$$tlb|| +(R("transclusion",v,F,J),v=F),"element"==t?(Ha=!0,y=F.priority,t=M(c,Q,V),J=d.$$element=z(T.createComment(" "+ha+": "+d[ha]+" ")),c=J[0],mb(f,z(ua.call(t,0)),c),E=Y(t,e,y,h&&h.name,{nonTlbTranscludeDirective:v})):(t=z(Db(c)).contents(),J.empty(),E=Y(t,e));if(F.template)if(R("template",ba,F,J),ba=F,t=N(F.template)?F.template(J,d):F.template,t=X(t),F.replace){h=F;t=x(t);c=t[0];if(1!=t.length||1!==c.nodeType)throw ia("tplrt",ha,"");mb(f,J,c);P={$attr:{}};t=U(c,[],P);var $=a.splice(C+1,a.length-(C+1)); +L&&kb(t);a=a.concat(t).concat($);w(d,P);P=a.length}else J.html(t);if(F.templateUrl)R("template",ba,F,J),ba=F,F.replace&&(h=F),I=O(a.splice(C,a.length-C),J,d,f,E,g,k,{controllerDirectives:W,newIsolateScopeDirective:L,templateDirective:ba,nonTlbTranscludeDirective:v}),P=a.length;else if(F.compile)try{pa=F.compile(J,d,E),N(pa)?p(null,pa,Q,V):pa&&p(pa.pre,pa.post,Q,V)}catch(aa){m(aa,ga(J))}F.terminal&&(I.terminal=!0,y=Math.max(y,F.priority))}I.scope=u&&!0===u.scope;I.transclude=Wa&&E;q.hasElementTranscludeDirective= +Ha;return I}function kb(a){for(var b=0,c=a.length;bp.priority)&&-1!=p.restrict.indexOf(f)&&(q&&(p=Tb(p,{$$start:q,$$end:l})),b.push(p),g=p)}catch(B){m(B)}}return g}function w(a,b){var c=b.$attr,d=a.$attr,e=a.$$element;r(a,function(d,e){"$"!=e.charAt(0)&&(b[e]&&(d+=("style"===e?";":" ")+b[e]),a.$set(e,d,!0,c[e]))}); +r(b,function(b,f){"class"==f?(S(e,b),a["class"]=(a["class"]?a["class"]+" ":"")+b):"style"==f?(e.attr("style",e.attr("style")+";"+b),a.style=(a.style?a.style+";":"")+b):"$"==f.charAt(0)||a.hasOwnProperty(f)||(a[f]=b,d[f]=c[f])})}function x(a){var b;a=da(a);if(b=g.exec(a)){b=b[1].toLowerCase();a=z(""+a+"
");var c=a.children("tbody"),d=/(td|th)/.test(b)&&a.find("tr");c.length&&"tbody"!==b&&(a=c);d&&d.length&&(a=d);return a.contents()}return z("
"+a+"
").contents()}function O(a, +b,c,d,e,f,h,g){var k=[],l,m,A=b[0],B=a.shift(),y=t({},B,{templateUrl:null,transclude:null,replace:null,$$originalDirective:B}),I=N(B.templateUrl)?B.templateUrl(b,c):B.templateUrl;b.empty();p.get(G.getTrustedResourceUrl(I),{cache:q}).success(function(q){var p,G;q=X(q);if(B.replace){q=x(q);p=q[0];if(1!=q.length||1!==p.nodeType)throw ia("tplrt",B.name,I);q={$attr:{}};mb(d,b,p);var u=U(p,[],q);Z(B.scope)&&kb(u);a=u.concat(a);w(c,q)}else p=A,b.html(q);a.unshift(y);l=Wa(a,p,c,e,b,B,f,h,g);r(d,function(a, +c){a==p&&(d[c]=b[0])});for(m=L(b[0].childNodes,e);k.length;){q=k.shift();G=k.shift();var W=k.shift(),Y=k.shift(),u=b[0];if(G!==A){var M=G.className;g.hasElementTranscludeDirective&&B.replace||(u=Db(p));mb(W,z(G),u);S(z(u),M)}G=l.transclude?ba(q,l.transclude):Y;l(m,q,u,d,G)}k=null}).error(function(a,b,c,d){throw ia("tpload",d.url);});return function(a,b,c,d,e){k?(k.push(b),k.push(c),k.push(d),k.push(e)):l(m,b,c,d,e)}}function E(a,b){var c=b.priority-a.priority;return 0!==c?c:a.name!==b.name?a.name< +b.name?-1:1:a.index-b.index}function R(a,b,c,d){if(b)throw ia("multidir",b.name,c.name,a,ga(d));}function C(a,c){var d=b(c,!0);d&&a.push({priority:0,compile:aa(function(a,b){var c=b.parent(),e=c.data("$binding")||[];e.push(d);S(c.data("$binding",e),"ng-binding");a.$watch(d,function(a){b[0].nodeValue=a})})})}function Ha(a,b){if("srcdoc"==b)return G.HTML;var c=Ga(a);if("xlinkHref"==b||"FORM"==c&&"action"==b||"IMG"!=c&&("src"==b||"ngSrc"==b))return G.RESOURCE_URL}function ha(a,c,d,e){var f=b(d,!0);if(f){if("multiple"=== +e&&"SELECT"===Ga(a))throw ia("selmulti",ga(a));c.push({priority:100,compile:function(){return{pre:function(c,d,g){d=g.$$observers||(g.$$observers={});if(h.test(e))throw ia("nodomevents");if(f=b(g[e],!0,Ha(a,e)))g[e]=f(c),(d[e]||(d[e]=[])).$$inter=!0,(g.$$observers&&g.$$observers[e].$$scope||c).$watch(f,function(a,b){"class"===e&&a!=b?g.$updateClass(a,b):g.$set(e,a)})}}}})}}function mb(a,b,c){var d=b[0],e=b.length,f=d.parentNode,h,g;if(a)for(h=0,g=a.length;ha.status?b:m.reject(b)}var d={transformRequest:e.transformRequest,transformResponse:e.transformResponse},f=function(a){function b(a){var c;r(a,function(b,d){N(b)&&(c=b(),null!=c?a[d]=c:delete a[d])})}var c=e.headers,d=t({},a.headers), +f,h,c=t({},c.common,c[O(a.method)]);b(c);b(d);a:for(f in c){a=O(f);for(h in d)if(O(h)===a)continue a;d[f]=c[f]}return d}(a);t(d,a);d.headers=f;d.method=Ia(d.method);(a=Hb(d.url)?b.cookies()[d.xsrfCookieName||e.xsrfCookieName]:s)&&(f[d.xsrfHeaderName||e.xsrfHeaderName]=a);var h=[function(a){f=a.headers;var b=pc(a.data,oc(f),a.transformRequest);x(a.data)&&r(f,function(a,b){"content-type"===O(b)&&delete f[b]});x(a.withCredentials)&&!x(e.withCredentials)&&(a.withCredentials=e.withCredentials);return A(a, +b,f).then(c,c)},s],g=m.when(d);for(r(u,function(a){(a.request||a.requestError)&&h.unshift(a.request,a.requestError);(a.response||a.responseError)&&h.push(a.response,a.responseError)});h.length;){a=h.shift();var k=h.shift(),g=g.then(a,k)}g.success=function(a){g.then(function(b){a(b.data,b.status,b.headers,d)});return g};g.error=function(a){g.then(null,function(b){a(b.data,b.status,b.headers,d)});return g};return g}function A(b,c,f){function g(a,b,c){u&&(200<=a&&300>a?u.put(s,[a,b,nc(c)]):u.remove(s)); +k(b,a,c);d.$$phase||d.$apply()}function k(a,c,d){c=Math.max(c,0);(200<=c&&300>c?p.resolve:p.reject)({data:a,status:c,headers:oc(d),config:b})}function n(){var a=bb(q.pendingRequests,b);-1!==a&&q.pendingRequests.splice(a,1)}var p=m.defer(),A=p.promise,u,r,s=B(b.url,b.params);q.pendingRequests.push(b);A.then(n,n);(b.cache||e.cache)&&(!1!==b.cache&&"GET"==b.method)&&(u=Z(b.cache)?b.cache:Z(e.cache)?e.cache:I);if(u)if(r=u.get(s),v(r)){if(r.then)return r.then(n,n),r;H(r)?k(r[1],r[0],ca(r[2])):k(r,200, +{})}else u.put(s,A);x(r)&&a(b.method,s,c,g,f,b.timeout,b.withCredentials,b.responseType);return A}function B(a,b){if(!b)return a;var c=[];Qc(b,function(a,b){null===a||x(a)||(H(a)||(a=[a]),r(a,function(a){Z(a)&&(a=oa(a));c.push(va(b)+"="+va(a))}))});return a+(-1==a.indexOf("?")?"?":"&")+c.join("&")}var I=c("$http"),u=[];r(f,function(a){u.unshift(D(a)?p.get(a):p.invoke(a))});r(g,function(a,b){var c=D(a)?p.get(a):p.invoke(a);u.splice(b,0,{response:function(a){return c(m.when(a))},responseError:function(a){return c(m.reject(a))}})}); +q.pendingRequests=[];(function(a){r(arguments,function(a){q[a]=function(b,c){return q(t(c||{},{method:a,url:b}))}})})("get","delete","head","jsonp");(function(a){r(arguments,function(a){q[a]=function(b,c,d){return q(t(d||{},{method:a,url:b,data:c}))}})})("post","put");q.defaults=e;return q}]}function od(b){if(8>=P&&(!b.match(/^(get|post|head|put|delete|options)$/i)||!C.XMLHttpRequest))return new C.ActiveXObject("Microsoft.XMLHTTP");if(C.XMLHttpRequest)return new C.XMLHttpRequest;throw E("$httpBackend")("noxhr"); +}function pd(){this.$get=["$browser","$window","$document",function(b,a,c){return qd(b,od,b.defer,a.angular.callbacks,c[0])}]}function qd(b,a,c,d,e){function f(a,b){var c=e.createElement("script"),d=function(){c.onreadystatechange=c.onload=c.onerror=null;e.body.removeChild(c);b&&b()};c.type="text/javascript";c.src=a;P&&8>=P?c.onreadystatechange=function(){/loaded|complete/.test(c.readyState)&&d()}:c.onload=c.onerror=function(){d()};e.body.appendChild(c);return d}var g=-1;return function(e,n,k,l,m, +p,q,A){function B(){u=g;W&&W();y&&y.abort()}function I(a,d,e,f){S&&c.cancel(S);W=y=null;d=0===d?e?200:404:d;a(1223==d?204:d,e,f);b.$$completeOutstandingRequest(w)}var u;b.$$incOutstandingRequestCount();n=n||b.url();if("jsonp"==O(e)){var G="_"+(d.counter++).toString(36);d[G]=function(a){d[G].data=a};var W=f(n.replace("JSON_CALLBACK","angular.callbacks."+G),function(){d[G].data?I(l,200,d[G].data):I(l,u||-2);d[G]=Ba.noop})}else{var y=a(e);y.open(e,n,!0);r(m,function(a,b){v(a)&&y.setRequestHeader(b,a)}); +y.onreadystatechange=function(){if(y&&4==y.readyState){var a=null,b=null;u!==g&&(a=y.getAllResponseHeaders(),b="response"in y?y.response:y.responseText);I(l,u||y.status,b,a)}};q&&(y.withCredentials=!0);if(A)try{y.responseType=A}catch(Y){if("json"!==A)throw Y;}y.send(k||null)}if(0=h&&(m.resolve(q),l(p.$$intervalId),delete e[p.$$intervalId]); +A||b.$apply()},g);e[p.$$intervalId]=m;return p}var e={};d.cancel=function(a){return a&&a.$$intervalId in e?(e[a.$$intervalId].reject("canceled"),clearInterval(a.$$intervalId),delete e[a.$$intervalId],!0):!1};return d}]}function td(){this.$get=function(){return{id:"en-us",NUMBER_FORMATS:{DECIMAL_SEP:".",GROUP_SEP:",",PATTERNS:[{minInt:1,minFrac:0,maxFrac:3,posPre:"",posSuf:"",negPre:"-",negSuf:"",gSize:3,lgSize:3},{minInt:1,minFrac:2,maxFrac:2,posPre:"\u00a4",posSuf:"",negPre:"(\u00a4",negSuf:")", +gSize:3,lgSize:3}],CURRENCY_SYM:"$"},DATETIME_FORMATS:{MONTH:"January February March April May June July August September October November December".split(" "),SHORTMONTH:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),DAY:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),SHORTDAY:"Sun Mon Tue Wed Thu Fri Sat".split(" "),AMPMS:["AM","PM"],medium:"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a",fullDate:"EEEE, MMMM d, y",longDate:"MMMM d, y",mediumDate:"MMM d, y",shortDate:"M/d/yy", +mediumTime:"h:mm:ss a",shortTime:"h:mm a"},pluralCat:function(b){return 1===b?"one":"other"}}}}function rc(b){b=b.split("/");for(var a=b.length;a--;)b[a]=xb(b[a]);return b.join("/")}function sc(b,a,c){b=xa(b,c);a.$$protocol=b.protocol;a.$$host=b.hostname;a.$$port=Q(b.port)||ud[b.protocol]||null}function tc(b,a,c){var d="/"!==b.charAt(0);d&&(b="/"+b);b=xa(b,c);a.$$path=decodeURIComponent(d&&"/"===b.pathname.charAt(0)?b.pathname.substring(1):b.pathname);a.$$search=Yb(b.search);a.$$hash=decodeURIComponent(b.hash); +a.$$path&&"/"!=a.$$path.charAt(0)&&(a.$$path="/"+a.$$path)}function ma(b,a){if(0===a.indexOf(b))return a.substr(b.length)}function Xa(b){var a=b.indexOf("#");return-1==a?b:b.substr(0,a)}function Ib(b){return b.substr(0,Xa(b).lastIndexOf("/")+1)}function uc(b,a){this.$$html5=!0;a=a||"";var c=Ib(b);sc(b,this,b);this.$$parse=function(a){var e=ma(c,a);if(!D(e))throw Jb("ipthprfx",a,c);tc(e,this,b);this.$$path||(this.$$path="/");this.$$compose()};this.$$compose=function(){var a=Zb(this.$$search),b=this.$$hash? +"#"+xb(this.$$hash):"";this.$$url=rc(this.$$path)+(a?"?"+a:"")+b;this.$$absUrl=c+this.$$url.substr(1)};this.$$rewrite=function(d){var e;if((e=ma(b,d))!==s)return d=e,(e=ma(a,e))!==s?c+(ma("/",e)||e):b+d;if((e=ma(c,d))!==s)return c+e;if(c==d+"/")return c}}function Kb(b,a){var c=Ib(b);sc(b,this,b);this.$$parse=function(d){var e=ma(b,d)||ma(c,d),e="#"==e.charAt(0)?ma(a,e):this.$$html5?e:"";if(!D(e))throw Jb("ihshprfx",d,a);tc(e,this,b);d=this.$$path;var f=/^\/?.*?:(\/.*)/;0===e.indexOf(b)&&(e=e.replace(b, +""));f.exec(e)||(d=(e=f.exec(d))?e[1]:d);this.$$path=d;this.$$compose()};this.$$compose=function(){var c=Zb(this.$$search),e=this.$$hash?"#"+xb(this.$$hash):"";this.$$url=rc(this.$$path)+(c?"?"+c:"")+e;this.$$absUrl=b+(this.$$url?a+this.$$url:"")};this.$$rewrite=function(a){if(Xa(b)==Xa(a))return a}}function vc(b,a){this.$$html5=!0;Kb.apply(this,arguments);var c=Ib(b);this.$$rewrite=function(d){var e;if(b==Xa(d))return d;if(e=ma(c,d))return b+a+e;if(c===d+"/")return c}}function nb(b){return function(){return this[b]}} +function wc(b,a){return function(c){if(x(c))return this[b];this[b]=a(c);this.$$compose();return this}}function vd(){var b="",a=!1;this.hashPrefix=function(a){return v(a)?(b=a,this):b};this.html5Mode=function(b){return v(b)?(a=b,this):a};this.$get=["$rootScope","$browser","$sniffer","$rootElement",function(c,d,e,f){function g(a){c.$broadcast("$locationChangeSuccess",h.absUrl(),a)}var h,n=d.baseHref(),k=d.url();a?(n=k.substring(0,k.indexOf("/",k.indexOf("//")+2))+(n||"/"),e=e.history?uc:vc):(n=Xa(k), +e=Kb);h=new e(n,"#"+b);h.$$parse(h.$$rewrite(k));f.on("click",function(a){if(!a.ctrlKey&&!a.metaKey&&2!=a.which){for(var b=z(a.target);"a"!==O(b[0].nodeName);)if(b[0]===f[0]||!(b=b.parent())[0])return;var e=b.prop("href");Z(e)&&"[object SVGAnimatedString]"===e.toString()&&(e=xa(e.animVal).href);var g=h.$$rewrite(e);e&&(!b.attr("target")&&g&&!a.isDefaultPrevented())&&(a.preventDefault(),g!=d.url()&&(h.$$parse(g),c.$apply(),C.angular["ff-684208-preventDefault"]=!0))}});h.absUrl()!=k&&d.url(h.absUrl(), +!0);d.onUrlChange(function(a){h.absUrl()!=a&&(c.$evalAsync(function(){var b=h.absUrl();h.$$parse(a);c.$broadcast("$locationChangeStart",a,b).defaultPrevented?(h.$$parse(b),d.url(b)):g(b)}),c.$$phase||c.$digest())});var l=0;c.$watch(function(){var a=d.url(),b=h.$$replace;l&&a==h.absUrl()||(l++,c.$evalAsync(function(){c.$broadcast("$locationChangeStart",h.absUrl(),a).defaultPrevented?h.$$parse(a):(d.url(h.absUrl(),b),g(a))}));h.$$replace=!1;return l});return h}]}function wd(){var b=!0,a=this;this.debugEnabled= +function(a){return v(a)?(b=a,this):b};this.$get=["$window",function(c){function d(a){a instanceof Error&&(a.stack?a=a.message&&-1===a.stack.indexOf(a.message)?"Error: "+a.message+"\n"+a.stack:a.stack:a.sourceURL&&(a=a.message+"\n"+a.sourceURL+":"+a.line));return a}function e(a){var b=c.console||{},e=b[a]||b.log||w;a=!1;try{a=!!e.apply}catch(n){}return a?function(){var a=[];r(arguments,function(b){a.push(d(b))});return e.apply(b,a)}:function(a,b){e(a,null==b?"":b)}}return{log:e("log"),info:e("info"), +warn:e("warn"),error:e("error"),debug:function(){var c=e("debug");return function(){b&&c.apply(a,arguments)}}()}}]}function ea(b,a){if("constructor"===b)throw ya("isecfld",a);return b}function Ya(b,a){if(b){if(b.constructor===b)throw ya("isecfn",a);if(b.document&&b.location&&b.alert&&b.setInterval)throw ya("isecwindow",a);if(b.children&&(b.nodeName||b.on&&b.find))throw ya("isecdom",a);}return b}function ob(b,a,c,d,e){e=e||{};a=a.split(".");for(var f,g=0;1e?xc(d[0],d[1],d[2],d[3],d[4],c,a):function(b,f){var h=0,g;do g=xc(d[h++],d[h++],d[h++],d[h++],d[h++],c,a)(b,f),f=s,b=g;while(ha)for(b in h++,d)d.hasOwnProperty(b)&&!e.hasOwnProperty(b)&&(l--,delete d[b])}else d!== +e&&(d=e,h++);return h},function(){b(e,d,c)})},$digest:function(){var d,f,h,g,k=this.$$asyncQueue,l=this.$$postDigestQueue,r,y,s=b,S,L=[],v,t,M;n("$digest");c=null;do{y=!1;for(S=this;k.length;){try{M=k.shift(),M.scope.$eval(M.expression)}catch(z){p.$$phase=null,e(z)}c=null}a:do{if(g=S.$$watchers)for(r=g.length;r--;)try{if(d=g[r])if((f=d.get(S))!==(h=d.last)&&!(d.eq?ta(f,h):"number"==typeof f&&"number"==typeof h&&isNaN(f)&&isNaN(h)))y=!0,c=d,d.last=d.eq?ca(f):f,d.fn(f,h===m?f:h,S),5>s&&(v=4-s,L[v]|| +(L[v]=[]),t=N(d.exp)?"fn: "+(d.exp.name||d.exp.toString()):d.exp,t+="; newVal: "+oa(f)+"; oldVal: "+oa(h),L[v].push(t));else if(d===c){y=!1;break a}}catch(D){p.$$phase=null,e(D)}if(!(g=S.$$childHead||S!==this&&S.$$nextSibling))for(;S!==this&&!(g=S.$$nextSibling);)S=S.$parent}while(S=g);if((y||k.length)&&!s--)throw p.$$phase=null,a("infdig",b,oa(L));}while(y||k.length);for(p.$$phase=null;l.length;)try{l.shift()()}catch(w){e(w)}},$destroy:function(){if(!this.$$destroyed){var a=this.$parent;this.$broadcast("$destroy"); +this.$$destroyed=!0;this!==p&&(r(this.$$listenerCount,cb(null,l,this)),a.$$childHead==this&&(a.$$childHead=this.$$nextSibling),a.$$childTail==this&&(a.$$childTail=this.$$prevSibling),this.$$prevSibling&&(this.$$prevSibling.$$nextSibling=this.$$nextSibling),this.$$nextSibling&&(this.$$nextSibling.$$prevSibling=this.$$prevSibling),this.$parent=this.$$nextSibling=this.$$prevSibling=this.$$childHead=this.$$childTail=null)}},$eval:function(a,b){return f(a)(this,b)},$evalAsync:function(a){p.$$phase||p.$$asyncQueue.length|| +g.defer(function(){p.$$asyncQueue.length&&p.$digest()});this.$$asyncQueue.push({scope:this,expression:a})},$$postDigest:function(a){this.$$postDigestQueue.push(a)},$apply:function(a){try{return n("$apply"),this.$eval(a)}catch(b){e(b)}finally{p.$$phase=null;try{p.$digest()}catch(c){throw e(c),c;}}},$on:function(a,b){var c=this.$$listeners[a];c||(this.$$listeners[a]=c=[]);c.push(b);var d=this;do d.$$listenerCount[a]||(d.$$listenerCount[a]=0),d.$$listenerCount[a]++;while(d=d.$parent);var e=this;return function(){c[bb(c, +b)]=null;l(e,1,a)}},$emit:function(a,b){var c=[],d,f=this,h=!1,g={name:a,targetScope:f,stopPropagation:function(){h=!0},preventDefault:function(){g.defaultPrevented=!0},defaultPrevented:!1},k=[g].concat(ua.call(arguments,1)),n,l;do{d=f.$$listeners[a]||c;g.currentScope=f;n=0;for(l=d.length;nc.msieDocumentMode)throw ra("iequirks");var e=ca(fa);e.isEnabled=function(){return b};e.trustAs=d.trustAs;e.getTrusted=d.getTrusted;e.valueOf=d.valueOf;b||(e.trustAs=e.getTrusted=function(a,b){return b},e.valueOf=Aa);e.parseAs=function(b,c){var d=a(c);return d.literal&&d.constant?d:function(a,c){return e.getTrusted(b,d(a,c))}};var f=e.parseAs, +g=e.getTrusted,h=e.trustAs;r(fa,function(a,b){var c=O(b);e[Ra("parse_as_"+c)]=function(b){return f(a,b)};e[Ra("get_trusted_"+c)]=function(b){return g(a,b)};e[Ra("trust_as_"+c)]=function(b){return h(a,b)}});return e}]}function Hd(){this.$get=["$window","$document",function(b,a){var c={},d=Q((/android (\d+)/.exec(O((b.navigator||{}).userAgent))||[])[1]),e=/Boxee/i.test((b.navigator||{}).userAgent),f=a[0]||{},g=f.documentMode,h,n=/^(Moz|webkit|O|ms)(?=[A-Z])/,k=f.body&&f.body.style,l=!1,m=!1;if(k){for(var p in k)if(l= +n.exec(p)){h=l[0];h=h.substr(0,1).toUpperCase()+h.substr(1);break}h||(h="WebkitOpacity"in k&&"webkit");l=!!("transition"in k||h+"Transition"in k);m=!!("animation"in k||h+"Animation"in k);!d||l&&m||(l=D(f.body.style.webkitTransition),m=D(f.body.style.webkitAnimation))}return{history:!(!b.history||!b.history.pushState||4>d||e),hashchange:"onhashchange"in b&&(!g||7b;b=Math.abs(b);var g=b+"",h="",n=[],k=!1;if(-1!==g.indexOf("e")){var l=g.match(/([\d\.]+)e(-?)(\d+)/);l&&"-"==l[2]&&l[3]>e+1?g="0":(h=g,k=!0)}if(k)0b)&&(h=b.toFixed(e));else{g=(g.split(Ic)[1]||"").length; +x(e)&&(e=Math.min(Math.max(a.minFrac,g),a.maxFrac));g=Math.pow(10,e);b=Math.round(b*g)/g;b=(""+b).split(Ic);g=b[0];b=b[1]||"";var l=0,m=a.lgSize,p=a.gSize;if(g.length>=m+p)for(l=g.length-m,k=0;kb&&(d="-",b=-b); +for(b=""+b;b.length-c)e+=c;0===e&&-12==c&&(e=12);return Nb(e,a,d)}}function pb(b,a){return function(c,d){var e=c["get"+b](),f=Ia(a?"SHORT"+b:b);return d[f][e]}}function Ec(b){function a(a){var b;if(b=a.match(c)){a=new Date(0);var f=0,g=0,h=b[8]?a.setUTCFullYear:a.setFullYear,n=b[8]?a.setUTCHours:a.setHours;b[9]&&(f=Q(b[9]+b[10]),g=Q(b[9]+b[11]));h.call(a,Q(b[1]),Q(b[2])-1,Q(b[3])); +f=Q(b[4]||0)-f;g=Q(b[5]||0)-g;h=Q(b[6]||0);b=Math.round(1E3*parseFloat("0."+(b[7]||0)));n.call(a,f,g,h,b)}return a}var c=/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;return function(c,e){var f="",g=[],h,n;e=e||"mediumDate";e=b.DATETIME_FORMATS[e]||e;D(c)&&(c=Qd.test(c)?Q(c):a(c));wb(c)&&(c=new Date(c));if(!La(c))return c;for(;e;)(n=Rd.exec(e))?(g=g.concat(ua.call(n,1)),e=g.pop()):(g.push(e),e=null);r(g,function(a){h=Sd[a];f+=h?h(c,b.DATETIME_FORMATS): +a.replace(/(^'|'$)/g,"").replace(/''/g,"'")});return f}}function Ld(){return function(b){return oa(b,!0)}}function Md(){return function(b,a){if(!H(b)&&!D(b))return b;a=Q(a);if(D(b))return a?0<=a?b.slice(0,a):b.slice(a,b.length):"";var c=[],d,e;a>b.length?a=b.length:a<-b.length&&(a=-b.length);0a||37<=a&&40>=a)||k()});if(e.hasEvent("paste"))a.on("paste cut",k)}a.on("change",h);d.$render=function(){a.val(d.$isEmpty(d.$viewValue)?"":d.$viewValue)};var l=c.ngPattern;l&&((e=l.match(/^\/(.*)\/([gim]*)$/))?(l=RegExp(e[1],e[2]),e=function(a){return na(d,"pattern",d.$isEmpty(a)||l.test(a),a)}):e=function(c){var e=b.$eval(l);if(!e||!e.test)throw E("ngPattern")("noregexp",l,e,ga(a));return na(d,"pattern",d.$isEmpty(c)||e.test(c),c)},d.$formatters.push(e),d.$parsers.push(e));if(c.ngMinlength){var m= +Q(c.ngMinlength);e=function(a){return na(d,"minlength",d.$isEmpty(a)||a.length>=m,a)};d.$parsers.push(e);d.$formatters.push(e)}if(c.ngMaxlength){var p=Q(c.ngMaxlength);e=function(a){return na(d,"maxlength",d.$isEmpty(a)||a.length<=p,a)};d.$parsers.push(e);d.$formatters.push(e)}}function Ob(b,a){b="ngClass"+b;return function(){return{restrict:"AC",link:function(c,d,e){function f(b){if(!0===a||c.$index%2===a){var d=g(b||"");h?ta(b,h)||e.$updateClass(d,g(h)):e.$addClass(d)}h=ca(b)}function g(a){if(H(a))return a.join(" "); +if(Z(a)){var b=[];r(a,function(a,c){a&&b.push(c)});return b.join(" ")}return a}var h;c.$watch(e[b],f,!0);e.$observe("class",function(a){f(c.$eval(e[b]))});"ngClass"!==b&&c.$watch("$index",function(d,f){var h=d&1;if(h!==f&1){var m=g(c.$eval(e[b]));h===a?e.$addClass(m):e.$removeClass(m)}})}}}}var O=function(b){return D(b)?b.toLowerCase():b},Pd=Object.prototype.hasOwnProperty,Ia=function(b){return D(b)?b.toUpperCase():b},P,z,Ca,ua=[].slice,Td=[].push,Ma=Object.prototype.toString,Oa=E("ng"),Ba=C.angular|| +(C.angular={}),Va,Ga,ja=["0","0","0"];P=Q((/msie (\d+)/.exec(O(navigator.userAgent))||[])[1]);isNaN(P)&&(P=Q((/trident\/.*; rv:(\d+)/.exec(O(navigator.userAgent))||[])[1]));w.$inject=[];Aa.$inject=[];var da=function(){return String.prototype.trim?function(b){return D(b)?b.trim():b}:function(b){return D(b)?b.replace(/^\s\s*/,"").replace(/\s\s*$/,""):b}}();Ga=9>P?function(b){b=b.nodeName?b:b[0];return b.scopeName&&"HTML"!=b.scopeName?Ia(b.scopeName+":"+b.nodeName):b.nodeName}:function(b){return b.nodeName? +b.nodeName:b[0].nodeName};var Vc=/[A-Z]/g,Ud={full:"1.2.13",major:1,minor:2,dot:13,codeName:"romantic-transclusion"},Sa=R.cache={},eb=R.expando="ng-"+(new Date).getTime(),Zc=1,Kc=C.document.addEventListener?function(b,a,c){b.addEventListener(a,c,!1)}:function(b,a,c){b.attachEvent("on"+a,c)},Eb=C.document.removeEventListener?function(b,a,c){b.removeEventListener(a,c,!1)}:function(b,a,c){b.detachEvent("on"+a,c)};R._data=function(b){return this.cache[b[this.expando]]||{}};var Xc=/([\:\-\_]+(.))/g,Yc= +/^moz([A-Z])/,Bb=E("jqLite"),Fa=R.prototype={ready:function(b){function a(){c||(c=!0,b())}var c=!1;"complete"===T.readyState?setTimeout(a):(this.on("DOMContentLoaded",a),R(C).on("load",a))},toString:function(){var b=[];r(this,function(a){b.push(""+a)});return"["+b.join(", ")+"]"},eq:function(b){return 0<=b?z(this[b]):z(this[this.length+b])},length:0,push:Td,sort:[].sort,splice:[].splice},ib={};r("multiple selected checked disabled readOnly required open".split(" "),function(b){ib[O(b)]=b});var ic= +{};r("input select option textarea button form details".split(" "),function(b){ic[Ia(b)]=!0});r({data:ec,inheritedData:hb,scope:function(b){return z(b).data("$scope")||hb(b.parentNode||b,["$isolateScope","$scope"])},isolateScope:function(b){return z(b).data("$isolateScope")||z(b).data("$isolateScopeNoTemplate")},controller:fc,injector:function(b){return hb(b,"$injector")},removeAttr:function(b,a){b.removeAttribute(a)},hasClass:Fb,css:function(b,a,c){a=Ra(a);if(v(c))b.style[a]=c;else{var d;8>=P&&(d= +b.currentStyle&&b.currentStyle[a],""===d&&(d="auto"));d=d||b.style[a];8>=P&&(d=""===d?s:d);return d}},attr:function(b,a,c){var d=O(a);if(ib[d])if(v(c))c?(b[a]=!0,b.setAttribute(a,d)):(b[a]=!1,b.removeAttribute(d));else return b[a]||(b.attributes.getNamedItem(a)||w).specified?d:s;else if(v(c))b.setAttribute(a,c);else if(b.getAttribute)return b=b.getAttribute(a,2),null===b?s:b},prop:function(b,a,c){if(v(c))b[a]=c;else return b[a]},text:function(){function b(b,d){var e=a[b.nodeType];if(x(d))return e? +b[e]:"";b[e]=d}var a=[];9>P?(a[1]="innerText",a[3]="nodeValue"):a[1]=a[3]="textContent";b.$dv="";return b}(),val:function(b,a){if(x(a)){if("SELECT"===Ga(b)&&b.multiple){var c=[];r(b.options,function(a){a.selected&&c.push(a.value||a.text)});return 0===c.length?null:c}return b.value}b.value=a},html:function(b,a){if(x(a))return b.innerHTML;for(var c=0,d=b.childNodes;c":function(a,c,d,e){return d(a,c)>e(a,c)},"<=":function(a,c,d,e){return d(a,c)<=e(a,c)},">=":function(a,c,d,e){return d(a,c)>=e(a,c)},"&&":function(a,c,d,e){return d(a,c)&&e(a,c)},"||":function(a,c,d,e){return d(a,c)||e(a,c)},"&":function(a,c,d,e){return d(a, +c)&e(a,c)},"|":function(a,c,d,e){return e(a,c)(a,c,d(a,c))},"!":function(a,c,d){return!d(a,c)}},Yd={n:"\n",f:"\f",r:"\r",t:"\t",v:"\v","'":"'",'"':'"'},Mb=function(a){this.options=a};Mb.prototype={constructor:Mb,lex:function(a){this.text=a;this.index=0;this.ch=s;this.lastCh=":";this.tokens=[];var c;for(a=[];this.index=a},isWhitespace:function(a){return" "===a||"\r"===a||"\t"===a||"\n"===a||"\v"===a||"\u00a0"===a},isIdent:function(a){return"a"<=a&&"z">=a||"A"<=a&&"Z">=a||"_"===a||"$"===a},isExpOperator:function(a){return"-"===a||"+"===a||this.isNumber(a)},throwError:function(a,c,d){d=d||this.index;c=v(c)?"s "+c+"-"+this.index+" ["+this.text.substring(c,d)+"]":" "+d;throw ya("lexerr",a,c,this.text);},readNumber:function(){for(var a="",c=this.index;this.index","<=",">="))a=this.binaryFn(a,c.fn,this.relational());return a},additive:function(){for(var a=this.multiplicative(),c;c=this.expect("+","-");)a=this.binaryFn(a,c.fn,this.multiplicative());return a},multiplicative:function(){for(var a=this.unary(),c;c=this.expect("*","/","%");)a=this.binaryFn(a,c.fn,this.unary());return a},unary:function(){var a;return this.expect("+")?this.primary():(a=this.expect("-"))?this.binaryFn(Za.ZERO,a.fn, -this.unary()):(a=this.expect("!"))?this.unaryFn(a.fn,this.unary()):this.primary()},fieldAccess:function(a){var c=this,d=this.expect().text,e=xc(d,this.options,this.text);return t(function(c,d,h){return e(h||a(c,d))},{assign:function(e,f,h){return kb(a(e,h),d,f,c.text,c.options)}})},objectIndex:function(a){var c=this,d=this.expression();this.consume("]");return t(function(e,g){var f=a(e,g),h=d(e,g),m;if(!f)return r;(f=Ya(f[h],c.text))&&(f.then&&c.options.unwrapPromises)&&(m=f,"$$v"in f||(m.$$v=r,m.then(function(a){m.$$v= -a})),f=f.$$v);return f},{assign:function(e,g,f){var h=d(e,f);return Ya(a(e,f),c.text)[h]=g}})},functionCall:function(a,c){var d=[];if(")"!==this.peekToken().text){do d.push(this.expression());while(this.expect(","))}this.consume(")");var e=this;return function(g,f){for(var h=[],m=c?c(g,f):g,k=0;ka.getHours()?c.AMPMS[0]:c.AMPMS[1]},Z:function(a){a=-1*a.getTimezoneOffset();return a=(0<=a?"+":"")+(Mb(Math[0=M&&(c.href||c.name||c.$set("href",""),a.append(Q.createComment("IE fix")));if(!c.href&&!c.xlinkHref&&!c.name)return function(a,c){var g="[object SVGAnimatedString]"===Ma.call(c.prop("href"))?"xlink:href":"href";c.on("click",function(a){c.attr(g)||a.preventDefault()})}}}),Ob={};q(gb,function(a,c){if("multiple"!=a){var d=ma("ng-"+c);Ob[d]=function(){return{priority:100,link:function(a,g,f){a.$watch(f[d],function(a){f.$set(c,!!a)})}}}}});q(["src","srcset","href"],function(a){var c= -ma("ng-"+a);Ob[c]=function(){return{priority:99,link:function(d,e,g){g.$observe(c,function(c){c&&(g.$set(a,c),M&&e.prop(a,g[a]))})}}}});var ob={$addControl:w,$removeControl:w,$setValidity:w,$setDirty:w,$setPristine:w};Ic.$inject=["$element","$attrs","$scope"];var Kc=function(a){return["$timeout",function(c){return{name:"form",restrict:a?"EAC":"E",controller:Ic,compile:function(){return{pre:function(a,e,g,f){if(!g.action){var h=function(a){a.preventDefault?a.preventDefault():a.returnValue=!1};Jc(e[0], -"submit",h);e.on("$destroy",function(){c(function(){Bb(e[0],"submit",h)},0,!1)})}var m=e.parent().controller("form"),k=g.name||g.ngForm;k&&kb(a,k,f,k);if(m)e.on("$destroy",function(){m.$removeControl(f);k&&kb(a,k,r,k);t(f,ob)})}}}}}]},Yd=Kc(),Zd=Kc(!0),$d=/^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/,ae=/^[a-z0-9!#$%&'*+/=?^_`{|}~.-]+@[a-z0-9-]+(\.[a-z0-9-]+)*$/i,be=/^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/,Lc={text:qb,number:function(a,c,d,e,g,f){qb(a,c,d,e,g,f); -e.$parsers.push(function(a){var c=e.$isEmpty(a);if(c||be.test(a))return e.$setValidity("number",!0),""===a?null:c?a:parseFloat(a);e.$setValidity("number",!1);return r});e.$formatters.push(function(a){return e.$isEmpty(a)?"":""+a});d.min&&(a=function(a){var c=parseFloat(d.min);return pa(e,"min",e.$isEmpty(a)||a>=c,a)},e.$parsers.push(a),e.$formatters.push(a));d.max&&(a=function(a){var c=parseFloat(d.max);return pa(e,"max",e.$isEmpty(a)||a<=c,a)},e.$parsers.push(a),e.$formatters.push(a));e.$formatters.push(function(a){return pa(e, -"number",e.$isEmpty(a)||sb(a),a)})},url:function(a,c,d,e,g,f){qb(a,c,d,e,g,f);a=function(a){return pa(e,"url",e.$isEmpty(a)||$d.test(a),a)};e.$formatters.push(a);e.$parsers.push(a)},email:function(a,c,d,e,g,f){qb(a,c,d,e,g,f);a=function(a){return pa(e,"email",e.$isEmpty(a)||ae.test(a),a)};e.$formatters.push(a);e.$parsers.push(a)},radio:function(a,c,d,e){z(d.name)&&c.attr("name",$a());c.on("click",function(){c[0].checked&&a.$apply(function(){e.$setViewValue(d.value)})});e.$render=function(){c[0].checked= -d.value==e.$viewValue};d.$observe("value",e.$render)},checkbox:function(a,c,d,e){var g=d.ngTrueValue,f=d.ngFalseValue;D(g)||(g=!0);D(f)||(f=!1);c.on("click",function(){a.$apply(function(){e.$setViewValue(c[0].checked)})});e.$render=function(){c[0].checked=e.$viewValue};e.$isEmpty=function(a){return a!==g};e.$formatters.push(function(a){return a===g});e.$parsers.push(function(a){return a?g:f})},hidden:w,button:w,submit:w,reset:w},Mc=["$browser","$sniffer",function(a,c){return{restrict:"E",require:"?ngModel", -link:function(d,e,g,f){f&&(Lc[x(g.type)]||Lc.text)(d,e,g,f,c,a)}}}],nb="ng-valid",mb="ng-invalid",Ja="ng-pristine",pb="ng-dirty",ce=["$scope","$exceptionHandler","$attrs","$element","$parse",function(a,c,d,e,g){function f(a,c){c=c?"-"+db(c,"-"):"";e.removeClass((a?mb:nb)+c).addClass((a?nb:mb)+c)}this.$modelValue=this.$viewValue=Number.NaN;this.$parsers=[];this.$formatters=[];this.$viewChangeListeners=[];this.$pristine=!0;this.$dirty=!1;this.$valid=!0;this.$invalid=!1;this.$name=d.name;var h=g(d.ngModel), -m=h.assign;if(!m)throw F("ngModel")("nonassign",d.ngModel,ga(e));this.$render=w;this.$isEmpty=function(a){return z(a)||""===a||null===a||a!==a};var k=e.inheritedData("$formController")||ob,l=0,n=this.$error={};e.addClass(Ja);f(!0);this.$setValidity=function(a,c){n[a]!==!c&&(c?(n[a]&&l--,l||(f(!0),this.$valid=!0,this.$invalid=!1)):(f(!1),this.$invalid=!0,this.$valid=!1,l++),n[a]=!c,f(c,a),k.$setValidity(a,c,this))};this.$setPristine=function(){this.$dirty=!1;this.$pristine=!0;e.removeClass(pb).addClass(Ja)}; -this.$setViewValue=function(d){this.$viewValue=d;this.$pristine&&(this.$dirty=!0,this.$pristine=!1,e.removeClass(Ja).addClass(pb),k.$setDirty());q(this.$parsers,function(a){d=a(d)});this.$modelValue!==d&&(this.$modelValue=d,m(a,d),q(this.$viewChangeListeners,function(a){try{a()}catch(d){c(d)}}))};var p=this;a.$watch(function(){var c=h(a);if(p.$modelValue!==c){var d=p.$formatters,e=d.length;for(p.$modelValue=c;e--;)c=d[e](c);p.$viewValue!==c&&(p.$viewValue=c,p.$render())}return c})}],de=function(){return{require:["ngModel", -"^?form"],controller:ce,link:function(a,c,d,e){var g=e[0],f=e[1]||ob;f.$addControl(g);a.$on("$destroy",function(){f.$removeControl(g)})}}},ee=$({require:"ngModel",link:function(a,c,d,e){e.$viewChangeListeners.push(function(){a.$eval(d.ngChange)})}}),Nc=function(){return{require:"?ngModel",link:function(a,c,d,e){if(e){d.required=!0;var g=function(a){if(d.required&&e.$isEmpty(a))e.$setValidity("required",!1);else return e.$setValidity("required",!0),a};e.$formatters.push(g);e.$parsers.unshift(g);d.$observe("required", -function(){g(e.$viewValue)})}}}},fe=function(){return{require:"ngModel",link:function(a,c,d,e){var g=(a=/\/(.*)\//.exec(d.ngList))&&RegExp(a[1])||d.ngList||",";e.$parsers.push(function(a){if(!z(a)){var c=[];a&&q(a.split(g),function(a){a&&c.push(ba(a))});return c}});e.$formatters.push(function(a){return K(a)?a.join(", "):r});e.$isEmpty=function(a){return!a||!a.length}}}},ge=/^(true|false|\d+)$/,he=function(){return{priority:100,compile:function(a,c){return ge.test(c.ngValue)?function(a,c,g){g.$set("value", -a.$eval(g.ngValue))}:function(a,c,g){a.$watch(g.ngValue,function(a){g.$set("value",a)})}}}},ie=ta(function(a,c,d){c.addClass("ng-binding").data("$binding",d.ngBind);a.$watch(d.ngBind,function(a){c.text(a==r?"":a)})}),je=["$interpolate",function(a){return function(c,d,e){c=a(d.attr(e.$attr.ngBindTemplate));d.addClass("ng-binding").data("$binding",c);e.$observe("ngBindTemplate",function(a){d.text(a)})}}],ke=["$sce","$parse",function(a,c){return function(d,e,g){e.addClass("ng-binding").data("$binding", -g.ngBindHtml);var f=c(g.ngBindHtml);d.$watch(function(){return(f(d)||"").toString()},function(c){e.html(a.getTrustedHtml(f(d))||"")})}}],le=Nb("",!0),me=Nb("Odd",0),ne=Nb("Even",1),oe=ta({compile:function(a,c){c.$set("ngCloak",r);a.removeClass("ng-cloak")}}),pe=[function(){return{scope:!0,controller:"@",priority:500}}],Oc={};q("click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste".split(" "),function(a){var c=ma("ng-"+ -a);Oc[c]=["$parse",function(d){return{compile:function(e,g){var f=d(g[c]);return function(c,d,e){d.on(x(a),function(a){c.$apply(function(){f(c,{$event:a})})})}}}}]});var qe=["$animate",function(a){return{transclude:"element",priority:600,terminal:!0,restrict:"A",$$tlb:!0,link:function(c,d,e,g,f){var h,m;c.$watch(e.ngIf,function(g){Pa(g)?m||(m=c.$new(),f(m,function(c){c[c.length++]=Q.createComment(" end ngIf: "+e.ngIf+" ");h={clone:c};a.enter(c,d.parent(),d)})):(m&&(m.$destroy(),m=null),h&&(a.leave(wb(h.clone)), -h=null))})}}}],re=["$http","$templateCache","$anchorScroll","$animate","$sce",function(a,c,d,e,g){return{restrict:"ECA",priority:400,terminal:!0,transclude:"element",controller:Ca.noop,compile:function(f,h){var m=h.ngInclude||h.src,k=h.onload||"",l=h.autoscroll;return function(f,h,q,r,y){var A=0,u,t,H=function(){u&&(u.$destroy(),u=null);t&&(e.leave(t),t=null)};f.$watch(g.parseAsResourceUrl(m),function(g){var m=function(){!B(l)||l&&!f.$eval(l)||d()},q=++A;g?(a.get(g,{cache:c}).success(function(a){if(q=== -A){var c=f.$new();r.template=a;a=y(c,function(a){H();e.enter(a,null,h,m)});u=c;t=a;u.$emit("$includeContentLoaded");f.$eval(k)}}).error(function(){q===A&&H()}),f.$emit("$includeContentRequested")):(H(),r.template=null)})}}}}],se=["$compile",function(a){return{restrict:"ECA",priority:-400,require:"ngInclude",link:function(c,d,e,g){d.html(g.template);a(d.contents())(c)}}}],te=ta({priority:450,compile:function(){return{pre:function(a,c,d){a.$eval(d.ngInit)}}}}),ue=ta({terminal:!0,priority:1E3}),ve=["$locale", -"$interpolate",function(a,c){var d=/{}/g;return{restrict:"EA",link:function(e,g,f){var h=f.count,m=f.$attr.when&&g.attr(f.$attr.when),k=f.offset||0,l=e.$eval(m)||{},n={},p=c.startSymbol(),s=c.endSymbol(),r=/^when(Minus)?(.+)$/;q(f,function(a,c){r.test(c)&&(l[x(c.replace("when","").replace("Minus","-"))]=g.attr(f.$attr[c]))});q(l,function(a,e){n[e]=c(a.replace(d,p+h+"-"+k+s))});e.$watch(function(){var c=parseFloat(e.$eval(h));if(isNaN(c))return"";c in l||(c=a.pluralCat(c-k));return n[c](e,g,!0)},function(a){g.text(a)})}}}], -we=["$parse","$animate",function(a,c){var d=F("ngRepeat");return{transclude:"element",priority:1E3,terminal:!0,$$tlb:!0,link:function(e,g,f,h,m){var k=f.ngRepeat,l=k.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),n,p,s,r,y,t,u={$id:Fa};if(!l)throw d("iexp",k);f=l[1];h=l[2];(l=l[3])?(n=a(l),p=function(a,c,d){t&&(u[t]=a);u[y]=c;u.$index=d;return n(e,u)}):(s=function(a,c){return Fa(c)},r=function(a){return a});l=f.match(/^(?:([\$\w]+)|\(([\$\w]+)\s*,\s*([\$\w]+)\))$/);if(!l)throw d("iidexp", -f);y=l[3]||l[1];t=l[2];var B={};e.$watchCollection(h,function(a){var f,h,l=g[0],n,u={},z,P,D,x,T,w,F=[];if(rb(a))T=a,n=p||s;else{n=p||r;T=[];for(D in a)a.hasOwnProperty(D)&&"$"!=D.charAt(0)&&T.push(D);T.sort()}z=T.length;h=F.length=T.length;for(f=0;fz;)v.pop().element.remove()}for(;x.length>I;)x.pop()[0].element.remove()}var k;if(!(k=t.match(d)))throw Fe("iexp", -t,ga(f));var l=c(k[2]||k[1]),m=k[4]||k[6],n=k[5],p=c(k[3]||""),q=c(k[2]?k[1]:m),A=c(k[7]),w=k[8]?c(k[8]):null,x=[[{element:f,label:""}]];y&&(a(y)(e),y.removeClass("ng-scope"),y.remove());f.empty();f.on("change",function(){e.$apply(function(){var a,c=A(e)||[],d={},h,k,l,p,t,u,v;if(s)for(k=[],p=0,u=x.length;p@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide{display:none !important;}ng\\:form{display:block;}'); +this.unary()):(a=this.expect("!"))?this.unaryFn(a.fn,this.unary()):this.primary()},fieldAccess:function(a){var c=this,d=this.expect().text,e=yc(d,this.options,this.text);return t(function(c,d,h){return e(h||a(c,d))},{assign:function(e,g,h){return ob(a(e,h),d,g,c.text,c.options)}})},objectIndex:function(a){var c=this,d=this.expression();this.consume("]");return t(function(e,f){var g=a(e,f),h=d(e,f),n;if(!g)return s;(g=Ya(g[h],c.text))&&(g.then&&c.options.unwrapPromises)&&(n=g,"$$v"in g||(n.$$v=s,n.then(function(a){n.$$v= +a})),g=g.$$v);return g},{assign:function(e,f,g){var h=d(e,g);return Ya(a(e,g),c.text)[h]=f}})},functionCall:function(a,c){var d=[];if(")"!==this.peekToken().text){do d.push(this.expression());while(this.expect(","))}this.consume(")");var e=this;return function(f,g){for(var h=[],n=c?c(f,g):f,k=0;ka.getHours()?c.AMPMS[0]:c.AMPMS[1]},Z:function(a){a=-1*a.getTimezoneOffset();return a=(0<=a?"+":"")+(Nb(Math[0=P&&(c.href||c.name||c.$set("href",""),a.append(T.createComment("IE fix")));if(!c.href&&!c.xlinkHref&&!c.name)return function(a,c){var f="[object SVGAnimatedString]"===Ma.call(c.prop("href"))?"xlink:href":"href";c.on("click",function(a){c.attr(f)||a.preventDefault()})}}}),Pb={};r(ib,function(a,c){if("multiple"!=a){var d=la("ng-"+c);Pb[d]=function(){return{priority:100,link:function(a,f,g){a.$watch(g[d],function(a){g.$set(c,!!a)})}}}}});r(["src","srcset","href"],function(a){var c= +la("ng-"+a);Pb[c]=function(){return{priority:99,link:function(d,e,f){f.$observe(c,function(c){c&&(f.$set(a,c),P&&e.prop(a,f[a]))})}}}});var sb={$addControl:w,$removeControl:w,$setValidity:w,$setDirty:w,$setPristine:w};Jc.$inject=["$element","$attrs","$scope"];var Lc=function(a){return["$timeout",function(c){return{name:"form",restrict:a?"EAC":"E",controller:Jc,compile:function(){return{pre:function(a,e,f,g){if(!f.action){var h=function(a){a.preventDefault?a.preventDefault():a.returnValue=!1};Kc(e[0], +"submit",h);e.on("$destroy",function(){c(function(){Eb(e[0],"submit",h)},0,!1)})}var n=e.parent().controller("form"),k=f.name||f.ngForm;k&&ob(a,k,g,k);if(n)e.on("$destroy",function(){n.$removeControl(g);k&&ob(a,k,s,k);t(g,sb)})}}}}}]},$d=Lc(),ae=Lc(!0),be=/^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/,ce=/^[a-z0-9!#$%&'*+/=?^_`{|}~.-]+@[a-z0-9-]+(\.[a-z0-9-]+)*$/i,de=/^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/,Mc={text:ub,number:function(a,c,d,e,f,g){ub(a,c,d,e,f,g); +e.$parsers.push(function(a){var c=e.$isEmpty(a);if(c||de.test(a))return e.$setValidity("number",!0),""===a?null:c?a:parseFloat(a);e.$setValidity("number",!1);return s});e.$formatters.push(function(a){return e.$isEmpty(a)?"":""+a});d.min&&(a=function(a){var c=parseFloat(d.min);return na(e,"min",e.$isEmpty(a)||a>=c,a)},e.$parsers.push(a),e.$formatters.push(a));d.max&&(a=function(a){var c=parseFloat(d.max);return na(e,"max",e.$isEmpty(a)||a<=c,a)},e.$parsers.push(a),e.$formatters.push(a));e.$formatters.push(function(a){return na(e, +"number",e.$isEmpty(a)||wb(a),a)})},url:function(a,c,d,e,f,g){ub(a,c,d,e,f,g);a=function(a){return na(e,"url",e.$isEmpty(a)||be.test(a),a)};e.$formatters.push(a);e.$parsers.push(a)},email:function(a,c,d,e,f,g){ub(a,c,d,e,f,g);a=function(a){return na(e,"email",e.$isEmpty(a)||ce.test(a),a)};e.$formatters.push(a);e.$parsers.push(a)},radio:function(a,c,d,e){x(d.name)&&c.attr("name",$a());c.on("click",function(){c[0].checked&&a.$apply(function(){e.$setViewValue(d.value)})});e.$render=function(){c[0].checked= +d.value==e.$viewValue};d.$observe("value",e.$render)},checkbox:function(a,c,d,e){var f=d.ngTrueValue,g=d.ngFalseValue;D(f)||(f=!0);D(g)||(g=!1);c.on("click",function(){a.$apply(function(){e.$setViewValue(c[0].checked)})});e.$render=function(){c[0].checked=e.$viewValue};e.$isEmpty=function(a){return a!==f};e.$formatters.push(function(a){return a===f});e.$parsers.push(function(a){return a?f:g})},hidden:w,button:w,submit:w,reset:w,file:w},Nc=["$browser","$sniffer",function(a,c){return{restrict:"E",require:"?ngModel", +link:function(d,e,f,g){g&&(Mc[O(f.type)]||Mc.text)(d,e,f,g,c,a)}}}],rb="ng-valid",qb="ng-invalid",Ja="ng-pristine",tb="ng-dirty",ee=["$scope","$exceptionHandler","$attrs","$element","$parse",function(a,c,d,e,f){function g(a,c){c=c?"-"+db(c,"-"):"";e.removeClass((a?qb:rb)+c).addClass((a?rb:qb)+c)}this.$modelValue=this.$viewValue=Number.NaN;this.$parsers=[];this.$formatters=[];this.$viewChangeListeners=[];this.$pristine=!0;this.$dirty=!1;this.$valid=!0;this.$invalid=!1;this.$name=d.name;var h=f(d.ngModel), +n=h.assign;if(!n)throw E("ngModel")("nonassign",d.ngModel,ga(e));this.$render=w;this.$isEmpty=function(a){return x(a)||""===a||null===a||a!==a};var k=e.inheritedData("$formController")||sb,l=0,m=this.$error={};e.addClass(Ja);g(!0);this.$setValidity=function(a,c){m[a]!==!c&&(c?(m[a]&&l--,l||(g(!0),this.$valid=!0,this.$invalid=!1)):(g(!1),this.$invalid=!0,this.$valid=!1,l++),m[a]=!c,g(c,a),k.$setValidity(a,c,this))};this.$setPristine=function(){this.$dirty=!1;this.$pristine=!0;e.removeClass(tb).addClass(Ja)}; +this.$setViewValue=function(d){this.$viewValue=d;this.$pristine&&(this.$dirty=!0,this.$pristine=!1,e.removeClass(Ja).addClass(tb),k.$setDirty());r(this.$parsers,function(a){d=a(d)});this.$modelValue!==d&&(this.$modelValue=d,n(a,d),r(this.$viewChangeListeners,function(a){try{a()}catch(d){c(d)}}))};var p=this;a.$watch(function(){var c=h(a);if(p.$modelValue!==c){var d=p.$formatters,e=d.length;for(p.$modelValue=c;e--;)c=d[e](c);p.$viewValue!==c&&(p.$viewValue=c,p.$render())}return c})}],fe=function(){return{require:["ngModel", +"^?form"],controller:ee,link:function(a,c,d,e){var f=e[0],g=e[1]||sb;g.$addControl(f);a.$on("$destroy",function(){g.$removeControl(f)})}}},ge=aa({require:"ngModel",link:function(a,c,d,e){e.$viewChangeListeners.push(function(){a.$eval(d.ngChange)})}}),Oc=function(){return{require:"?ngModel",link:function(a,c,d,e){if(e){d.required=!0;var f=function(a){if(d.required&&e.$isEmpty(a))e.$setValidity("required",!1);else return e.$setValidity("required",!0),a};e.$formatters.push(f);e.$parsers.unshift(f);d.$observe("required", +function(){f(e.$viewValue)})}}}},he=function(){return{require:"ngModel",link:function(a,c,d,e){var f=(a=/\/(.*)\//.exec(d.ngList))&&RegExp(a[1])||d.ngList||",";e.$parsers.push(function(a){if(!x(a)){var c=[];a&&r(a.split(f),function(a){a&&c.push(da(a))});return c}});e.$formatters.push(function(a){return H(a)?a.join(", "):s});e.$isEmpty=function(a){return!a||!a.length}}}},ie=/^(true|false|\d+)$/,je=function(){return{priority:100,compile:function(a,c){return ie.test(c.ngValue)?function(a,c,f){f.$set("value", +a.$eval(f.ngValue))}:function(a,c,f){a.$watch(f.ngValue,function(a){f.$set("value",a)})}}}},ke=sa(function(a,c,d){c.addClass("ng-binding").data("$binding",d.ngBind);a.$watch(d.ngBind,function(a){c.text(a==s?"":a)})}),le=["$interpolate",function(a){return function(c,d,e){c=a(d.attr(e.$attr.ngBindTemplate));d.addClass("ng-binding").data("$binding",c);e.$observe("ngBindTemplate",function(a){d.text(a)})}}],me=["$sce","$parse",function(a,c){return function(d,e,f){e.addClass("ng-binding").data("$binding", +f.ngBindHtml);var g=c(f.ngBindHtml);d.$watch(function(){return(g(d)||"").toString()},function(c){e.html(a.getTrustedHtml(g(d))||"")})}}],ne=Ob("",!0),oe=Ob("Odd",0),pe=Ob("Even",1),qe=sa({compile:function(a,c){c.$set("ngCloak",s);a.removeClass("ng-cloak")}}),re=[function(){return{scope:!0,controller:"@",priority:500}}],Pc={};r("click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste".split(" "),function(a){var c=la("ng-"+ +a);Pc[c]=["$parse",function(d){return{compile:function(e,f){var g=d(f[c]);return function(c,d,e){d.on(O(a),function(a){c.$apply(function(){g(c,{$event:a})})})}}}}]});var se=["$animate",function(a){return{transclude:"element",priority:600,terminal:!0,restrict:"A",$$tlb:!0,link:function(c,d,e,f,g){var h,n;c.$watch(e.ngIf,function(f){Pa(f)?n||(n=c.$new(),g(n,function(c){c[c.length++]=T.createComment(" end ngIf: "+e.ngIf+" ");h={clone:c};a.enter(c,d.parent(),d)})):(n&&(n.$destroy(),n=null),h&&(a.leave(zb(h.clone)), +h=null))})}}}],te=["$http","$templateCache","$anchorScroll","$animate","$sce",function(a,c,d,e,f){return{restrict:"ECA",priority:400,terminal:!0,transclude:"element",controller:Ba.noop,compile:function(g,h){var n=h.ngInclude||h.src,k=h.onload||"",l=h.autoscroll;return function(g,h,q,r,B){var s=0,u,t,z=function(){u&&(u.$destroy(),u=null);t&&(e.leave(t),t=null)};g.$watch(f.parseAsResourceUrl(n),function(f){var n=function(){!v(l)||l&&!g.$eval(l)||d()},q=++s;f?(a.get(f,{cache:c}).success(function(a){if(q=== +s){var c=g.$new();r.template=a;a=B(c,function(a){z();e.enter(a,null,h,n)});u=c;t=a;u.$emit("$includeContentLoaded");g.$eval(k)}}).error(function(){q===s&&z()}),g.$emit("$includeContentRequested")):(z(),r.template=null)})}}}}],ue=["$compile",function(a){return{restrict:"ECA",priority:-400,require:"ngInclude",link:function(c,d,e,f){d.html(f.template);a(d.contents())(c)}}}],ve=sa({priority:450,compile:function(){return{pre:function(a,c,d){a.$eval(d.ngInit)}}}}),we=sa({terminal:!0,priority:1E3}),xe=["$locale", +"$interpolate",function(a,c){var d=/{}/g;return{restrict:"EA",link:function(e,f,g){var h=g.count,n=g.$attr.when&&f.attr(g.$attr.when),k=g.offset||0,l=e.$eval(n)||{},m={},p=c.startSymbol(),q=c.endSymbol(),s=/^when(Minus)?(.+)$/;r(g,function(a,c){s.test(c)&&(l[O(c.replace("when","").replace("Minus","-"))]=f.attr(g.$attr[c]))});r(l,function(a,e){m[e]=c(a.replace(d,p+h+"-"+k+q))});e.$watch(function(){var c=parseFloat(e.$eval(h));if(isNaN(c))return"";c in l||(c=a.pluralCat(c-k));return m[c](e,f,!0)},function(a){f.text(a)})}}}], +ye=["$parse","$animate",function(a,c){var d=E("ngRepeat");return{transclude:"element",priority:1E3,terminal:!0,$$tlb:!0,link:function(e,f,g,h,n){var k=g.ngRepeat,l=k.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),m,p,q,s,t,v,u={$id:Ea};if(!l)throw d("iexp",k);g=l[1];h=l[2];(l=l[3])?(m=a(l),p=function(a,c,d){v&&(u[v]=a);u[t]=c;u.$index=d;return m(e,u)}):(q=function(a,c){return Ea(c)},s=function(a){return a});l=g.match(/^(?:([\$\w]+)|\(([\$\w]+)\s*,\s*([\$\w]+)\))$/);if(!l)throw d("iidexp", +g);t=l[3]||l[1];v=l[2];var G={};e.$watchCollection(h,function(a){var g,h,l=f[0],m,u={},D,M,w,x,E,J,H=[];if(vb(a))E=a,m=p||q;else{m=p||s;E=[];for(w in a)a.hasOwnProperty(w)&&"$"!=w.charAt(0)&&E.push(w);E.sort()}D=E.length;h=H.length=E.length;for(g=0;gC;)x.pop().element.remove()}for(;y.length>X;)y.pop()[0].element.remove()}var k;if(!(k=t.match(d)))throw He("iexp",t,ga(f));var l=c(k[2]||k[1]),m=k[4]||k[6],n=k[5],p=c(k[3]||""),r=c(k[2]?k[1]:m),z=c(k[7]), +w=k[8]?c(k[8]):null,y=[[{element:f,label:""}]];B&&(a(B)(e),B.removeClass("ng-scope"),B.remove());f.empty();f.on("change",function(){e.$apply(function(){var a,c=z(e)||[],d={},h,k,l,p,t,v,u;if(q)for(k=[],p=0,v=y.length;p@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide{display:none !important;}ng\\:form{display:block;}.ng-animate-block-transitions{transition:0s all!important;-webkit-transition:0s all!important;}'); //# sourceMappingURL=angular.min.js.map diff --git a/config/lib/js/angular/errors.json b/config/lib/js/angular/errors.json index 7b4c923e105..3b12188f81d 100755 --- a/config/lib/js/angular/errors.json +++ b/config/lib/js/angular/errors.json @@ -1 +1 @@ -{"id":"ng","generated":"Fri Jan 24 2014 15:29:18 GMT-0800 (PST)","errors":{"$cacheFactory":{"iid":"CacheId '{0}' is already taken!"},"ngModel":{"nonassign":"Expression '{0}' is non-assignable. Element: {1}"},"$sce":{"iequirks":"Strict Contextual Escaping does not support Internet Explorer version < 9 in quirks mode. You can fix this by adding the text to the top of your HTML document. See http://docs.angularjs.org/api/ng.$sce for more information.","insecurl":"Blocked loading resource from url not allowed by $sceDelegate policy. URL: {0}","icontext":"Attempted to trust a value in invalid context. Context: {0}; Value: {1}","imatcher":"Matchers may only be \"self\", string patterns or RegExp objects","iwcard":"Illegal sequence *** in string matcher. String: {0}","itype":"Attempted to trust a non-string value in a content requiring a string: Context: {0}","unsafe":"Attempting to use an unsafe value in a safe context."},"$controller":{"noscp":"Cannot export controller '{0}' as '{1}'! No $scope object provided via `locals`."},"$compile":{"nodomevents":"Interpolations for HTML DOM event attributes are disallowed. Please use the ng- versions (such as ng-click instead of onclick) instead.","multidir":"Multiple directives [{0}, {1}] asking for {2} on: {3}","nonassign":"Expression '{0}' used with directive '{1}' is non-assignable!","tplrt":"Template for directive '{0}' must have exactly one root element. {1}","selmulti":"Binding to the 'multiple' attribute is not supported. Element: {0}","tpload":"Failed to load template: {0}","iscp":"Invalid isolate scope definition for directive '{0}'. Definition: {... {1}: '{2}' ...}","ctreq":"Controller '{0}', required by directive '{1}', can't be found!","uterdir":"Unterminated attribute, found '{0}' but no matching '{1}' found."},"$injector":{"modulerr":"Failed to instantiate module {0} due to:\n{1}","unpr":"Unknown provider: {0}","itkn":"Incorrect injection token! Expected service name as string, got {0}","cdep":"Circular dependency found: {0}","nomod":"Module '{0}' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.","pget":"Provider '{0}' must define $get factory method."},"ngPattern":{"noregexp":"Expected {0} to be a RegExp but was {1}. Element: {2}"},"$rootScope":{"inprog":"{0} already in progress","infdig":"{0} $digest() iterations reached. Aborting!\nWatchers fired in the last 5 iterations: {1}"},"$interpolate":{"noconcat":"Error while interpolating: {0}\nStrict Contextual Escaping disallows interpolations that concatenate multiple expressions when a trusted value is required. See http://docs.angularjs.org/api/ng.$sce","interr":"Can't interpolate: {0}\n{1}"},"jqLite":{"offargs":"jqLite#off() does not support the `selector` argument","onargs":"jqLite#on() does not support the `selector` or `eventData` parameters","nosel":"Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element"},"ngOptions":{"iexp":"Expected expression in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_' but got '{0}'. Element: {1}"},"ngRepeat":{"iidexp":"'_item_' in '_item_ in _collection_' should be an identifier or '(_key_, _value_)' expression, but got '{0}'.","dupes":"Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}","iexp":"Expected expression in form of '_item_ in _collection_[ track by _id_]' but got '{0}'."},"ng":{"areq":"Argument '{0}' is {1}","cpws":"Can't copy! Making copies of Window or Scope instances is not supported.","badname":"hasOwnProperty is not a valid {0} name","btstrpd":"App Already Bootstrapped with this Element '{0}'","cpi":"Can't copy! Source and destination are identical."},"$animate":{"notcsel":"Expecting class selector starting with '.' got '{0}'."},"ngTransclude":{"orphan":"Illegal use of ngTransclude directive in the template! No parent directive that requires a transclusion found. Element: {0}"},"$parse":{"isecfld":"Referencing \"constructor\" field in Angular expressions is disallowed! Expression: {0}","syntax":"Syntax Error: Token '{0}' {1} at column {2} of the expression [{3}] starting at [{4}].","isecdom":"Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}","lexerr":"Lexer Error: {0} at column{1} in expression [{2}].","ueoe":"Unexpected end of expression: {0}","isecwindow":"Referencing the Window in Angular expressions is disallowed! Expression: {0}","isecfn":"Referencing Function in Angular expressions is disallowed! Expression: {0}"},"$location":{"ipthprfx":"Invalid url \"{0}\", missing path prefix \"{1}\".","isrcharg":"The first argument of the `$location#search()` call must be a string or an object.","ihshprfx":"Invalid url \"{0}\", missing hash prefix \"{1}\"."},"$resource":{"badargs":"Expected up to 4 arguments [params, data, success, error], got {0} arguments","badmember":"Dotted member path \"@{0}\" is invalid.","badcfg":"Error in resource configuration. Expected response to contain an {0} but got an {1}","badname":"hasOwnProperty is not a valid parameter name."},"$sanitize":{"badparse":"The sanitizer was unable to parse the following block of html: {0}"}}} +{"id":"ng","generated":"Fri Feb 14 2014 17:02:34 GMT-0800 (PST)","errors":{"$cacheFactory":{"iid":"CacheId '{0}' is already taken!"},"ngModel":{"nonassign":"Expression '{0}' is non-assignable. Element: {1}"},"$sce":{"iequirks":"Strict Contextual Escaping does not support Internet Explorer version < 9 in quirks mode. You can fix this by adding the text to the top of your HTML document. See http://docs.angularjs.org/api/ng.$sce for more information.","insecurl":"Blocked loading resource from url not allowed by $sceDelegate policy. URL: {0}","icontext":"Attempted to trust a value in invalid context. Context: {0}; Value: {1}","imatcher":"Matchers may only be \"self\", string patterns or RegExp objects","iwcard":"Illegal sequence *** in string matcher. String: {0}","itype":"Attempted to trust a non-string value in a content requiring a string: Context: {0}","unsafe":"Attempting to use an unsafe value in a safe context."},"$controller":{"noscp":"Cannot export controller '{0}' as '{1}'! No $scope object provided via `locals`."},"$compile":{"nodomevents":"Interpolations for HTML DOM event attributes are disallowed. Please use the ng- versions (such as ng-click instead of onclick) instead.","multidir":"Multiple directives [{0}, {1}] asking for {2} on: {3}","nonassign":"Expression '{0}' used with directive '{1}' is non-assignable!","tplrt":"Template for directive '{0}' must have exactly one root element. {1}","selmulti":"Binding to the 'multiple' attribute is not supported. Element: {0}","tpload":"Failed to load template: {0}","iscp":"Invalid isolate scope definition for directive '{0}'. Definition: {... {1}: '{2}' ...}","ctreq":"Controller '{0}', required by directive '{1}', can't be found!","uterdir":"Unterminated attribute, found '{0}' but no matching '{1}' found."},"$injector":{"modulerr":"Failed to instantiate module {0} due to:\n{1}","unpr":"Unknown provider: {0}","itkn":"Incorrect injection token! Expected service name as string, got {0}","cdep":"Circular dependency found: {0}","nomod":"Module '{0}' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.","pget":"Provider '{0}' must define $get factory method."},"$rootScope":{"inprog":"{0} already in progress","infdig":"{0} $digest() iterations reached. Aborting!\nWatchers fired in the last 5 iterations: {1}"},"ngPattern":{"noregexp":"Expected {0} to be a RegExp but was {1}. Element: {2}"},"$interpolate":{"noconcat":"Error while interpolating: {0}\nStrict Contextual Escaping disallows interpolations that concatenate multiple expressions when a trusted value is required. See http://docs.angularjs.org/api/ng.$sce","interr":"Can't interpolate: {0}\n{1}"},"jqLite":{"offargs":"jqLite#off() does not support the `selector` argument","onargs":"jqLite#on() does not support the `selector` or `eventData` parameters","nosel":"Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element"},"ngOptions":{"iexp":"Expected expression in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_' but got '{0}'. Element: {1}"},"ngRepeat":{"iidexp":"'_item_' in '_item_ in _collection_' should be an identifier or '(_key_, _value_)' expression, but got '{0}'.","dupes":"Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}","iexp":"Expected expression in form of '_item_ in _collection_[ track by _id_]' but got '{0}'."},"ng":{"areq":"Argument '{0}' is {1}","cpws":"Can't copy! Making copies of Window or Scope instances is not supported.","badname":"hasOwnProperty is not a valid {0} name","btstrpd":"App Already Bootstrapped with this Element '{0}'","cpi":"Can't copy! Source and destination are identical."},"$animate":{"notcsel":"Expecting class selector starting with '.' got '{0}'."},"ngTransclude":{"orphan":"Illegal use of ngTransclude directive in the template! No parent directive that requires a transclusion found. Element: {0}"},"$parse":{"isecfld":"Referencing \"constructor\" field in Angular expressions is disallowed! Expression: {0}","syntax":"Syntax Error: Token '{0}' {1} at column {2} of the expression [{3}] starting at [{4}].","isecdom":"Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}","lexerr":"Lexer Error: {0} at column{1} in expression [{2}].","ueoe":"Unexpected end of expression: {0}","isecwindow":"Referencing the Window in Angular expressions is disallowed! Expression: {0}","isecfn":"Referencing Function in Angular expressions is disallowed! Expression: {0}"},"$httpBackend":{"noxhr":"This browser does not support XMLHttpRequest."},"$location":{"ipthprfx":"Invalid url \"{0}\", missing path prefix \"{1}\".","isrcharg":"The first argument of the `$location#search()` call must be a string or an object.","ihshprfx":"Invalid url \"{0}\", missing hash prefix \"{1}\"."},"$resource":{"badargs":"Expected up to 4 arguments [params, data, success, error], got {0} arguments","badmember":"Dotted member path \"@{0}\" is invalid.","badcfg":"Error in resource configuration. Expected response to contain an {0} but got an {1}","badname":"hasOwnProperty is not a valid parameter name."},"$sanitize":{"badparse":"The sanitizer was unable to parse the following block of html: {0}"}}} \ No newline at end of file diff --git a/js/ext/angular/test/service/ionicActionSheet.unit.js b/js/ext/angular/test/service/ionicActionSheet.unit.js index cd14608d2a5..4e7578d1652 100644 --- a/js/ext/angular/test/service/ionicActionSheet.unit.js +++ b/js/ext/angular/test/service/ionicActionSheet.unit.js @@ -19,8 +19,6 @@ describe('Ionic ActionSheet Service', function() { ionic.Platform.isReady = true; var s = sheet.show(); - timeout.flush(); - ionic.trigger('backbutton', { target: document });