Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

update angular to 1.0.5

  • Loading branch information...
commit 07ffa8ced4ab1eee63c41257e07c51362867ef3c 1 parent e9f4115
@IgorMinar IgorMinar authored
View
14 app/lib/angular/angular-cookies.js
@@ -1,5 +1,5 @@
/**
- * @license AngularJS v1.0.4
+ * @license AngularJS v1.0.5
* (c) 2010-2012 Google, Inc. http://angularjs.org
* License: MIT
*/
@@ -25,6 +25,18 @@ angular.module('ngCookies', ['ng']).
* this object, new cookies are created/deleted at the end of current $eval.
*
* @example
+ <doc:example>
+ <doc:source>
+ <script>
+ function ExampleController($cookies) {
+ // Retrieving a cookie
+ var favoriteCookie = $cookies.myFavorite;
+ // Setting a cookie
+ $cookies.myFavorite = 'oatmeal';
+ }
+ </script>
+ </doc:source>
+ </doc:example>
*/
factory('$cookies', ['$rootScope', '$browser', function ($rootScope, $browser) {
var cookies = {},
View
2  app/lib/angular/angular-cookies.min.js
@@ -1,5 +1,5 @@
/*
- AngularJS v1.0.4
+ AngularJS v1.0.5
(c) 2010-2012 Google, Inc. http://angularjs.org
License: MIT
*/
View
2  app/lib/angular/angular-loader.js
@@ -1,5 +1,5 @@
/**
- * @license AngularJS v1.0.4
+ * @license AngularJS v1.0.5
* (c) 2010-2012 Google, Inc. http://angularjs.org
* License: MIT
*/
View
2  app/lib/angular/angular-loader.min.js
@@ -1,5 +1,5 @@
/*
- AngularJS v1.0.4
+ AngularJS v1.0.5
(c) 2010-2012 Google, Inc. http://angularjs.org
License: MIT
*/
View
16 app/lib/angular/angular-resource.js
@@ -1,5 +1,5 @@
/**
- * @license AngularJS v1.0.4
+ * @license AngularJS v1.0.5
* (c) 2010-2012 Google, Inc. http://angularjs.org
* License: MIT
*/
@@ -69,9 +69,9 @@
*
* Calling these methods invoke an {@link ng.$http} with the specified http method,
* destination and parameters. When the data is returned from the server then the object is an
- * instance of the resource class `save`, `remove` and `delete` actions are available on it as
- * methods with the `$` prefix. This allows you to easily perform CRUD operations (create, read,
- * update, delete) on server-side data like this:
+ * instance of the resource class. The actions `save`, `remove` and `delete` are available on it
+ * as methods with the `$` prefix. This allows you to easily perform CRUD operations (create,
+ * read, update, delete) on server-side data like this:
* <pre>
var User = $resource('/user/:userId', {userId:'@id'});
var user = User.get({userId:123}, function() {
@@ -151,9 +151,9 @@
});
</pre>
*
- * It's worth noting that the success callback for `get`, `query` and other method gets passed
- * in the response that came from the server as well as $http header getter function, so one
- * could rewrite the above example and get access to http headers as:
+ * It's worth noting that the success callback for `get`, `query` and other method gets passed
+ * in the response that came from the server as well as $http header getter function, so one
+ * could rewrite the above example and get access to http headers as:
*
<pre>
var User = $resource('/user/:userId', {userId:'@id'});
@@ -276,7 +276,7 @@ angular.module('ngResource', ['ng']).
this.defaults = defaults || {};
var urlParams = this.urlParams = {};
forEach(template.split(/\W/), function(param){
- if (param && template.match(new RegExp("[^\\\\]:" + param + "\\W"))) {
+ if (param && (new RegExp("(^|[^\\\\]):" + param + "\\W").test(template))) {
urlParams[param] = true;
}
});
View
4 app/lib/angular/angular-resource.min.js
@@ -1,9 +1,9 @@
/*
- AngularJS v1.0.4
+ AngularJS v1.0.5
(c) 2010-2012 Google, Inc. http://angularjs.org
License: MIT
*/
-(function(C,d,w){'use strict';d.module("ngResource",["ng"]).factory("$resource",["$http","$parse",function(x,y){function s(b,e){return encodeURIComponent(b).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(e?null:/%20/g,"+")}function t(b,e){this.template=b+="#";this.defaults=e||{};var a=this.urlParams={};h(b.split(/\W/),function(f){f&&b.match(RegExp("[^\\\\]:"+f+"\\W"))&&(a[f]=!0)});this.template=b.replace(/\\:/g,":")}function u(b,e,a){function f(m,a){var b=
+(function(C,d,w){'use strict';d.module("ngResource",["ng"]).factory("$resource",["$http","$parse",function(x,y){function s(b,e){return encodeURIComponent(b).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(e?null:/%20/g,"+")}function t(b,e){this.template=b+="#";this.defaults=e||{};var a=this.urlParams={};h(b.split(/\W/),function(f){f&&RegExp("(^|[^\\\\]):"+f+"\\W").test(b)&&(a[f]=!0)});this.template=b.replace(/\\:/g,":")}function u(b,e,a){function f(m,a){var b=
{},a=o({},e,a);h(a,function(a,z){var c;a.charAt&&a.charAt(0)=="@"?(c=a.substr(1),c=y(c)(m)):c=a;b[z]=c});return b}function g(a){v(a||{},this)}var k=new t(b),a=o({},A,a);h(a,function(a,b){a.method=d.uppercase(a.method);var e=a.method=="POST"||a.method=="PUT"||a.method=="PATCH";g[b]=function(b,c,d,B){var j={},i,l=p,q=null;switch(arguments.length){case 4:q=B,l=d;case 3:case 2:if(r(c)){if(r(b)){l=b;q=c;break}l=c;q=d}else{j=b;i=c;l=d;break}case 1:r(b)?l=b:e?i=b:j=b;break;case 0:break;default:throw"Expected between 0-4 arguments [params, data, success, error], got "+
arguments.length+" arguments.";}var n=this instanceof g?this:a.isArray?[]:new g(i);x({method:a.method,url:k.url(o({},f(i,a.params||{}),j)),data:i}).then(function(b){var c=b.data;if(c)a.isArray?(n.length=0,h(c,function(a){n.push(new g(a))})):v(c,n);(l||p)(n,b.headers)},q);return n};g.prototype["$"+b]=function(a,d,h){var m=f(this),j=p,i;switch(arguments.length){case 3:m=a;j=d;i=h;break;case 2:case 1:r(a)?(j=a,i=d):(m=a,j=d||p);case 0:break;default:throw"Expected between 1-3 arguments [params, success, error], got "+
arguments.length+" arguments.";}g[b].call(this,m,e?this:w,j,i)}});g.bind=function(d){return u(b,o({},e,d),a)};return g}var A={get:{method:"GET"},save:{method:"POST"},query:{method:"GET",isArray:!0},remove:{method:"DELETE"},"delete":{method:"DELETE"}},p=d.noop,h=d.forEach,o=d.extend,v=d.copy,r=d.isFunction;t.prototype={url:function(b){var e=this,a=this.template,f,g,b=b||{};h(this.urlParams,function(h,c){f=b.hasOwnProperty(c)?b[c]:e.defaults[c];d.isDefined(f)&&f!==null?(g=s(f,!0).replace(/%26/gi,"&").replace(/%3D/gi,
View
2  app/lib/angular/angular-sanitize.js
@@ -1,5 +1,5 @@
/**
- * @license AngularJS v1.0.4
+ * @license AngularJS v1.0.5
* (c) 2010-2012 Google, Inc. http://angularjs.org
* License: MIT
*/
View
2  app/lib/angular/angular-sanitize.min.js
@@ -1,5 +1,5 @@
/*
- AngularJS v1.0.4
+ AngularJS v1.0.5
(c) 2010-2012 Google, Inc. http://angularjs.org
License: MIT
*/
View
257 app/lib/angular/angular.js
@@ -1,5 +1,5 @@
/**
- * @license AngularJS v1.0.4
+ * @license AngularJS v1.0.5
* (c) 2010-2012 Google, Inc. http://angularjs.org
* License: MIT
*/
@@ -55,8 +55,7 @@ if ('i' !== 'I'.toLowerCase()) {
function fromCharCode(code) {return String.fromCharCode(code);}
-var Error = window.Error,
- /** holds major version number for IE or NaN for real browsers */
+var /** holds major version number for IE or NaN for real browsers */
msie = int((/msie (\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),
jqLite, // delay binding since jQuery could be loaded after us.
jQuery, // delay binding
@@ -97,6 +96,30 @@ var Error = window.Error,
* @param {Object=} context Object to become context (`this`) for the iterator function.
* @returns {Object|Array} Reference to `obj`.
*/
+
+
+/**
+ * @private
+ * @param {*} obj
+ * @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments, ...)
+ */
+function isArrayLike(obj) {
+ if (!obj || (typeof obj.length !== 'number')) return false;
+
+ // We have on object which has length property. Should we treat it as array?
+ if (typeof obj.hasOwnProperty != 'function' &&
+ typeof obj.constructor != 'function') {
+ // This is here for IE8: it is a bogus object treat it as array;
+ return true;
+ } else {
+ return obj instanceof JQLite || // JQLite
+ (jQuery && obj instanceof jQuery) || // jQuery
+ toString.call(obj) !== '[object Object]' || // some browser native object
+ typeof obj.callee === 'function'; // arguments (on IE8 looks like regular obj)
+ }
+}
+
+
function forEach(obj, iterator, context) {
var key;
if (obj) {
@@ -108,7 +131,7 @@ function forEach(obj, iterator, context) {
}
} else if (obj.forEach && obj.forEach !== forEach) {
obj.forEach(iterator, context);
- } else if (isObject(obj) && isNumber(obj.length)) {
+ } else if (isArrayLike(obj)) {
for (key = 0; key < obj.length; key++)
iterator.call(context, obj[key], key);
} else {
@@ -153,7 +176,7 @@ function reverseParams(iteratorFn) {
/**
* A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric
* characters such as '012ABC'. The reason why we are not using simply a number counter is that
- * the number string gets longer over time, and it can also overflow, where as the the nextId
+ * the number string gets longer over time, and it can also overflow, where as the nextId
* will grow much slower, it is a string, and it will never overflow.
*
* @returns an unique alpha-numeric string
@@ -549,9 +572,7 @@ function copy(source, destination){
} else {
if (source === destination) throw Error("Can't copy equivalent objects or arrays");
if (isArray(source)) {
- while(destination.length) {
- destination.pop();
- }
+ destination.length = 0;
for ( var i = 0; i < source.length; i++) {
destination.push(copy(source[i]));
}
@@ -762,9 +783,18 @@ function startingTag(element) {
// are not allowed to have children. So we just ignore it.
element.html('');
} catch(e) {}
- return jqLite('<div>').append(element).html().
- match(/^(<[^>]+>)/)[1].
- replace(/^<([\w\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });
+ // As Per DOM Standards
+ var TEXT_NODE = 3;
+ var elemHtml = jqLite('<div>').append(element).html();
+ try {
+ return element[0].nodeType === TEXT_NODE ? lowercase(elemHtml) :
+ elemHtml.
+ match(/^(<[^>]+>)/)[1].
+ replace(/^<([\w\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });
+ } catch(e) {
+ return lowercase(elemHtml);
+ }
+
}
@@ -848,7 +878,7 @@ function encodeUriQuery(val, pctEncodeSpaces) {
* Use this directive to auto-bootstrap on application. Only
* one directive can be used per HTML document. The directive
* designates the root of the application and is typically placed
- * ot the root of the page.
+ * at the root of the page.
*
* In the example below if the `ngApp` directive would not be placed
* on the `html` element then the document would not be compiled
@@ -1249,11 +1279,11 @@ function setupModuleLoader(window) {
* - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
*/
var version = {
- full: '1.0.4', // all of these placeholder strings will be replaced by rake's
+ full: '1.0.5', // all of these placeholder strings will be replaced by rake's
major: 1, // compile task
minor: 0,
- dot: 4,
- codeName: 'bewildering-hair'
+ dot: 5,
+ codeName: 'flatulent-propulsion'
};
@@ -2430,7 +2460,7 @@ function annotate(fn) {
* This method does not work with code minfication / obfuscation. For this reason the following annotation strategies
* are supported.
*
- * # The `$injector` property
+ * # The `$inject` property
*
* If a function has an `$inject` property and its value is an array of strings, then the strings represent names of
* services to be injected into the function.
@@ -3144,7 +3174,7 @@ function Browser(window, document, $log, $sniffer) {
*/
self.baseHref = function() {
var href = baseElement.attr('href');
- return href ? href.replace(/^https?\:\/\/[^\/]*/, '') : href;
+ return href ? href.replace(/^https?\:\/\/[^\/]*/, '') : '';
};
//////////////////////////////////////////////////////////////
@@ -3594,7 +3624,8 @@ function $CompileProvider($provide) {
Suffix = 'Directive',
COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\d\w\-_]+)\s+(.*)$/,
CLASS_DIRECTIVE_REGEXP = /(([\d\w\-_]+)(?:\:([^;]+))?;?)/,
- MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';
+ MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ',
+ urlSanitizationWhitelist = /^\s*(https?|ftp|mailto):/;
/**
@@ -3648,11 +3679,41 @@ function $CompileProvider($provide) {
};
+ /**
+ * @ngdoc function
+ * @name ng.$compileProvider#urlSanitizationWhitelist
+ * @methodOf ng.$compileProvider
+ * @function
+ *
+ * @description
+ * Retrieves or overrides the default regular expression that is used for whitelisting of safe
+ * urls during a[href] sanitization.
+ *
+ * The sanitization is a security measure aimed at prevent XSS attacks via html links.
+ *
+ * Any url about to be assigned to a[href] via data-binding is first normalized and turned into an
+ * absolute url. Afterwards the url is matched against the `urlSanitizationWhitelist` regular
+ * expression. If a match is found the original url is written into the dom. Otherwise the
+ * absolute url is prefixed with `'unsafe:'` string and only then it is written into the DOM.
+ *
+ * @param {RegExp=} regexp New regexp to whitelist urls with.
+ * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
+ * chaining otherwise.
+ */
+ this.urlSanitizationWhitelist = function(regexp) {
+ if (isDefined(regexp)) {
+ urlSanitizationWhitelist = regexp;
+ return this;
+ }
+ return urlSanitizationWhitelist;
+ };
+
+
this.$get = [
'$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',
- '$controller', '$rootScope',
+ '$controller', '$rootScope', '$document',
function($injector, $interpolate, $exceptionHandler, $http, $templateCache, $parse,
- $controller, $rootScope) {
+ $controller, $rootScope, $document) {
var Attributes = function(element, attr) {
this.$$element = element;
@@ -3674,7 +3735,8 @@ function $CompileProvider($provide) {
*/
$set: function(key, value, writeAttr, attrName) {
var booleanKey = getBooleanAttrName(this.$$element[0], key),
- $$observers = this.$$observers;
+ $$observers = this.$$observers,
+ normalizedVal;
if (booleanKey) {
this.$$element.prop(key, value);
@@ -3693,6 +3755,19 @@ function $CompileProvider($provide) {
}
}
+
+ // sanitize a[href] values
+ if (nodeName_(this.$$element[0]) === 'A' && key === 'href') {
+ urlSanitizationNode.setAttribute('href', value);
+
+ // href property always returns normalized absolute url, so we can match against that
+ normalizedVal = urlSanitizationNode.href;
+ if (!normalizedVal.match(urlSanitizationWhitelist)) {
+ this[key] = value = 'unsafe:' + normalizedVal;
+ }
+ }
+
+
if (writeAttr !== false) {
if (value === null || value === undefined) {
this.$$element.removeAttr(attrName);
@@ -3736,7 +3811,8 @@ function $CompileProvider($provide) {
}
};
- var startSymbol = $interpolate.startSymbol(),
+ var urlSanitizationNode = $document[0].createElement('a'),
+ startSymbol = $interpolate.startSymbol(),
endSymbol = $interpolate.endSymbol(),
denormalizeTemplate = (startSymbol == '{{' || endSymbol == '}}')
? identity
@@ -3769,7 +3845,14 @@ function $CompileProvider($provide) {
var $linkNode = cloneConnectFn
? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!
: $compileNodes;
- $linkNode.data('$scope', scope);
+
+ // Attach scope only to non-text nodes.
+ for(var i = 0, ii = $linkNode.length; i<ii; i++) {
+ var node = $linkNode[i];
+ if (node.nodeType == 1 /* element */ || node.nodeType == 9 /* document */) {
+ $linkNode.eq(i).data('$scope', scope);
+ }
+ }
safeAddClass($linkNode, 'ng-scope');
if (cloneConnectFn) cloneConnectFn($linkNode, scope);
if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);
@@ -3859,6 +3942,7 @@ function $CompileProvider($provide) {
(function(transcludeFn) {
return function(cloneFn) {
var transcludeScope = scope.$new();
+ transcludeScope.$$transcluded = true;
return transcludeFn(transcludeScope, cloneFn).
bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));
@@ -4164,6 +4248,8 @@ function $CompileProvider($provide) {
lastValue,
parentGet, parentSet;
+ scope.$$isolateBindings[scopeName] = mode + attrName;
+
switch (mode) {
case '@': {
@@ -4374,7 +4460,7 @@ function $CompileProvider($provide) {
}
directives.unshift(derivedSyncDirective);
- afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);
+ afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs, childTranscludeFn);
afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);
@@ -4454,10 +4540,10 @@ function $CompileProvider($provide) {
function addAttrInterpolateDirective(node, directives, value, name) {
var interpolateFn = $interpolate(value, true);
-
// no interpolation found -> ignore
if (!interpolateFn) return;
+
directives.push({
priority: 100,
compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {
@@ -6451,9 +6537,10 @@ function getterFn(path, csp) {
* @param {string} expression String expression to compile.
* @returns {function(context, locals)} a function which represents the compiled expression:
*
- * * `context`: an object against which any expressions embedded in the strings are evaluated
- * against (Topically a scope object).
- * * `locals`: local variables context object, useful for overriding values in `context`.
+ * * `context` – `{object}` – an object against which any expressions embedded in the strings
+ * are evaluated against (tipically a scope object).
+ * * `locals` – `{object=}` – local variables context object, useful for overriding values in
+ * `context`.
*
* The return function also has an `assign` property, if the expression is assignable, which
* allows one to set values to expressions.
@@ -6489,7 +6576,7 @@ function $ParseProvider() {
* interface for interacting with an object that represents the result of an action that is
* performed asynchronously, and may or may not be finished at any given point in time.
*
- * From the perspective of dealing with error handling, deferred and promise apis are to
+ * From the perspective of dealing with error handling, deferred and promise APIs are to
* asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.
*
* <pre>
@@ -6524,7 +6611,7 @@ function $ParseProvider() {
*
* At first it might not be obvious why this extra complexity is worth the trouble. The payoff
* comes in the way of
- * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).
+ * [guarantees that promise and deferred APIs make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).
*
* Additionally the promise api allows for composition that is very hard to do with the
* traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.
@@ -6536,7 +6623,7 @@ function $ParseProvider() {
*
* A new instance of deferred is constructed by calling `$q.defer()`.
*
- * The purpose of the deferred object is to expose the associated Promise instance as well as apis
+ * The purpose of the deferred object is to expose the associated Promise instance as well as APIs
* that can be used for signaling the successful or unsuccessful completion of the task.
*
* **Methods**
@@ -6579,7 +6666,7 @@ function $ParseProvider() {
* return result + 1;
* });
*
- * // promiseB will be resolved immediately after promiseA is resolved and it's value will be
+ * // promiseB will be resolved immediately after promiseA is resolved and its value will be
* // the result of promiseA incremented by 1
* </pre>
*
@@ -6604,7 +6691,7 @@ function $ParseProvider() {
* # Testing
*
* <pre>
- * it('should simulate promise', inject(function($q, $rootSCope) {
+ * it('should simulate promise', inject(function($q, $rootScope) {
* var deferred = $q.defer();
* var promise = deferred.promise;
* var resolvedValue;
@@ -6613,7 +6700,7 @@ function $ParseProvider() {
* expect(resolvedValue).toBeUndefined();
*
* // Simulate resolving of promise
- * defered.resolve(123);
+ * deferred.resolve(123);
* // Note that the 'then' function does not get called synchronously.
* // This is because we want the promise API to always be async, whether or not
* // it got called synchronously or asynchronously.
@@ -6789,12 +6876,12 @@ function qFactory(nextTick, exceptionHandler) {
* @methodOf ng.$q
* @description
* Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.
- * This is useful when you are dealing with on object that might or might not be a promise, or if
+ * This is useful when you are dealing with an object that might or might not be a promise, or if
* the promise comes from a source that can't be trusted.
*
* @param {*} value Value or a promise
* @returns {Promise} Returns a single promise that will be resolved with an array of values,
- * each value coresponding to the promise at the same index in the `promises` array. If any of
+ * each value corresponding to the promise at the same index in the `promises` array. If any of
* the promises is resolved with a rejection, this resulting promise will be resolved with the
* same rejection.
*/
@@ -6856,7 +6943,7 @@ function qFactory(nextTick, exceptionHandler) {
*
* @param {Array.<Promise>} promises An array of promises.
* @returns {Promise} Returns a single promise that will be resolved with an array of values,
- * each value coresponding to the promise at the same index in the `promises` array. If any of
+ * each value corresponding to the promise at the same index in the `promises` array. If any of
* the promises is resolved with a rejection, this resulting promise will be resolved with the
* same rejection.
*/
@@ -7525,6 +7612,7 @@ function $RootScopeProvider(){
this.$$destroyed = false;
this.$$asyncQueue = [];
this.$$listeners = {};
+ this.$$isolateBindings = {};
}
/**
@@ -8006,10 +8094,6 @@ function $RootScopeProvider(){
* Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of
* event life cycle.
*
- * @param {string} name Event name to listen on.
- * @param {function(event)} listener Function to call when the event is emitted.
- * @returns {function()} Returns a deregistration function for this listener.
- *
* The event listener function format is: `function(event, args...)`. The `event` object
* passed into the listener has the following attributes:
*
@@ -8020,6 +8104,10 @@ function $RootScopeProvider(){
* propagation (available only for events that were `$emit`-ed).
* - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.
* - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.
+ *
+ * @param {string} name Event name to listen on.
+ * @param {function(event, args...)} listener Function to call when the event is emitted.
+ * @returns {function()} Returns a deregistration function for this listener.
*/
$on: function(name, listener) {
var namedListeners = this.$$listeners[name];
@@ -8197,7 +8285,7 @@ function $RootScopeProvider(){
/**
* function used as an initial value for watchers.
- * because it's uniqueue we can easily tell it apart from other values
+ * because it's unique we can easily tell it apart from other values
*/
function initWatchVal() {}
}];
@@ -9108,8 +9196,30 @@ function createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument,
// always async
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
- completeRequest(
- callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());
+ var responseHeaders = xhr.getAllResponseHeaders();
+
+ // TODO(vojta): remove once Firefox 21 gets released.
+ // begin: workaround to overcome Firefox CORS http response headers bug
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=608735
+ // Firefox already patched in nightly. Should land in Firefox 21.
+
+ // CORS "simple response headers" http://www.w3.org/TR/cors/
+ var value,
+ simpleHeaders = ["Cache-Control", "Content-Language", "Content-Type",
+ "Expires", "Last-Modified", "Pragma"];
+ if (!responseHeaders) {
+ responseHeaders = "";
+ forEach(simpleHeaders, function (header) {
+ var value = xhr.getResponseHeader(header);
+ if (value) {
+ responseHeaders += header + ": " + value + "\n";
+ }
+ });
+ }
+ // end of the workaround.
+
+ completeRequest(callback, status || xhr.status, xhr.responseText,
+ responseHeaders);
}
};
@@ -9508,7 +9618,7 @@ function $FilterProvider($provide) {
*/
function filterFilter() {
return function(array, expression) {
- if (!(array instanceof Array)) return array;
+ if (!isArray(array)) return array;
var predicates = [];
predicates.check = function(value) {
for (var j = 0; j < predicates.length; j++) {
@@ -9757,7 +9867,7 @@ function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
fraction += '0';
}
- if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);
+ if (fractionSize && fractionSize !== "0") formatedText += decimalSep + fraction.substr(0, fractionSize);
}
parts.push(isNegative ? pattern.negPre : pattern.posPre);
@@ -9800,8 +9910,12 @@ function dateStrGetter(name, shortForm) {
}
function timeZoneGetter(date) {
- var offset = date.getTimezoneOffset();
- return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);
+ var zone = -1 * date.getTimezoneOffset();
+ var paddedZone = (zone >= 0) ? "+" : "";
+
+ paddedZone += padNumber(zone / 60, 2) + padNumber(Math.abs(zone % 60), 2);
+
+ return paddedZone;
}
function ampmGetter(date, formats) {
@@ -9887,7 +10001,8 @@ var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+
*
* @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or
* number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's
- * shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).
+ * shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ). If no timezone is
+ * specified in the string input, the time is considered to be in the local timezone.
* @param {string=} format Formatting rules (see Description). If not specified,
* `mediumDate` is used.
* @returns {string} Formatted string or the input if input is not recognized as date/millis.
@@ -9907,7 +10022,7 @@ var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+
expect(binding("1288323623006 | date:'medium'")).
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'")).
- toMatch(/2010\-10\-2\d \d{2}:\d{2}:\d{2} \-?\d{4}/);
+ toMatch(/2010\-10\-2\d \d{2}:\d{2}:\d{2} (\-|\+)?\d{4}/);
expect(binding("'1288323623006' | date:'MM/dd/yyyy @ h:mma'")).
toMatch(/10\/2\d\/2010 @ \d{1,2}:\d{2}(AM|PM)/);
});
@@ -10213,7 +10328,7 @@ function limitToFilter(){
orderByFilter.$inject = ['$parse'];
function orderByFilter($parse){
return function(array, sortPredicate, reverseOrder) {
- if (!(array instanceof Array)) return array;
+ if (!isArray(array)) return array;
if (!sortPredicate) return array;
sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];
sortPredicate = map(sortPredicate, function(predicate){
@@ -10281,15 +10396,25 @@ function ngDirective(directive) {
*
* The reasoning for this change is to allow easy creation of action links with `ngClick` directive
* without changing the location or causing page reloads, e.g.:
- * <a href="" ng-click="model.$save()">Save</a>
+ * `<a href="" ng-click="model.$save()">Save</a>`
*/
var htmlAnchorDirective = valueFn({
restrict: 'E',
compile: function(element, attr) {
- // turn <a href ng-click="..">link</a> into a link in IE
- // but only if it doesn't have name attribute, in which case it's an anchor
- if (!attr.href) {
- attr.$set('href', '');
+
+ if (msie <= 8) {
+
+ // turn <a href ng-click="..">link</a> into a stylable link in IE
+ // but only if it doesn't have name attribute, in which case it's an anchor
+ if (!attr.href && !attr.name) {
+ attr.$set('href', '');
+ }
+
+ // add a comment node to anchors to workaround IE bug that causes element content to be reset
+ // to new attribute content if attribute is updated with value containing @ and element also
+ // contains value with @
+ // see issue #1949
+ element.append(document.createComment('IE fix'));
}
return function(scope, element) {
@@ -10369,7 +10494,7 @@ var htmlAnchorDirective = valueFn({
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('');
+ expect(element('#link-5').attr('href')).toBe(undefined);
});
it('should only change url when only ng-href', function() {
@@ -10612,8 +10737,9 @@ forEach(['src', 'href'], function(attrName) {
// on IE, if "ng:src" directive declaration is used and "src" attribute doesn't exist
// then calling element.setAttribute('src', 'foo') doesn't do anything, so we need
- // to set the property as well to achieve the desired effect
- if (msie) element.prop(attrName, value);
+ // to set the property as well to achieve the desired effect.
+ // we use attr[attrName] value since $set can sanitize the url.
+ if (msie) element.prop(attrName, attr[attrName]);
});
}
};
@@ -12318,6 +12444,7 @@ var ngBindHtmlUnsafeDirective = [function() {
function classDirective(name, selector) {
name = 'ngClass' + name;
return ngDirective(function(scope, element, attr) {
+ var oldVal = undefined;
scope.$watch(attr[name], ngClassWatchAction, true);
@@ -12341,13 +12468,14 @@ function classDirective(name, selector) {
}
- function ngClassWatchAction(newVal, oldVal) {
+ function ngClassWatchAction(newVal) {
if (selector === true || scope.$index % 2 === selector) {
if (oldVal && (newVal !== oldVal)) {
removeClass(oldVal);
}
addClass(newVal);
}
+ oldVal = newVal;
}
@@ -12380,7 +12508,7 @@ function classDirective(name, selector) {
*
* The directive won't add duplicate classes if a particular class was already set.
*
- * When the expression changes, the previously added classes are removed and only then the classes
+ * When the expression changes, the previously added classes are removed and only then the
* new classes are added.
*
* @element ANY
@@ -13704,9 +13832,10 @@ var NG_SWITCH = 'ng-switch';
var ngSwitchDirective = valueFn({
restrict: 'EA',
require: 'ngSwitch',
- controller: function ngSwitchController() {
+ // asks for $scope to fool the BC controller module
+ controller: ['$scope', function ngSwitchController() {
this.cases = {};
- },
+ }],
link: function(scope, element, attr, ctrl) {
var watchExpr = attr.ngSwitch || attr.on,
selectedTransclude,
@@ -13957,7 +14086,7 @@ var ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$c
if (current.controller) {
locals.$scope = lastScope;
controller = $controller(current.controller, locals);
- element.contents().data('$ngControllerController', controller);
+ element.children().data('$ngControllerController', controller);
}
link(lastScope);
View
313 app/lib/angular/angular.min.js
157 additions, 156 deletions not shown
View
2  app/lib/angular/version.txt
@@ -1 +1 @@
-1.0.4
+1.0.5
View
2  test/lib/angular/angular-mocks.js
@@ -1,5 +1,5 @@
/**
- * @license AngularJS v1.0.4
+ * @license AngularJS v1.0.5
* (c) 2010-2012 Google, Inc. http://angularjs.org
* License: MIT
*
View
259 test/lib/angular/angular-scenario.js
@@ -9404,7 +9404,7 @@ if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
})( window );
/**
- * @license AngularJS v1.0.4
+ * @license AngularJS v1.0.5
* (c) 2010-2012 Google, Inc. http://angularjs.org
* License: MIT
*/
@@ -9460,8 +9460,7 @@ if ('i' !== 'I'.toLowerCase()) {
function fromCharCode(code) {return String.fromCharCode(code);}
-var Error = window.Error,
- /** holds major version number for IE or NaN for real browsers */
+var /** holds major version number for IE or NaN for real browsers */
msie = int((/msie (\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),
jqLite, // delay binding since jQuery could be loaded after us.
jQuery, // delay binding
@@ -9502,6 +9501,30 @@ var Error = window.Error,
* @param {Object=} context Object to become context (`this`) for the iterator function.
* @returns {Object|Array} Reference to `obj`.
*/
+
+
+/**
+ * @private
+ * @param {*} obj
+ * @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments, ...)
+ */
+function isArrayLike(obj) {
+ if (!obj || (typeof obj.length !== 'number')) return false;
+
+ // We have on object which has length property. Should we treat it as array?
+ if (typeof obj.hasOwnProperty != 'function' &&
+ typeof obj.constructor != 'function') {
+ // This is here for IE8: it is a bogus object treat it as array;
+ return true;
+ } else {
+ return obj instanceof JQLite || // JQLite
+ (jQuery && obj instanceof jQuery) || // jQuery
+ toString.call(obj) !== '[object Object]' || // some browser native object
+ typeof obj.callee === 'function'; // arguments (on IE8 looks like regular obj)
+ }
+}
+
+
function forEach(obj, iterator, context) {
var key;
if (obj) {
@@ -9513,7 +9536,7 @@ function forEach(obj, iterator, context) {
}
} else if (obj.forEach && obj.forEach !== forEach) {
obj.forEach(iterator, context);
- } else if (isObject(obj) && isNumber(obj.length)) {
+ } else if (isArrayLike(obj)) {
for (key = 0; key < obj.length; key++)
iterator.call(context, obj[key], key);
} else {
@@ -9558,7 +9581,7 @@ function reverseParams(iteratorFn) {
/**
* A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric
* characters such as '012ABC'. The reason why we are not using simply a number counter is that
- * the number string gets longer over time, and it can also overflow, where as the the nextId
+ * the number string gets longer over time, and it can also overflow, where as the nextId
* will grow much slower, it is a string, and it will never overflow.
*
* @returns an unique alpha-numeric string
@@ -9954,9 +9977,7 @@ function copy(source, destination){
} else {
if (source === destination) throw Error("Can't copy equivalent objects or arrays");
if (isArray(source)) {
- while(destination.length) {
- destination.pop();
- }
+ destination.length = 0;
for ( var i = 0; i < source.length; i++) {
destination.push(copy(source[i]));
}
@@ -10167,9 +10188,18 @@ function startingTag(element) {
// are not allowed to have children. So we just ignore it.
element.html('');
} catch(e) {}
- return jqLite('<div>').append(element).html().
- match(/^(<[^>]+>)/)[1].
- replace(/^<([\w\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });
+ // As Per DOM Standards
+ var TEXT_NODE = 3;
+ var elemHtml = jqLite('<div>').append(element).html();
+ try {
+ return element[0].nodeType === TEXT_NODE ? lowercase(elemHtml) :
+ elemHtml.
+ match(/^(<[^>]+>)/)[1].
+ replace(/^<([\w\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });
+ } catch(e) {
+ return lowercase(elemHtml);
+ }
+
}
@@ -10253,7 +10283,7 @@ function encodeUriQuery(val, pctEncodeSpaces) {
* Use this directive to auto-bootstrap on application. Only
* one directive can be used per HTML document. The directive
* designates the root of the application and is typically placed
- * ot the root of the page.
+ * at the root of the page.
*
* In the example below if the `ngApp` directive would not be placed
* on the `html` element then the document would not be compiled
@@ -10654,11 +10684,11 @@ function setupModuleLoader(window) {
* - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
*/
var version = {
- full: '1.0.4', // all of these placeholder strings will be replaced by rake's
+ full: '1.0.5', // all of these placeholder strings will be replaced by rake's
major: 1, // compile task
minor: 0,
- dot: 4,
- codeName: 'bewildering-hair'
+ dot: 5,
+ codeName: 'flatulent-propulsion'
};
@@ -11835,7 +11865,7 @@ function annotate(fn) {
* This method does not work with code minfication / obfuscation. For this reason the following annotation strategies
* are supported.
*
- * # The `$injector` property
+ * # The `$inject` property
*
* If a function has an `$inject` property and its value is an array of strings, then the strings represent names of
* services to be injected into the function.
@@ -12549,7 +12579,7 @@ function Browser(window, document, $log, $sniffer) {
*/
self.baseHref = function() {
var href = baseElement.attr('href');
- return href ? href.replace(/^https?\:\/\/[^\/]*/, '') : href;
+ return href ? href.replace(/^https?\:\/\/[^\/]*/, '') : '';
};
//////////////////////////////////////////////////////////////
@@ -12999,7 +13029,8 @@ function $CompileProvider($provide) {
Suffix = 'Directive',
COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\d\w\-_]+)\s+(.*)$/,
CLASS_DIRECTIVE_REGEXP = /(([\d\w\-_]+)(?:\:([^;]+))?;?)/,
- MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';
+ MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ',
+ urlSanitizationWhitelist = /^\s*(https?|ftp|mailto):/;
/**
@@ -13053,11 +13084,41 @@ function $CompileProvider($provide) {
};
+ /**
+ * @ngdoc function
+ * @name ng.$compileProvider#urlSanitizationWhitelist
+ * @methodOf ng.$compileProvider
+ * @function
+ *
+ * @description
+ * Retrieves or overrides the default regular expression that is used for whitelisting of safe
+ * urls during a[href] sanitization.
+ *
+ * The sanitization is a security measure aimed at prevent XSS attacks via html links.
+ *
+ * Any url about to be assigned to a[href] via data-binding is first normalized and turned into an
+ * absolute url. Afterwards the url is matched against the `urlSanitizationWhitelist` regular
+ * expression. If a match is found the original url is written into the dom. Otherwise the
+ * absolute url is prefixed with `'unsafe:'` string and only then it is written into the DOM.
+ *
+ * @param {RegExp=} regexp New regexp to whitelist urls with.
+ * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
+ * chaining otherwise.
+ */
+ this.urlSanitizationWhitelist = function(regexp) {
+ if (isDefined(regexp)) {
+ urlSanitizationWhitelist = regexp;
+ return this;
+ }
+ return urlSanitizationWhitelist;
+ };
+
+
this.$get = [
'$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',
- '$controller', '$rootScope',
+ '$controller', '$rootScope', '$document',
function($injector, $interpolate, $exceptionHandler, $http, $templateCache, $parse,
- $controller, $rootScope) {
+ $controller, $rootScope, $document) {
var Attributes = function(element, attr) {
this.$$element = element;
@@ -13079,7 +13140,8 @@ function $CompileProvider($provide) {
*/
$set: function(key, value, writeAttr, attrName) {
var booleanKey = getBooleanAttrName(this.$$element[0], key),
- $$observers = this.$$observers;
+ $$observers = this.$$observers,
+ normalizedVal;
if (booleanKey) {
this.$$element.prop(key, value);
@@ -13098,6 +13160,19 @@ function $CompileProvider($provide) {
}
}
+
+ // sanitize a[href] values
+ if (nodeName_(this.$$element[0]) === 'A' && key === 'href') {
+ urlSanitizationNode.setAttribute('href', value);
+
+ // href property always returns normalized absolute url, so we can match against that
+ normalizedVal = urlSanitizationNode.href;
+ if (!normalizedVal.match(urlSanitizationWhitelist)) {
+ this[key] = value = 'unsafe:' + normalizedVal;
+ }
+ }
+
+
if (writeAttr !== false) {
if (value === null || value === undefined) {
this.$$element.removeAttr(attrName);
@@ -13141,7 +13216,8 @@ function $CompileProvider($provide) {
}
};
- var startSymbol = $interpolate.startSymbol(),
+ var urlSanitizationNode = $document[0].createElement('a'),
+ startSymbol = $interpolate.startSymbol(),
endSymbol = $interpolate.endSymbol(),
denormalizeTemplate = (startSymbol == '{{' || endSymbol == '}}')
? identity
@@ -13174,7 +13250,14 @@ function $CompileProvider($provide) {
var $linkNode = cloneConnectFn
? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!
: $compileNodes;
- $linkNode.data('$scope', scope);
+
+ // Attach scope only to non-text nodes.
+ for(var i = 0, ii = $linkNode.length; i<ii; i++) {
+ var node = $linkNode[i];
+ if (node.nodeType == 1 /* element */ || node.nodeType == 9 /* document */) {
+ $linkNode.eq(i).data('$scope', scope);
+ }
+ }
safeAddClass($linkNode, 'ng-scope');
if (cloneConnectFn) cloneConnectFn($linkNode, scope);
if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);
@@ -13264,6 +13347,7 @@ function $CompileProvider($provide) {
(function(transcludeFn) {
return function(cloneFn) {
var transcludeScope = scope.$new();
+ transcludeScope.$$transcluded = true;
return transcludeFn(transcludeScope, cloneFn).
bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));
@@ -13569,6 +13653,8 @@ function $CompileProvider($provide) {
lastValue,
parentGet, parentSet;
+ scope.$$isolateBindings[scopeName] = mode + attrName;
+
switch (mode) {
case '@': {
@@ -13779,7 +13865,7 @@ function $CompileProvider($provide) {
}
directives.unshift(derivedSyncDirective);
- afterTemplateNodeLinkFn = applyDirectivesToNode(directives, $compileNode, tAttrs, childTranscludeFn);
+ afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs, childTranscludeFn);
afterTemplateChildLinkFn = compileNodes($compileNode.contents(), childTranscludeFn);
@@ -13859,10 +13945,10 @@ function $CompileProvider($provide) {
function addAttrInterpolateDirective(node, directives, value, name) {
var interpolateFn = $interpolate(value, true);
-
// no interpolation found -> ignore
if (!interpolateFn) return;
+
directives.push({
priority: 100,
compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {
@@ -15856,9 +15942,10 @@ function getterFn(path, csp) {
* @param {string} expression String expression to compile.
* @returns {function(context, locals)} a function which represents the compiled expression:
*
- * * `context`: an object against which any expressions embedded in the strings are evaluated
- * against (Topically a scope object).
- * * `locals`: local variables context object, useful for overriding values in `context`.
+ * * `context` – `{object}` – an object against which any expressions embedded in the strings
+ * are evaluated against (tipically a scope object).
+ * * `locals` – `{object=}` – local variables context object, useful for overriding values in
+ * `context`.
*
* The return function also has an `assign` property, if the expression is assignable, which
* allows one to set values to expressions.
@@ -15894,7 +15981,7 @@ function $ParseProvider() {
* interface for interacting with an object that represents the result of an action that is
* performed asynchronously, and may or may not be finished at any given point in time.
*
- * From the perspective of dealing with error handling, deferred and promise apis are to
+ * From the perspective of dealing with error handling, deferred and promise APIs are to
* asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.
*
* <pre>
@@ -15929,7 +16016,7 @@ function $ParseProvider() {
*
* At first it might not be obvious why this extra complexity is worth the trouble. The payoff
* comes in the way of
- * [guarantees that promise and deferred apis make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).
+ * [guarantees that promise and deferred APIs make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md).
*
* Additionally the promise api allows for composition that is very hard to do with the
* traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.
@@ -15941,7 +16028,7 @@ function $ParseProvider() {
*
* A new instance of deferred is constructed by calling `$q.defer()`.
*
- * The purpose of the deferred object is to expose the associated Promise instance as well as apis
+ * The purpose of the deferred object is to expose the associated Promise instance as well as APIs
* that can be used for signaling the successful or unsuccessful completion of the task.
*
* **Methods**
@@ -15984,7 +16071,7 @@ function $ParseProvider() {
* return result + 1;
* });
*
- * // promiseB will be resolved immediately after promiseA is resolved and it's value will be
+ * // promiseB will be resolved immediately after promiseA is resolved and its value will be
* // the result of promiseA incremented by 1
* </pre>
*
@@ -16009,7 +16096,7 @@ function $ParseProvider() {
* # Testing
*
* <pre>
- * it('should simulate promise', inject(function($q, $rootSCope) {
+ * it('should simulate promise', inject(function($q, $rootScope) {
* var deferred = $q.defer();
* var promise = deferred.promise;
* var resolvedValue;
@@ -16018,7 +16105,7 @@ function $ParseProvider() {
* expect(resolvedValue).toBeUndefined();
*
* // Simulate resolving of promise
- * defered.resolve(123);
+ * deferred.resolve(123);
* // Note that the 'then' function does not get called synchronously.
* // This is because we want the promise API to always be async, whether or not
* // it got called synchronously or asynchronously.
@@ -16194,12 +16281,12 @@ function qFactory(nextTick, exceptionHandler) {
* @methodOf ng.$q
* @description
* Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.
- * This is useful when you are dealing with on object that might or might not be a promise, or if
+ * This is useful when you are dealing with an object that might or might not be a promise, or if
* the promise comes from a source that can't be trusted.
*
* @param {*} value Value or a promise
* @returns {Promise} Returns a single promise that will be resolved with an array of values,
- * each value coresponding to the promise at the same index in the `promises` array. If any of
+ * each value corresponding to the promise at the same index in the `promises` array. If any of
* the promises is resolved with a rejection, this resulting promise will be resolved with the
* same rejection.
*/
@@ -16261,7 +16348,7 @@ function qFactory(nextTick, exceptionHandler) {
*
* @param {Array.<Promise>} promises An array of promises.
* @returns {Promise} Returns a single promise that will be resolved with an array of values,
- * each value coresponding to the promise at the same index in the `promises` array. If any of
+ * each value corresponding to the promise at the same index in the `promises` array. If any of
* the promises is resolved with a rejection, this resulting promise will be resolved with the
* same rejection.
*/
@@ -16930,6 +17017,7 @@ function $RootScopeProvider(){
this.$$destroyed = false;
this.$$asyncQueue = [];
this.$$listeners = {};
+ this.$$isolateBindings = {};
}
/**
@@ -17411,10 +17499,6 @@ function $RootScopeProvider(){
* Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of
* event life cycle.
*
- * @param {string} name Event name to listen on.
- * @param {function(event)} listener Function to call when the event is emitted.
- * @returns {function()} Returns a deregistration function for this listener.
- *
* The event listener function format is: `function(event, args...)`. The `event` object
* passed into the listener has the following attributes:
*
@@ -17425,6 +17509,10 @@ function $RootScopeProvider(){
* propagation (available only for events that were `$emit`-ed).
* - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true.
* - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.
+ *
+ * @param {string} name Event name to listen on.
+ * @param {function(event, args...)} listener Function to call when the event is emitted.
+ * @returns {function()} Returns a deregistration function for this listener.
*/
$on: function(name, listener) {
var namedListeners = this.$$listeners[name];
@@ -17602,7 +17690,7 @@ function $RootScopeProvider(){
/**
* function used as an initial value for watchers.
- * because it's uniqueue we can easily tell it apart from other values
+ * because it's unique we can easily tell it apart from other values
*/
function initWatchVal() {}
}];
@@ -18513,8 +18601,30 @@ function createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument,
// always async
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
- completeRequest(
- callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());
+ var responseHeaders = xhr.getAllResponseHeaders();
+
+ // TODO(vojta): remove once Firefox 21 gets released.
+ // begin: workaround to overcome Firefox CORS http response headers bug
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=608735
+ // Firefox already patched in nightly. Should land in Firefox 21.
+
+ // CORS "simple response headers" http://www.w3.org/TR/cors/
+ var value,
+ simpleHeaders = ["Cache-Control", "Content-Language", "Content-Type",
+ "Expires", "Last-Modified", "Pragma"];
+ if (!responseHeaders) {
+ responseHeaders = "";
+ forEach(simpleHeaders, function (header) {
+ var value = xhr.getResponseHeader(header);
+ if (value) {
+ responseHeaders += header + ": " + value + "\n";
+ }
+ });
+ }
+ // end of the workaround.
+
+ completeRequest(callback, status || xhr.status, xhr.responseText,
+ responseHeaders);
}
};
@@ -18913,7 +19023,7 @@ function $FilterProvider($provide) {
*/
function filterFilter() {
return function(array, expression) {
- if (!(array instanceof Array)) return array;
+ if (!isArray(array)) return array;
var predicates = [];
predicates.check = function(value) {
for (var j = 0; j < predicates.length; j++) {
@@ -19162,7 +19272,7 @@ function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
fraction += '0';
}
- if (fractionSize) formatedText += decimalSep + fraction.substr(0, fractionSize);
+ if (fractionSize && fractionSize !== "0") formatedText += decimalSep + fraction.substr(0, fractionSize);
}
parts.push(isNegative ? pattern.negPre : pattern.posPre);
@@ -19205,8 +19315,12 @@ function dateStrGetter(name, shortForm) {
}
function timeZoneGetter(date) {
- var offset = date.getTimezoneOffset();
- return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);
+ var zone = -1 * date.getTimezoneOffset();
+ var paddedZone = (zone >= 0) ? "+" : "";
+
+ paddedZone += padNumber(zone / 60, 2) + padNumber(Math.abs(zone % 60), 2);
+
+ return paddedZone;
}
function ampmGetter(date, formats) {
@@ -19292,7 +19406,8 @@ var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+
*
* @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or
* number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and it's
- * shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ).
+ * shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ). If no timezone is
+ * specified in the string input, the time is considered to be in the local timezone.
* @param {string=} format Formatting rules (see Description). If not specified,
* `mediumDate` is used.
* @returns {string} Formatted string or the input if input is not recognized as date/millis.
@@ -19312,7 +19427,7 @@ var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+
expect(binding("1288323623006 | date:'medium'")).
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'")).
- toMatch(/2010\-10\-2\d \d{2}:\d{2}:\d{2} \-?\d{4}/);
+ toMatch(/2010\-10\-2\d \d{2}:\d{2}:\d{2} (\-|\+)?\d{4}/);
expect(binding("'1288323623006' | date:'MM/dd/yyyy @ h:mma'")).
toMatch(/10\/2\d\/2010 @ \d{1,2}:\d{2}(AM|PM)/);
});
@@ -19618,7 +19733,7 @@ function limitToFilter(){
orderByFilter.$inject = ['$parse'];
function orderByFilter($parse){
return function(array, sortPredicate, reverseOrder) {
- if (!(array instanceof Array)) return array;
+ if (!isArray(array)) return array;
if (!sortPredicate) return array;
sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];
sortPredicate = map(sortPredicate, function(predicate){
@@ -19686,15 +19801,25 @@ function ngDirective(directive) {
*
* The reasoning for this change is to allow easy creation of action links with `ngClick` directive
* without changing the location or causing page reloads, e.g.:
- * <a href="" ng-click="model.$save()">Save</a>
+ * `<a href="" ng-click="model.$save()">Save</a>`
*/
var htmlAnchorDirective = valueFn({
restrict: 'E',
compile: function(element, attr) {
- // turn <a href ng-click="..">link</a> into a link in IE
- // but only if it doesn't have name attribute, in which case it's an anchor
- if (!attr.href) {
- attr.$set('href', '');
+
+ if (msie <= 8) {
+
+ // turn <a href ng-click="..">link</a> into a stylable link in IE
+ // but only if it doesn't have name attribute, in which case it's an anchor
+ if (!attr.href && !attr.name) {
+ attr.$set('href', '');
+ }
+
+ // add a comment node to anchors to workaround IE bug that causes element content to be reset
+ // to new attribute content if attribute is updated with value containing @ and element also
+ // contains value with @
+ // see issue #1949
+ element.append(document.createComment('IE fix'));
}
return function(scope, element) {
@@ -19774,7 +19899,7 @@ var htmlAnchorDirective = valueFn({
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('');
+ expect(element('#link-5').attr('href')).toBe(undefined);
});
it('should only change url when only ng-href', function() {
@@ -20017,8 +20142,9 @@ forEach(['src', 'href'], function(attrName) {
// on IE, if "ng:src" directive declaration is used and "src" attribute doesn't exist
// then calling element.setAttribute('src', 'foo') doesn't do anything, so we need
- // to set the property as well to achieve the desired effect
- if (msie) element.prop(attrName, value);
+ // to set the property as well to achieve the desired effect.
+ // we use attr[attrName] value since $set can sanitize the url.
+ if (msie) element.prop(attrName, attr[attrName]);
});
}
};
@@ -21723,6 +21849,7 @@ var ngBindHtmlUnsafeDirective = [function() {
function classDirective(name, selector) {
name = 'ngClass' + name;
return ngDirective(function(scope, element, attr) {
+ var oldVal = undefined;
scope.$watch(attr[name], ngClassWatchAction, true);
@@ -21746,13 +21873,14 @@ function classDirective(name, selector) {
}
- function ngClassWatchAction(newVal, oldVal) {
+ function ngClassWatchAction(newVal) {
if (selector === true || scope.$index % 2 === selector) {
if (oldVal && (newVal !== oldVal)) {
removeClass(oldVal);
}
addClass(newVal);
}
+ oldVal = newVal;
}
@@ -21785,7 +21913,7 @@ function classDirective(name, selector) {
*
* The directive won't add duplicate classes if a particular class was already set.
*
- * When the expression changes, the previously added classes are removed and only then the classes
+ * When the expression changes, the previously added classes are removed and only then the
* new classes are added.
*
* @element ANY
@@ -23109,9 +23237,10 @@ var NG_SWITCH = 'ng-switch';
var ngSwitchDirective = valueFn({
restrict: 'EA',
require: 'ngSwitch',
- controller: function ngSwitchController() {
+ // asks for $scope to fool the BC controller module
+ controller: ['$scope', function ngSwitchController() {
this.cases = {};
- },
+ }],
link: function(scope, element, attr, ctrl) {
var watchExpr = attr.ngSwitch || attr.on,
selectedTransclude,
@@ -23362,7 +23491,7 @@ var ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$c
if (current.controller) {
locals.$scope = lastScope;
controller = $controller(current.controller, locals);
- element.contents().data('$ngControllerController', controller);
+ element.children().data('$ngControllerController', controller);
}
link(lastScope);
@@ -26027,7 +26156,7 @@ angular.scenario.output('xml', function(context, runner, model) {
if (step.error) {
var error = $('<error></error>');
stepContext.append(error);
- error.text(formatException(stepContext.error));
+ error.text(formatException(step.error));
}
});
});
View
2  test/lib/angular/version.txt
@@ -1 +1 @@
-1.0.4
+1.0.5
Please sign in to comment.
Something went wrong with that request. Please try again.