annot-server/static/js/lib.js
changeset 117 c0034b35c44e
parent 84 d7c5bffdd2d8
child 159 f2e4641681f6
equal deleted inserted replaced
114:9fcb0e0991ed 117:c0034b35c44e
     1 /*!
     1 /*!
     2  * jQuery JavaScript Library v2.1.1
     2  * jQuery JavaScript Library v2.1.3
     3  * http://jquery.com/
     3  * http://jquery.com/
     4  *
     4  *
     5  * Includes Sizzle.js
     5  * Includes Sizzle.js
     6  * http://sizzlejs.com/
     6  * http://sizzlejs.com/
     7  *
     7  *
     8  * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors
     8  * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors
     9  * Released under the MIT license
     9  * Released under the MIT license
    10  * http://jquery.org/license
    10  * http://jquery.org/license
    11  *
    11  *
    12  * Date: 2014-05-01T17:11Z
    12  * Date: 2014-12-18T15:11Z
    13  */
    13  */
    14 
    14 
    15 (function( global, factory ) {
    15 (function( global, factory ) {
    16 
    16 
    17 	if ( typeof module === "object" && typeof module.exports === "object" ) {
    17 	if ( typeof module === "object" && typeof module.exports === "object" ) {
    18 		// For CommonJS and CommonJS-like environments where a proper window is present,
    18 		// For CommonJS and CommonJS-like environments where a proper `window`
    19 		// execute the factory and get jQuery
    19 		// is present, execute the factory and get jQuery.
    20 		// For environments that do not inherently posses a window with a document
    20 		// For environments that do not have a `window` with a `document`
    21 		// (such as Node.js), expose a jQuery-making factory as module.exports
    21 		// (such as Node.js), expose a factory as module.exports.
    22 		// This accentuates the need for the creation of a real window
    22 		// This accentuates the need for the creation of a real `window`.
    23 		// e.g. var jQuery = require("jquery")(window);
    23 		// e.g. var jQuery = require("jquery")(window);
    24 		// See ticket #14549 for more info
    24 		// See ticket #14549 for more info.
    25 		module.exports = global.document ?
    25 		module.exports = global.document ?
    26 			factory( global, true ) :
    26 			factory( global, true ) :
    27 			function( w ) {
    27 			function( w ) {
    28 				if ( !w.document ) {
    28 				if ( !w.document ) {
    29 					throw new Error( "jQuery requires a window with a document" );
    29 					throw new Error( "jQuery requires a window with a document" );
    35 	}
    35 	}
    36 
    36 
    37 // Pass this if window is not defined yet
    37 // Pass this if window is not defined yet
    38 }(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
    38 }(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
    39 
    39 
    40 // Can't do this because several apps including ASP.NET trace
    40 // Support: Firefox 18+
       
    41 // Can't be in strict mode, several libs including ASP.NET trace
    41 // the stack via arguments.caller.callee and Firefox dies if
    42 // the stack via arguments.caller.callee and Firefox dies if
    42 // you try to trace through "use strict" call chains. (#13335)
    43 // you try to trace through "use strict" call chains. (#13335)
    43 // Support: Firefox 18+
       
    44 //
    44 //
    45 
    45 
    46 var arr = [];
    46 var arr = [];
    47 
    47 
    48 var slice = arr.slice;
    48 var slice = arr.slice;
    65 
    65 
    66 var
    66 var
    67 	// Use the correct document accordingly with window argument (sandbox)
    67 	// Use the correct document accordingly with window argument (sandbox)
    68 	document = window.document,
    68 	document = window.document,
    69 
    69 
    70 	version = "2.1.1",
    70 	version = "2.1.3",
    71 
    71 
    72 	// Define a local copy of jQuery
    72 	// Define a local copy of jQuery
    73 	jQuery = function( selector, context ) {
    73 	jQuery = function( selector, context ) {
    74 		// The jQuery object is actually just the init constructor 'enhanced'
    74 		// The jQuery object is actually just the init constructor 'enhanced'
    75 		// Need init if jQuery is called (just allow error to be thrown if not included)
    75 		// Need init if jQuery is called (just allow error to be thrown if not included)
   183 
   183 
   184 	// Handle a deep copy situation
   184 	// Handle a deep copy situation
   185 	if ( typeof target === "boolean" ) {
   185 	if ( typeof target === "boolean" ) {
   186 		deep = target;
   186 		deep = target;
   187 
   187 
   188 		// skip the boolean and the target
   188 		// Skip the boolean and the target
   189 		target = arguments[ i ] || {};
   189 		target = arguments[ i ] || {};
   190 		i++;
   190 		i++;
   191 	}
   191 	}
   192 
   192 
   193 	// Handle case when target is a string or something (possible in deep copy)
   193 	// Handle case when target is a string or something (possible in deep copy)
   194 	if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
   194 	if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
   195 		target = {};
   195 		target = {};
   196 	}
   196 	}
   197 
   197 
   198 	// extend jQuery itself if only one argument is passed
   198 	// Extend jQuery itself if only one argument is passed
   199 	if ( i === length ) {
   199 	if ( i === length ) {
   200 		target = this;
   200 		target = this;
   201 		i--;
   201 		i--;
   202 	}
   202 	}
   203 
   203 
   250 		throw new Error( msg );
   250 		throw new Error( msg );
   251 	},
   251 	},
   252 
   252 
   253 	noop: function() {},
   253 	noop: function() {},
   254 
   254 
   255 	// See test/unit/core.js for details concerning isFunction.
       
   256 	// Since version 1.3, DOM methods and functions like alert
       
   257 	// aren't supported. They return false on IE (#2968).
       
   258 	isFunction: function( obj ) {
   255 	isFunction: function( obj ) {
   259 		return jQuery.type(obj) === "function";
   256 		return jQuery.type(obj) === "function";
   260 	},
   257 	},
   261 
   258 
   262 	isArray: Array.isArray,
   259 	isArray: Array.isArray,
   267 
   264 
   268 	isNumeric: function( obj ) {
   265 	isNumeric: function( obj ) {
   269 		// parseFloat NaNs numeric-cast false positives (null|true|false|"")
   266 		// parseFloat NaNs numeric-cast false positives (null|true|false|"")
   270 		// ...but misinterprets leading-number strings, particularly hex literals ("0x...")
   267 		// ...but misinterprets leading-number strings, particularly hex literals ("0x...")
   271 		// subtraction forces infinities to NaN
   268 		// subtraction forces infinities to NaN
   272 		return !jQuery.isArray( obj ) && obj - parseFloat( obj ) >= 0;
   269 		// adding 1 corrects loss of precision from parseFloat (#15100)
       
   270 		return !jQuery.isArray( obj ) && (obj - parseFloat( obj ) + 1) >= 0;
   273 	},
   271 	},
   274 
   272 
   275 	isPlainObject: function( obj ) {
   273 	isPlainObject: function( obj ) {
   276 		// Not plain objects:
   274 		// Not plain objects:
   277 		// - Any object or value whose internal [[Class]] property is not "[object Object]"
   275 		// - Any object or value whose internal [[Class]] property is not "[object Object]"
   301 
   299 
   302 	type: function( obj ) {
   300 	type: function( obj ) {
   303 		if ( obj == null ) {
   301 		if ( obj == null ) {
   304 			return obj + "";
   302 			return obj + "";
   305 		}
   303 		}
   306 		// Support: Android < 4.0, iOS < 6 (functionish RegExp)
   304 		// Support: Android<4.0, iOS<6 (functionish RegExp)
   307 		return typeof obj === "object" || typeof obj === "function" ?
   305 		return typeof obj === "object" || typeof obj === "function" ?
   308 			class2type[ toString.call(obj) ] || "object" :
   306 			class2type[ toString.call(obj) ] || "object" :
   309 			typeof obj;
   307 			typeof obj;
   310 	},
   308 	},
   311 
   309 
   331 			}
   329 			}
   332 		}
   330 		}
   333 	},
   331 	},
   334 
   332 
   335 	// Convert dashed to camelCase; used by the css and data modules
   333 	// Convert dashed to camelCase; used by the css and data modules
       
   334 	// Support: IE9-11+
   336 	// Microsoft forgot to hump their vendor prefix (#9572)
   335 	// Microsoft forgot to hump their vendor prefix (#9572)
   337 	camelCase: function( string ) {
   336 	camelCase: function( string ) {
   338 		return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
   337 		return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
   339 	},
   338 	},
   340 
   339 
   546 	return type === "array" || length === 0 ||
   545 	return type === "array" || length === 0 ||
   547 		typeof length === "number" && length > 0 && ( length - 1 ) in obj;
   546 		typeof length === "number" && length > 0 && ( length - 1 ) in obj;
   548 }
   547 }
   549 var Sizzle =
   548 var Sizzle =
   550 /*!
   549 /*!
   551  * Sizzle CSS Selector Engine v1.10.19
   550  * Sizzle CSS Selector Engine v2.2.0-pre
   552  * http://sizzlejs.com/
   551  * http://sizzlejs.com/
   553  *
   552  *
   554  * Copyright 2013 jQuery Foundation, Inc. and other contributors
   553  * Copyright 2008, 2014 jQuery Foundation, Inc. and other contributors
   555  * Released under the MIT license
   554  * Released under the MIT license
   556  * http://jquery.org/license
   555  * http://jquery.org/license
   557  *
   556  *
   558  * Date: 2014-04-18
   557  * Date: 2014-12-16
   559  */
   558  */
   560 (function( window ) {
   559 (function( window ) {
   561 
   560 
   562 var i,
   561 var i,
   563 	support,
   562 	support,
   580 	rbuggyMatches,
   579 	rbuggyMatches,
   581 	matches,
   580 	matches,
   582 	contains,
   581 	contains,
   583 
   582 
   584 	// Instance-specific data
   583 	// Instance-specific data
   585 	expando = "sizzle" + -(new Date()),
   584 	expando = "sizzle" + 1 * new Date(),
   586 	preferredDoc = window.document,
   585 	preferredDoc = window.document,
   587 	dirruns = 0,
   586 	dirruns = 0,
   588 	done = 0,
   587 	done = 0,
   589 	classCache = createCache(),
   588 	classCache = createCache(),
   590 	tokenCache = createCache(),
   589 	tokenCache = createCache(),
   595 		}
   594 		}
   596 		return 0;
   595 		return 0;
   597 	},
   596 	},
   598 
   597 
   599 	// General-purpose constants
   598 	// General-purpose constants
   600 	strundefined = typeof undefined,
       
   601 	MAX_NEGATIVE = 1 << 31,
   599 	MAX_NEGATIVE = 1 << 31,
   602 
   600 
   603 	// Instance methods
   601 	// Instance methods
   604 	hasOwn = ({}).hasOwnProperty,
   602 	hasOwn = ({}).hasOwnProperty,
   605 	arr = [],
   603 	arr = [],
   606 	pop = arr.pop,
   604 	pop = arr.pop,
   607 	push_native = arr.push,
   605 	push_native = arr.push,
   608 	push = arr.push,
   606 	push = arr.push,
   609 	slice = arr.slice,
   607 	slice = arr.slice,
   610 	// Use a stripped-down indexOf if we can't use a native one
   608 	// Use a stripped-down indexOf as it's faster than native
   611 	indexOf = arr.indexOf || function( elem ) {
   609 	// http://jsperf.com/thor-indexof-vs-for/5
       
   610 	indexOf = function( list, elem ) {
   612 		var i = 0,
   611 		var i = 0,
   613 			len = this.length;
   612 			len = list.length;
   614 		for ( ; i < len; i++ ) {
   613 		for ( ; i < len; i++ ) {
   615 			if ( this[i] === elem ) {
   614 			if ( list[i] === elem ) {
   616 				return i;
   615 				return i;
   617 			}
   616 			}
   618 		}
   617 		}
   619 		return -1;
   618 		return -1;
   620 	},
   619 	},
   650 		// 3. anything else (capture 2)
   649 		// 3. anything else (capture 2)
   651 		".*" +
   650 		".*" +
   652 		")\\)|)",
   651 		")\\)|)",
   653 
   652 
   654 	// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
   653 	// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
       
   654 	rwhitespace = new RegExp( whitespace + "+", "g" ),
   655 	rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
   655 	rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
   656 
   656 
   657 	rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
   657 	rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
   658 	rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
   658 	rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
   659 
   659 
   701 			high < 0 ?
   701 			high < 0 ?
   702 				// BMP codepoint
   702 				// BMP codepoint
   703 				String.fromCharCode( high + 0x10000 ) :
   703 				String.fromCharCode( high + 0x10000 ) :
   704 				// Supplemental Plane codepoint (surrogate pair)
   704 				// Supplemental Plane codepoint (surrogate pair)
   705 				String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
   705 				String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
       
   706 	},
       
   707 
       
   708 	// Used for iframes
       
   709 	// See setDocument()
       
   710 	// Removing the function wrapper causes a "Permission Denied"
       
   711 	// error in IE
       
   712 	unloadHandler = function() {
       
   713 		setDocument();
   706 	};
   714 	};
   707 
   715 
   708 // Optimize for push.apply( _, NodeList )
   716 // Optimize for push.apply( _, NodeList )
   709 try {
   717 try {
   710 	push.apply(
   718 	push.apply(
   743 		setDocument( context );
   751 		setDocument( context );
   744 	}
   752 	}
   745 
   753 
   746 	context = context || document;
   754 	context = context || document;
   747 	results = results || [];
   755 	results = results || [];
   748 
   756 	nodeType = context.nodeType;
   749 	if ( !selector || typeof selector !== "string" ) {
   757 
       
   758 	if ( typeof selector !== "string" || !selector ||
       
   759 		nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
       
   760 
   750 		return results;
   761 		return results;
   751 	}
   762 	}
   752 
   763 
   753 	if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {
   764 	if ( !seed && documentIsHTML ) {
   754 		return [];
   765 
   755 	}
   766 		// Try to shortcut find operations when possible (e.g., not under DocumentFragment)
   756 
   767 		if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {
   757 	if ( documentIsHTML && !seed ) {
       
   758 
       
   759 		// Shortcuts
       
   760 		if ( (match = rquickExpr.exec( selector )) ) {
       
   761 			// Speed-up: Sizzle("#ID")
   768 			// Speed-up: Sizzle("#ID")
   762 			if ( (m = match[1]) ) {
   769 			if ( (m = match[1]) ) {
   763 				if ( nodeType === 9 ) {
   770 				if ( nodeType === 9 ) {
   764 					elem = context.getElementById( m );
   771 					elem = context.getElementById( m );
   765 					// Check parentNode to catch when Blackberry 4.6 returns
   772 					// Check parentNode to catch when Blackberry 4.6 returns
   787 			} else if ( match[2] ) {
   794 			} else if ( match[2] ) {
   788 				push.apply( results, context.getElementsByTagName( selector ) );
   795 				push.apply( results, context.getElementsByTagName( selector ) );
   789 				return results;
   796 				return results;
   790 
   797 
   791 			// Speed-up: Sizzle(".CLASS")
   798 			// Speed-up: Sizzle(".CLASS")
   792 			} else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) {
   799 			} else if ( (m = match[3]) && support.getElementsByClassName ) {
   793 				push.apply( results, context.getElementsByClassName( m ) );
   800 				push.apply( results, context.getElementsByClassName( m ) );
   794 				return results;
   801 				return results;
   795 			}
   802 			}
   796 		}
   803 		}
   797 
   804 
   798 		// QSA path
   805 		// QSA path
   799 		if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
   806 		if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
   800 			nid = old = expando;
   807 			nid = old = expando;
   801 			newContext = context;
   808 			newContext = context;
   802 			newSelector = nodeType === 9 && selector;
   809 			newSelector = nodeType !== 1 && selector;
   803 
   810 
   804 			// qSA works strangely on Element-rooted queries
   811 			// qSA works strangely on Element-rooted queries
   805 			// We can work around this by specifying an extra ID on the root
   812 			// We can work around this by specifying an extra ID on the root
   806 			// and working up from there (Thanks to Andrew Dupont for the technique)
   813 			// and working up from there (Thanks to Andrew Dupont for the technique)
   807 			// IE 8 doesn't work on object elements
   814 			// IE 8 doesn't work on object elements
   984  * Checks a node for validity as a Sizzle context
   991  * Checks a node for validity as a Sizzle context
   985  * @param {Element|Object=} context
   992  * @param {Element|Object=} context
   986  * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
   993  * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
   987  */
   994  */
   988 function testContext( context ) {
   995 function testContext( context ) {
   989 	return context && typeof context.getElementsByTagName !== strundefined && context;
   996 	return context && typeof context.getElementsByTagName !== "undefined" && context;
   990 }
   997 }
   991 
   998 
   992 // Expose support vars for convenience
   999 // Expose support vars for convenience
   993 support = Sizzle.support = {};
  1000 support = Sizzle.support = {};
   994 
  1001 
  1008  * Sets document-related variables once based on the current document
  1015  * Sets document-related variables once based on the current document
  1009  * @param {Element|Object} [doc] An element or document object to use to set the document
  1016  * @param {Element|Object} [doc] An element or document object to use to set the document
  1010  * @returns {Object} Returns the current document
  1017  * @returns {Object} Returns the current document
  1011  */
  1018  */
  1012 setDocument = Sizzle.setDocument = function( node ) {
  1019 setDocument = Sizzle.setDocument = function( node ) {
  1013 	var hasCompare,
  1020 	var hasCompare, parent,
  1014 		doc = node ? node.ownerDocument || node : preferredDoc,
  1021 		doc = node ? node.ownerDocument || node : preferredDoc;
  1015 		parent = doc.defaultView;
       
  1016 
  1022 
  1017 	// If no document and documentElement is available, return
  1023 	// If no document and documentElement is available, return
  1018 	if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
  1024 	if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
  1019 		return document;
  1025 		return document;
  1020 	}
  1026 	}
  1021 
  1027 
  1022 	// Set our document
  1028 	// Set our document
  1023 	document = doc;
  1029 	document = doc;
  1024 	docElem = doc.documentElement;
  1030 	docElem = doc.documentElement;
  1025 
  1031 	parent = doc.defaultView;
  1026 	// Support tests
       
  1027 	documentIsHTML = !isXML( doc );
       
  1028 
  1032 
  1029 	// Support: IE>8
  1033 	// Support: IE>8
  1030 	// If iframe document is assigned to "document" variable and if iframe has been reloaded,
  1034 	// If iframe document is assigned to "document" variable and if iframe has been reloaded,
  1031 	// IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936
  1035 	// IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936
  1032 	// IE6-8 do not support the defaultView property so parent will be undefined
  1036 	// IE6-8 do not support the defaultView property so parent will be undefined
  1033 	if ( parent && parent !== parent.top ) {
  1037 	if ( parent && parent !== parent.top ) {
  1034 		// IE11 does not have attachEvent, so all must suffer
  1038 		// IE11 does not have attachEvent, so all must suffer
  1035 		if ( parent.addEventListener ) {
  1039 		if ( parent.addEventListener ) {
  1036 			parent.addEventListener( "unload", function() {
  1040 			parent.addEventListener( "unload", unloadHandler, false );
  1037 				setDocument();
       
  1038 			}, false );
       
  1039 		} else if ( parent.attachEvent ) {
  1041 		} else if ( parent.attachEvent ) {
  1040 			parent.attachEvent( "onunload", function() {
  1042 			parent.attachEvent( "onunload", unloadHandler );
  1041 				setDocument();
       
  1042 			});
       
  1043 		}
  1043 		}
  1044 	}
  1044 	}
  1045 
  1045 
       
  1046 	/* Support tests
       
  1047 	---------------------------------------------------------------------- */
       
  1048 	documentIsHTML = !isXML( doc );
       
  1049 
  1046 	/* Attributes
  1050 	/* Attributes
  1047 	---------------------------------------------------------------------- */
  1051 	---------------------------------------------------------------------- */
  1048 
  1052 
  1049 	// Support: IE<8
  1053 	// Support: IE<8
  1050 	// Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans)
  1054 	// Verify that getAttribute really returns attributes and not properties
       
  1055 	// (excepting IE8 booleans)
  1051 	support.attributes = assert(function( div ) {
  1056 	support.attributes = assert(function( div ) {
  1052 		div.className = "i";
  1057 		div.className = "i";
  1053 		return !div.getAttribute("className");
  1058 		return !div.getAttribute("className");
  1054 	});
  1059 	});
  1055 
  1060 
  1060 	support.getElementsByTagName = assert(function( div ) {
  1065 	support.getElementsByTagName = assert(function( div ) {
  1061 		div.appendChild( doc.createComment("") );
  1066 		div.appendChild( doc.createComment("") );
  1062 		return !div.getElementsByTagName("*").length;
  1067 		return !div.getElementsByTagName("*").length;
  1063 	});
  1068 	});
  1064 
  1069 
  1065 	// Check if getElementsByClassName can be trusted
  1070 	// Support: IE<9
  1066 	support.getElementsByClassName = rnative.test( doc.getElementsByClassName ) && assert(function( div ) {
  1071 	support.getElementsByClassName = rnative.test( doc.getElementsByClassName );
  1067 		div.innerHTML = "<div class='a'></div><div class='a i'></div>";
       
  1068 
       
  1069 		// Support: Safari<4
       
  1070 		// Catch class over-caching
       
  1071 		div.firstChild.className = "i";
       
  1072 		// Support: Opera<10
       
  1073 		// Catch gEBCN failure to find non-leading classes
       
  1074 		return div.getElementsByClassName("i").length === 2;
       
  1075 	});
       
  1076 
  1072 
  1077 	// Support: IE<10
  1073 	// Support: IE<10
  1078 	// Check if getElementById returns elements by name
  1074 	// Check if getElementById returns elements by name
  1079 	// The broken getElementById methods don't pick up programatically-set names,
  1075 	// The broken getElementById methods don't pick up programatically-set names,
  1080 	// so use a roundabout getElementsByName test
  1076 	// so use a roundabout getElementsByName test
  1084 	});
  1080 	});
  1085 
  1081 
  1086 	// ID find and filter
  1082 	// ID find and filter
  1087 	if ( support.getById ) {
  1083 	if ( support.getById ) {
  1088 		Expr.find["ID"] = function( id, context ) {
  1084 		Expr.find["ID"] = function( id, context ) {
  1089 			if ( typeof context.getElementById !== strundefined && documentIsHTML ) {
  1085 			if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
  1090 				var m = context.getElementById( id );
  1086 				var m = context.getElementById( id );
  1091 				// Check parentNode to catch when Blackberry 4.6 returns
  1087 				// Check parentNode to catch when Blackberry 4.6 returns
  1092 				// nodes that are no longer in the document #6963
  1088 				// nodes that are no longer in the document #6963
  1093 				return m && m.parentNode ? [ m ] : [];
  1089 				return m && m.parentNode ? [ m ] : [];
  1094 			}
  1090 			}
  1105 		delete Expr.find["ID"];
  1101 		delete Expr.find["ID"];
  1106 
  1102 
  1107 		Expr.filter["ID"] =  function( id ) {
  1103 		Expr.filter["ID"] =  function( id ) {
  1108 			var attrId = id.replace( runescape, funescape );
  1104 			var attrId = id.replace( runescape, funescape );
  1109 			return function( elem ) {
  1105 			return function( elem ) {
  1110 				var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
  1106 				var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
  1111 				return node && node.value === attrId;
  1107 				return node && node.value === attrId;
  1112 			};
  1108 			};
  1113 		};
  1109 		};
  1114 	}
  1110 	}
  1115 
  1111 
  1116 	// Tag
  1112 	// Tag
  1117 	Expr.find["TAG"] = support.getElementsByTagName ?
  1113 	Expr.find["TAG"] = support.getElementsByTagName ?
  1118 		function( tag, context ) {
  1114 		function( tag, context ) {
  1119 			if ( typeof context.getElementsByTagName !== strundefined ) {
  1115 			if ( typeof context.getElementsByTagName !== "undefined" ) {
  1120 				return context.getElementsByTagName( tag );
  1116 				return context.getElementsByTagName( tag );
       
  1117 
       
  1118 			// DocumentFragment nodes don't have gEBTN
       
  1119 			} else if ( support.qsa ) {
       
  1120 				return context.querySelectorAll( tag );
  1121 			}
  1121 			}
  1122 		} :
  1122 		} :
       
  1123 
  1123 		function( tag, context ) {
  1124 		function( tag, context ) {
  1124 			var elem,
  1125 			var elem,
  1125 				tmp = [],
  1126 				tmp = [],
  1126 				i = 0,
  1127 				i = 0,
       
  1128 				// By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
  1127 				results = context.getElementsByTagName( tag );
  1129 				results = context.getElementsByTagName( tag );
  1128 
  1130 
  1129 			// Filter out possible comments
  1131 			// Filter out possible comments
  1130 			if ( tag === "*" ) {
  1132 			if ( tag === "*" ) {
  1131 				while ( (elem = results[i++]) ) {
  1133 				while ( (elem = results[i++]) ) {
  1139 			return results;
  1141 			return results;
  1140 		};
  1142 		};
  1141 
  1143 
  1142 	// Class
  1144 	// Class
  1143 	Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
  1145 	Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
  1144 		if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) {
  1146 		if ( documentIsHTML ) {
  1145 			return context.getElementsByClassName( className );
  1147 			return context.getElementsByClassName( className );
  1146 		}
  1148 		}
  1147 	};
  1149 	};
  1148 
  1150 
  1149 	/* QSA/matchesSelector
  1151 	/* QSA/matchesSelector
  1168 			// Select is set to empty string on purpose
  1170 			// Select is set to empty string on purpose
  1169 			// This is to test IE's treatment of not explicitly
  1171 			// This is to test IE's treatment of not explicitly
  1170 			// setting a boolean content attribute,
  1172 			// setting a boolean content attribute,
  1171 			// since its presence should be enough
  1173 			// since its presence should be enough
  1172 			// http://bugs.jquery.com/ticket/12359
  1174 			// http://bugs.jquery.com/ticket/12359
  1173 			div.innerHTML = "<select msallowclip=''><option selected=''></option></select>";
  1175 			docElem.appendChild( div ).innerHTML = "<a id='" + expando + "'></a>" +
       
  1176 				"<select id='" + expando + "-\f]' msallowcapture=''>" +
       
  1177 				"<option selected=''></option></select>";
  1174 
  1178 
  1175 			// Support: IE8, Opera 11-12.16
  1179 			// Support: IE8, Opera 11-12.16
  1176 			// Nothing should be selected when empty strings follow ^= or $= or *=
  1180 			// Nothing should be selected when empty strings follow ^= or $= or *=
  1177 			// The test attribute must be unknown in Opera but "safe" for WinRT
  1181 			// The test attribute must be unknown in Opera but "safe" for WinRT
  1178 			// http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
  1182 			// http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
  1179 			if ( div.querySelectorAll("[msallowclip^='']").length ) {
  1183 			if ( div.querySelectorAll("[msallowcapture^='']").length ) {
  1180 				rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
  1184 				rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
  1181 			}
  1185 			}
  1182 
  1186 
  1183 			// Support: IE8
  1187 			// Support: IE8
  1184 			// Boolean attributes and "value" are not treated correctly
  1188 			// Boolean attributes and "value" are not treated correctly
  1185 			if ( !div.querySelectorAll("[selected]").length ) {
  1189 			if ( !div.querySelectorAll("[selected]").length ) {
  1186 				rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
  1190 				rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
  1187 			}
  1191 			}
  1188 
  1192 
       
  1193 			// Support: Chrome<29, Android<4.2+, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.7+
       
  1194 			if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
       
  1195 				rbuggyQSA.push("~=");
       
  1196 			}
       
  1197 
  1189 			// Webkit/Opera - :checked should return selected option elements
  1198 			// Webkit/Opera - :checked should return selected option elements
  1190 			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
  1199 			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
  1191 			// IE8 throws error here and will not see later tests
  1200 			// IE8 throws error here and will not see later tests
  1192 			if ( !div.querySelectorAll(":checked").length ) {
  1201 			if ( !div.querySelectorAll(":checked").length ) {
  1193 				rbuggyQSA.push(":checked");
  1202 				rbuggyQSA.push(":checked");
       
  1203 			}
       
  1204 
       
  1205 			// Support: Safari 8+, iOS 8+
       
  1206 			// https://bugs.webkit.org/show_bug.cgi?id=136851
       
  1207 			// In-page `selector#id sibing-combinator selector` fails
       
  1208 			if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) {
       
  1209 				rbuggyQSA.push(".#.+[+~]");
  1194 			}
  1210 			}
  1195 		});
  1211 		});
  1196 
  1212 
  1197 		assert(function( div ) {
  1213 		assert(function( div ) {
  1198 			// Support: Windows 8 Native Apps
  1214 			// Support: Windows 8 Native Apps
  1306 				return 1;
  1322 				return 1;
  1307 			}
  1323 			}
  1308 
  1324 
  1309 			// Maintain original order
  1325 			// Maintain original order
  1310 			return sortInput ?
  1326 			return sortInput ?
  1311 				( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
  1327 				( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
  1312 				0;
  1328 				0;
  1313 		}
  1329 		}
  1314 
  1330 
  1315 		return compare & 4 ? -1 : 1;
  1331 		return compare & 4 ? -1 : 1;
  1316 	} :
  1332 	} :
  1333 			return a === doc ? -1 :
  1349 			return a === doc ? -1 :
  1334 				b === doc ? 1 :
  1350 				b === doc ? 1 :
  1335 				aup ? -1 :
  1351 				aup ? -1 :
  1336 				bup ? 1 :
  1352 				bup ? 1 :
  1337 				sortInput ?
  1353 				sortInput ?
  1338 				( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
  1354 				( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
  1339 				0;
  1355 				0;
  1340 
  1356 
  1341 		// If the nodes are siblings, we can do a quick check
  1357 		// If the nodes are siblings, we can do a quick check
  1342 		} else if ( aup === bup ) {
  1358 		} else if ( aup === bup ) {
  1343 			return siblingCheck( a, b );
  1359 			return siblingCheck( a, b );
  1396 					// As well, disconnected nodes are said to be in a document
  1412 					// As well, disconnected nodes are said to be in a document
  1397 					// fragment in IE 9
  1413 					// fragment in IE 9
  1398 					elem.document && elem.document.nodeType !== 11 ) {
  1414 					elem.document && elem.document.nodeType !== 11 ) {
  1399 				return ret;
  1415 				return ret;
  1400 			}
  1416 			}
  1401 		} catch(e) {}
  1417 		} catch (e) {}
  1402 	}
  1418 	}
  1403 
  1419 
  1404 	return Sizzle( expr, document, null, [ elem ] ).length > 0;
  1420 	return Sizzle( expr, document, null, [ elem ] ).length > 0;
  1405 };
  1421 };
  1406 
  1422 
  1615 			var pattern = classCache[ className + " " ];
  1631 			var pattern = classCache[ className + " " ];
  1616 
  1632 
  1617 			return pattern ||
  1633 			return pattern ||
  1618 				(pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
  1634 				(pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
  1619 				classCache( className, function( elem ) {
  1635 				classCache( className, function( elem ) {
  1620 					return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" );
  1636 					return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
  1621 				});
  1637 				});
  1622 		},
  1638 		},
  1623 
  1639 
  1624 		"ATTR": function( name, operator, check ) {
  1640 		"ATTR": function( name, operator, check ) {
  1625 			return function( elem ) {
  1641 			return function( elem ) {
  1637 				return operator === "=" ? result === check :
  1653 				return operator === "=" ? result === check :
  1638 					operator === "!=" ? result !== check :
  1654 					operator === "!=" ? result !== check :
  1639 					operator === "^=" ? check && result.indexOf( check ) === 0 :
  1655 					operator === "^=" ? check && result.indexOf( check ) === 0 :
  1640 					operator === "*=" ? check && result.indexOf( check ) > -1 :
  1656 					operator === "*=" ? check && result.indexOf( check ) > -1 :
  1641 					operator === "$=" ? check && result.slice( -check.length ) === check :
  1657 					operator === "$=" ? check && result.slice( -check.length ) === check :
  1642 					operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 :
  1658 					operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
  1643 					operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
  1659 					operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
  1644 					false;
  1660 					false;
  1645 			};
  1661 			};
  1646 		},
  1662 		},
  1647 
  1663 
  1757 					markFunction(function( seed, matches ) {
  1773 					markFunction(function( seed, matches ) {
  1758 						var idx,
  1774 						var idx,
  1759 							matched = fn( seed, argument ),
  1775 							matched = fn( seed, argument ),
  1760 							i = matched.length;
  1776 							i = matched.length;
  1761 						while ( i-- ) {
  1777 						while ( i-- ) {
  1762 							idx = indexOf.call( seed, matched[i] );
  1778 							idx = indexOf( seed, matched[i] );
  1763 							seed[ idx ] = !( matches[ idx ] = matched[i] );
  1779 							seed[ idx ] = !( matches[ idx ] = matched[i] );
  1764 						}
  1780 						}
  1765 					}) :
  1781 					}) :
  1766 					function( elem ) {
  1782 					function( elem ) {
  1767 						return fn( elem, 0, args );
  1783 						return fn( elem, 0, args );
  1796 					}
  1812 					}
  1797 				}) :
  1813 				}) :
  1798 				function( elem, context, xml ) {
  1814 				function( elem, context, xml ) {
  1799 					input[0] = elem;
  1815 					input[0] = elem;
  1800 					matcher( input, null, xml, results );
  1816 					matcher( input, null, xml, results );
       
  1817 					// Don't keep the element (issue #299)
       
  1818 					input[0] = null;
  1801 					return !results.pop();
  1819 					return !results.pop();
  1802 				};
  1820 				};
  1803 		}),
  1821 		}),
  1804 
  1822 
  1805 		"has": markFunction(function( selector ) {
  1823 		"has": markFunction(function( selector ) {
  1807 				return Sizzle( selector, elem ).length > 0;
  1825 				return Sizzle( selector, elem ).length > 0;
  1808 			};
  1826 			};
  1809 		}),
  1827 		}),
  1810 
  1828 
  1811 		"contains": markFunction(function( text ) {
  1829 		"contains": markFunction(function( text ) {
       
  1830 			text = text.replace( runescape, funescape );
  1812 			return function( elem ) {
  1831 			return function( elem ) {
  1813 				return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
  1832 				return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
  1814 			};
  1833 			};
  1815 		}),
  1834 		}),
  1816 
  1835 
  2228 
  2247 
  2229 				// Move matched elements from seed to results to keep them synchronized
  2248 				// Move matched elements from seed to results to keep them synchronized
  2230 				i = matcherOut.length;
  2249 				i = matcherOut.length;
  2231 				while ( i-- ) {
  2250 				while ( i-- ) {
  2232 					if ( (elem = matcherOut[i]) &&
  2251 					if ( (elem = matcherOut[i]) &&
  2233 						(temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {
  2252 						(temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {
  2234 
  2253 
  2235 						seed[temp] = !(results[temp] = elem);
  2254 						seed[temp] = !(results[temp] = elem);
  2236 					}
  2255 					}
  2237 				}
  2256 				}
  2238 			}
  2257 			}
  2263 		// The foundational matcher ensures that elements are reachable from top-level context(s)
  2282 		// The foundational matcher ensures that elements are reachable from top-level context(s)
  2264 		matchContext = addCombinator( function( elem ) {
  2283 		matchContext = addCombinator( function( elem ) {
  2265 			return elem === checkContext;
  2284 			return elem === checkContext;
  2266 		}, implicitRelative, true ),
  2285 		}, implicitRelative, true ),
  2267 		matchAnyContext = addCombinator( function( elem ) {
  2286 		matchAnyContext = addCombinator( function( elem ) {
  2268 			return indexOf.call( checkContext, elem ) > -1;
  2287 			return indexOf( checkContext, elem ) > -1;
  2269 		}, implicitRelative, true ),
  2288 		}, implicitRelative, true ),
  2270 		matchers = [ function( elem, context, xml ) {
  2289 		matchers = [ function( elem, context, xml ) {
  2271 			return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
  2290 			var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
  2272 				(checkContext = context).nodeType ?
  2291 				(checkContext = context).nodeType ?
  2273 					matchContext( elem, context, xml ) :
  2292 					matchContext( elem, context, xml ) :
  2274 					matchAnyContext( elem, context, xml ) );
  2293 					matchAnyContext( elem, context, xml ) );
       
  2294 			// Avoid hanging onto element (issue #299)
       
  2295 			checkContext = null;
       
  2296 			return ret;
  2275 		} ];
  2297 		} ];
  2276 
  2298 
  2277 	for ( ; i < len; i++ ) {
  2299 	for ( ; i < len; i++ ) {
  2278 		if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
  2300 		if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
  2279 			matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
  2301 			matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
  2519 // One-time assignments
  2541 // One-time assignments
  2520 
  2542 
  2521 // Sort stability
  2543 // Sort stability
  2522 support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
  2544 support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
  2523 
  2545 
  2524 // Support: Chrome<14
  2546 // Support: Chrome 14-35+
  2525 // Always assume duplicates if they aren't passed to the comparison function
  2547 // Always assume duplicates if they aren't passed to the comparison function
  2526 support.detectDuplicates = !!hasDuplicate;
  2548 support.detectDuplicates = !!hasDuplicate;
  2527 
  2549 
  2528 // Initialize against the default document
  2550 // Initialize against the default document
  2529 setDocument();
  2551 setDocument();
  2728 
  2750 
  2729 				// HANDLE: $(html) -> $(array)
  2751 				// HANDLE: $(html) -> $(array)
  2730 				if ( match[1] ) {
  2752 				if ( match[1] ) {
  2731 					context = context instanceof jQuery ? context[0] : context;
  2753 					context = context instanceof jQuery ? context[0] : context;
  2732 
  2754 
  2733 					// scripts is true for back-compat
  2755 					// Option to run scripts is true for back-compat
  2734 					// Intentionally let the error be thrown if parseHTML is not present
  2756 					// Intentionally let the error be thrown if parseHTML is not present
  2735 					jQuery.merge( this, jQuery.parseHTML(
  2757 					jQuery.merge( this, jQuery.parseHTML(
  2736 						match[1],
  2758 						match[1],
  2737 						context && context.nodeType ? context.ownerDocument || context : document,
  2759 						context && context.nodeType ? context.ownerDocument || context : document,
  2738 						true
  2760 						true
  2756 
  2778 
  2757 				// HANDLE: $(#id)
  2779 				// HANDLE: $(#id)
  2758 				} else {
  2780 				} else {
  2759 					elem = document.getElementById( match[2] );
  2781 					elem = document.getElementById( match[2] );
  2760 
  2782 
  2761 					// Check parentNode to catch when Blackberry 4.6 returns
  2783 					// Support: Blackberry 4.6
  2762 					// nodes that are no longer in the document #6963
  2784 					// gEBID returns nodes no longer in the document (#6963)
  2763 					if ( elem && elem.parentNode ) {
  2785 					if ( elem && elem.parentNode ) {
  2764 						// Inject the element directly into the jQuery object
  2786 						// Inject the element directly into the jQuery object
  2765 						this.length = 1;
  2787 						this.length = 1;
  2766 						this[0] = elem;
  2788 						this[0] = elem;
  2767 					}
  2789 					}
  2810 // Initialize central reference
  2832 // Initialize central reference
  2811 rootjQuery = jQuery( document );
  2833 rootjQuery = jQuery( document );
  2812 
  2834 
  2813 
  2835 
  2814 var rparentsprev = /^(?:parents|prev(?:Until|All))/,
  2836 var rparentsprev = /^(?:parents|prev(?:Until|All))/,
  2815 	// methods guaranteed to produce a unique set when starting from a unique set
  2837 	// Methods guaranteed to produce a unique set when starting from a unique set
  2816 	guaranteedUnique = {
  2838 	guaranteedUnique = {
  2817 		children: true,
  2839 		children: true,
  2818 		contents: true,
  2840 		contents: true,
  2819 		next: true,
  2841 		next: true,
  2820 		prev: true
  2842 		prev: true
  2890 		}
  2912 		}
  2891 
  2913 
  2892 		return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );
  2914 		return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );
  2893 	},
  2915 	},
  2894 
  2916 
  2895 	// Determine the position of an element within
  2917 	// Determine the position of an element within the set
  2896 	// the matched set of elements
       
  2897 	index: function( elem ) {
  2918 	index: function( elem ) {
  2898 
  2919 
  2899 		// No argument, return index in parent
  2920 		// No argument, return index in parent
  2900 		if ( !elem ) {
  2921 		if ( !elem ) {
  2901 			return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
  2922 			return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
  2902 		}
  2923 		}
  2903 
  2924 
  2904 		// index in selector
  2925 		// Index in selector
  2905 		if ( typeof elem === "string" ) {
  2926 		if ( typeof elem === "string" ) {
  2906 			return indexOf.call( jQuery( elem ), this[ 0 ] );
  2927 			return indexOf.call( jQuery( elem ), this[ 0 ] );
  2907 		}
  2928 		}
  2908 
  2929 
  2909 		// Locate the position of the desired element
  2930 		// Locate the position of the desired element
  3315 				};
  3336 				};
  3316 			},
  3337 			},
  3317 
  3338 
  3318 			progressValues, progressContexts, resolveContexts;
  3339 			progressValues, progressContexts, resolveContexts;
  3319 
  3340 
  3320 		// add listeners to Deferred subordinates; treat others as resolved
  3341 		// Add listeners to Deferred subordinates; treat others as resolved
  3321 		if ( length > 1 ) {
  3342 		if ( length > 1 ) {
  3322 			progressValues = new Array( length );
  3343 			progressValues = new Array( length );
  3323 			progressContexts = new Array( length );
  3344 			progressContexts = new Array( length );
  3324 			resolveContexts = new Array( length );
  3345 			resolveContexts = new Array( length );
  3325 			for ( ; i < length; i++ ) {
  3346 			for ( ; i < length; i++ ) {
  3332 					--remaining;
  3353 					--remaining;
  3333 				}
  3354 				}
  3334 			}
  3355 			}
  3335 		}
  3356 		}
  3336 
  3357 
  3337 		// if we're not waiting on anything, resolve the master
  3358 		// If we're not waiting on anything, resolve the master
  3338 		if ( !remaining ) {
  3359 		if ( !remaining ) {
  3339 			deferred.resolveWith( resolveContexts, resolveValues );
  3360 			deferred.resolveWith( resolveContexts, resolveValues );
  3340 		}
  3361 		}
  3341 
  3362 
  3342 		return deferred.promise();
  3363 		return deferred.promise();
  3411 	if ( !readyList ) {
  3432 	if ( !readyList ) {
  3412 
  3433 
  3413 		readyList = jQuery.Deferred();
  3434 		readyList = jQuery.Deferred();
  3414 
  3435 
  3415 		// Catch cases where $(document).ready() is called after the browser event has already occurred.
  3436 		// Catch cases where $(document).ready() is called after the browser event has already occurred.
  3416 		// we once tried to use readyState "interactive" here, but it caused issues like the one
  3437 		// We once tried to use readyState "interactive" here, but it caused issues like the one
  3417 		// discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
  3438 		// discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
  3418 		if ( document.readyState === "complete" ) {
  3439 		if ( document.readyState === "complete" ) {
  3419 			// Handle it asynchronously to allow scripts the opportunity to delay ready
  3440 			// Handle it asynchronously to allow scripts the opportunity to delay ready
  3420 			setTimeout( jQuery.ready );
  3441 			setTimeout( jQuery.ready );
  3421 
  3442 
  3505 	return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );
  3526 	return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );
  3506 };
  3527 };
  3507 
  3528 
  3508 
  3529 
  3509 function Data() {
  3530 function Data() {
  3510 	// Support: Android < 4,
  3531 	// Support: Android<4,
  3511 	// Old WebKit does not have Object.preventExtensions/freeze method,
  3532 	// Old WebKit does not have Object.preventExtensions/freeze method,
  3512 	// return new empty object instead with no [[set]] accessor
  3533 	// return new empty object instead with no [[set]] accessor
  3513 	Object.defineProperty( this.cache = {}, 0, {
  3534 	Object.defineProperty( this.cache = {}, 0, {
  3514 		get: function() {
  3535 		get: function() {
  3515 			return {};
  3536 			return {};
  3516 		}
  3537 		}
  3517 	});
  3538 	});
  3518 
  3539 
  3519 	this.expando = jQuery.expando + Math.random();
  3540 	this.expando = jQuery.expando + Data.uid++;
  3520 }
  3541 }
  3521 
  3542 
  3522 Data.uid = 1;
  3543 Data.uid = 1;
  3523 Data.accepts = jQuery.acceptData;
  3544 Data.accepts = jQuery.acceptData;
  3524 
  3545 
  3542 			// Secure it in a non-enumerable, non-writable property
  3563 			// Secure it in a non-enumerable, non-writable property
  3543 			try {
  3564 			try {
  3544 				descriptor[ this.expando ] = { value: unlock };
  3565 				descriptor[ this.expando ] = { value: unlock };
  3545 				Object.defineProperties( owner, descriptor );
  3566 				Object.defineProperties( owner, descriptor );
  3546 
  3567 
  3547 			// Support: Android < 4
  3568 			// Support: Android<4
  3548 			// Fallback to a less secure definition
  3569 			// Fallback to a less secure definition
  3549 			} catch ( e ) {
  3570 			} catch ( e ) {
  3550 				descriptor[ this.expando ] = unlock;
  3571 				descriptor[ this.expando ] = unlock;
  3551 				jQuery.extend( owner, descriptor );
  3572 				jQuery.extend( owner, descriptor );
  3552 			}
  3573 			}
  3682 
  3703 
  3683 var data_user = new Data();
  3704 var data_user = new Data();
  3684 
  3705 
  3685 
  3706 
  3686 
  3707 
  3687 /*
  3708 //	Implementation Summary
  3688 	Implementation Summary
  3709 //
  3689 
  3710 //	1. Enforce API surface and semantic compatibility with 1.9.x branch
  3690 	1. Enforce API surface and semantic compatibility with 1.9.x branch
  3711 //	2. Improve the module's maintainability by reducing the storage
  3691 	2. Improve the module's maintainability by reducing the storage
  3712 //		paths to a single mechanism.
  3692 		paths to a single mechanism.
  3713 //	3. Use the same single mechanism to support "private" and "user" data.
  3693 	3. Use the same single mechanism to support "private" and "user" data.
  3714 //	4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
  3694 	4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
  3715 //	5. Avoid exposing implementation details on user objects (eg. expando properties)
  3695 	5. Avoid exposing implementation details on user objects (eg. expando properties)
  3716 //	6. Provide a clear path for implementation upgrade to WeakMap in 2014
  3696 	6. Provide a clear path for implementation upgrade to WeakMap in 2014
  3717 
  3697 */
       
  3698 var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
  3718 var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
  3699 	rmultiDash = /([A-Z])/g;
  3719 	rmultiDash = /([A-Z])/g;
  3700 
  3720 
  3701 function dataAttr( elem, key, data ) {
  3721 function dataAttr( elem, key, data ) {
  3702 	var name;
  3722 	var name;
  3897 			// automatically dequeued
  3917 			// automatically dequeued
  3898 			if ( type === "fx" ) {
  3918 			if ( type === "fx" ) {
  3899 				queue.unshift( "inprogress" );
  3919 				queue.unshift( "inprogress" );
  3900 			}
  3920 			}
  3901 
  3921 
  3902 			// clear up the last queue stop function
  3922 			// Clear up the last queue stop function
  3903 			delete hooks.stop;
  3923 			delete hooks.stop;
  3904 			fn.call( elem, next, hooks );
  3924 			fn.call( elem, next, hooks );
  3905 		}
  3925 		}
  3906 
  3926 
  3907 		if ( !startLength && hooks ) {
  3927 		if ( !startLength && hooks ) {
  3908 			hooks.empty.fire();
  3928 			hooks.empty.fire();
  3909 		}
  3929 		}
  3910 	},
  3930 	},
  3911 
  3931 
  3912 	// not intended for public consumption - generates a queueHooks object, or returns the current one
  3932 	// Not public - generate a queueHooks object, or return the current one
  3913 	_queueHooks: function( elem, type ) {
  3933 	_queueHooks: function( elem, type ) {
  3914 		var key = type + "queueHooks";
  3934 		var key = type + "queueHooks";
  3915 		return data_priv.get( elem, key ) || data_priv.access( elem, key, {
  3935 		return data_priv.get( elem, key ) || data_priv.access( elem, key, {
  3916 			empty: jQuery.Callbacks("once memory").add(function() {
  3936 			empty: jQuery.Callbacks("once memory").add(function() {
  3917 				data_priv.remove( elem, [ type + "queue", key ] );
  3937 				data_priv.remove( elem, [ type + "queue", key ] );
  3937 		return data === undefined ?
  3957 		return data === undefined ?
  3938 			this :
  3958 			this :
  3939 			this.each(function() {
  3959 			this.each(function() {
  3940 				var queue = jQuery.queue( this, type, data );
  3960 				var queue = jQuery.queue( this, type, data );
  3941 
  3961 
  3942 				// ensure a hooks for this queue
  3962 				// Ensure a hooks for this queue
  3943 				jQuery._queueHooks( this, type );
  3963 				jQuery._queueHooks( this, type );
  3944 
  3964 
  3945 				if ( type === "fx" && queue[0] !== "inprogress" ) {
  3965 				if ( type === "fx" && queue[0] !== "inprogress" ) {
  3946 					jQuery.dequeue( this, type );
  3966 					jQuery.dequeue( this, type );
  3947 				}
  3967 				}
  4004 (function() {
  4024 (function() {
  4005 	var fragment = document.createDocumentFragment(),
  4025 	var fragment = document.createDocumentFragment(),
  4006 		div = fragment.appendChild( document.createElement( "div" ) ),
  4026 		div = fragment.appendChild( document.createElement( "div" ) ),
  4007 		input = document.createElement( "input" );
  4027 		input = document.createElement( "input" );
  4008 
  4028 
  4009 	// #11217 - WebKit loses check when the name is after the checked attribute
  4029 	// Support: Safari<=5.1
       
  4030 	// Check state lost if the name is set (#11217)
  4010 	// Support: Windows Web Apps (WWA)
  4031 	// Support: Windows Web Apps (WWA)
  4011 	// `name` and `type` need .setAttribute for WWA
  4032 	// `name` and `type` must use .setAttribute for WWA (#14901)
  4012 	input.setAttribute( "type", "radio" );
  4033 	input.setAttribute( "type", "radio" );
  4013 	input.setAttribute( "checked", "checked" );
  4034 	input.setAttribute( "checked", "checked" );
  4014 	input.setAttribute( "name", "t" );
  4035 	input.setAttribute( "name", "t" );
  4015 
  4036 
  4016 	div.appendChild( input );
  4037 	div.appendChild( input );
  4017 
  4038 
  4018 	// Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3
  4039 	// Support: Safari<=5.1, Android<4.2
  4019 	// old WebKit doesn't clone checked state correctly in fragments
  4040 	// Older WebKit doesn't clone checked state correctly in fragments
  4020 	support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
  4041 	support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
  4021 
  4042 
       
  4043 	// Support: IE<=11+
  4022 	// Make sure textarea (and checkbox) defaultValue is properly cloned
  4044 	// Make sure textarea (and checkbox) defaultValue is properly cloned
  4023 	// Support: IE9-IE11+
       
  4024 	div.innerHTML = "<textarea>x</textarea>";
  4045 	div.innerHTML = "<textarea>x</textarea>";
  4025 	support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
  4046 	support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
  4026 })();
  4047 })();
  4027 var strundefined = typeof undefined;
  4048 var strundefined = typeof undefined;
  4028 
  4049 
  4396 			event.currentTarget = matched.elem;
  4417 			event.currentTarget = matched.elem;
  4397 
  4418 
  4398 			j = 0;
  4419 			j = 0;
  4399 			while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
  4420 			while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
  4400 
  4421 
  4401 				// Triggered event must either 1) have no namespace, or
  4422 				// Triggered event must either 1) have no namespace, or 2) have namespace(s)
  4402 				// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
  4423 				// a subset or equal to those in the bound event (both can have no namespace).
  4403 				if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
  4424 				if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
  4404 
  4425 
  4405 					event.handleObj = handleObj;
  4426 					event.handleObj = handleObj;
  4406 					event.data = handleObj.data;
  4427 					event.data = handleObj.data;
  4407 
  4428 
  4547 		// All events should have a target; Cordova deviceready doesn't
  4568 		// All events should have a target; Cordova deviceready doesn't
  4548 		if ( !event.target ) {
  4569 		if ( !event.target ) {
  4549 			event.target = document;
  4570 			event.target = document;
  4550 		}
  4571 		}
  4551 
  4572 
  4552 		// Support: Safari 6.0+, Chrome < 28
  4573 		// Support: Safari 6.0+, Chrome<28
  4553 		// Target should not be a text node (#504, #13143)
  4574 		// Target should not be a text node (#504, #13143)
  4554 		if ( event.target.nodeType === 3 ) {
  4575 		if ( event.target.nodeType === 3 ) {
  4555 			event.target = event.target.parentNode;
  4576 			event.target = event.target.parentNode;
  4556 		}
  4577 		}
  4557 
  4578 
  4652 
  4673 
  4653 		// Events bubbling up the document may have been marked as prevented
  4674 		// Events bubbling up the document may have been marked as prevented
  4654 		// by a handler lower down the tree; reflect the correct value.
  4675 		// by a handler lower down the tree; reflect the correct value.
  4655 		this.isDefaultPrevented = src.defaultPrevented ||
  4676 		this.isDefaultPrevented = src.defaultPrevented ||
  4656 				src.defaultPrevented === undefined &&
  4677 				src.defaultPrevented === undefined &&
  4657 				// Support: Android < 4.0
  4678 				// Support: Android<4.0
  4658 				src.returnValue === false ?
  4679 				src.returnValue === false ?
  4659 			returnTrue :
  4680 			returnTrue :
  4660 			returnFalse;
  4681 			returnFalse;
  4661 
  4682 
  4662 	// Event type
  4683 	// Event type
  4742 			return ret;
  4763 			return ret;
  4743 		}
  4764 		}
  4744 	};
  4765 	};
  4745 });
  4766 });
  4746 
  4767 
       
  4768 // Support: Firefox, Chrome, Safari
  4747 // Create "bubbling" focus and blur events
  4769 // Create "bubbling" focus and blur events
  4748 // Support: Firefox, Chrome, Safari
       
  4749 if ( !support.focusinBubbles ) {
  4770 if ( !support.focusinBubbles ) {
  4750 	jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
  4771 	jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
  4751 
  4772 
  4752 		// Attach a single capturing handler on the document while someone wants focusin/focusout
  4773 		// Attach a single capturing handler on the document while someone wants focusin/focusout
  4753 		var handler = function( event ) {
  4774 		var handler = function( event ) {
  4896 	rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
  4917 	rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
  4897 
  4918 
  4898 	// We have to close these tags to support XHTML (#13200)
  4919 	// We have to close these tags to support XHTML (#13200)
  4899 	wrapMap = {
  4920 	wrapMap = {
  4900 
  4921 
  4901 		// Support: IE 9
  4922 		// Support: IE9
  4902 		option: [ 1, "<select multiple='multiple'>", "</select>" ],
  4923 		option: [ 1, "<select multiple='multiple'>", "</select>" ],
  4903 
  4924 
  4904 		thead: [ 1, "<table>", "</table>" ],
  4925 		thead: [ 1, "<table>", "</table>" ],
  4905 		col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
  4926 		col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
  4906 		tr: [ 2, "<table><tbody>", "</tbody></table>" ],
  4927 		tr: [ 2, "<table><tbody>", "</tbody></table>" ],
  4907 		td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
  4928 		td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
  4908 
  4929 
  4909 		_default: [ 0, "", "" ]
  4930 		_default: [ 0, "", "" ]
  4910 	};
  4931 	};
  4911 
  4932 
  4912 // Support: IE 9
  4933 // Support: IE9
  4913 wrapMap.optgroup = wrapMap.option;
  4934 wrapMap.optgroup = wrapMap.option;
  4914 
  4935 
  4915 wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
  4936 wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
  4916 wrapMap.th = wrapMap.td;
  4937 wrapMap.th = wrapMap.td;
  4917 
  4938 
  4997 	return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
  5018 	return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
  4998 		jQuery.merge( [ context ], ret ) :
  5019 		jQuery.merge( [ context ], ret ) :
  4999 		ret;
  5020 		ret;
  5000 }
  5021 }
  5001 
  5022 
  5002 // Support: IE >= 9
  5023 // Fix IE bugs, see support tests
  5003 function fixInput( src, dest ) {
  5024 function fixInput( src, dest ) {
  5004 	var nodeName = dest.nodeName.toLowerCase();
  5025 	var nodeName = dest.nodeName.toLowerCase();
  5005 
  5026 
  5006 	// Fails to persist the checked state of a cloned checkbox or radio button.
  5027 	// Fails to persist the checked state of a cloned checkbox or radio button.
  5007 	if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
  5028 	if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
  5017 	clone: function( elem, dataAndEvents, deepDataAndEvents ) {
  5038 	clone: function( elem, dataAndEvents, deepDataAndEvents ) {
  5018 		var i, l, srcElements, destElements,
  5039 		var i, l, srcElements, destElements,
  5019 			clone = elem.cloneNode( true ),
  5040 			clone = elem.cloneNode( true ),
  5020 			inPage = jQuery.contains( elem.ownerDocument, elem );
  5041 			inPage = jQuery.contains( elem.ownerDocument, elem );
  5021 
  5042 
  5022 		// Support: IE >= 9
  5043 		// Fix IE cloning issues
  5023 		// Fix Cloning issues
       
  5024 		if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&
  5044 		if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&
  5025 				!jQuery.isXMLDoc( elem ) ) {
  5045 				!jQuery.isXMLDoc( elem ) ) {
  5026 
  5046 
  5027 			// We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
  5047 			// We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
  5028 			destElements = getAll( clone );
  5048 			destElements = getAll( clone );
  5069 
  5089 
  5070 			if ( elem || elem === 0 ) {
  5090 			if ( elem || elem === 0 ) {
  5071 
  5091 
  5072 				// Add nodes directly
  5092 				// Add nodes directly
  5073 				if ( jQuery.type( elem ) === "object" ) {
  5093 				if ( jQuery.type( elem ) === "object" ) {
  5074 					// Support: QtWebKit
  5094 					// Support: QtWebKit, PhantomJS
  5075 					// jQuery.merge because push.apply(_, arraylike) throws
  5095 					// push.apply(_, arraylike) throws on ancient WebKit
  5076 					jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
  5096 					jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
  5077 
  5097 
  5078 				// Convert non-html into a text node
  5098 				// Convert non-html into a text node
  5079 				} else if ( !rhtml.test( elem ) ) {
  5099 				} else if ( !rhtml.test( elem ) ) {
  5080 					nodes.push( context.createTextNode( elem ) );
  5100 					nodes.push( context.createTextNode( elem ) );
  5092 					j = wrap[ 0 ];
  5112 					j = wrap[ 0 ];
  5093 					while ( j-- ) {
  5113 					while ( j-- ) {
  5094 						tmp = tmp.lastChild;
  5114 						tmp = tmp.lastChild;
  5095 					}
  5115 					}
  5096 
  5116 
  5097 					// Support: QtWebKit
  5117 					// Support: QtWebKit, PhantomJS
  5098 					// jQuery.merge because push.apply(_, arraylike) throws
  5118 					// push.apply(_, arraylike) throws on ancient WebKit
  5099 					jQuery.merge( nodes, tmp.childNodes );
  5119 					jQuery.merge( nodes, tmp.childNodes );
  5100 
  5120 
  5101 					// Remember the top-level container
  5121 					// Remember the top-level container
  5102 					tmp = fragment.firstChild;
  5122 					tmp = fragment.firstChild;
  5103 
  5123 
  5104 					// Fixes #12346
  5124 					// Ensure the created nodes are orphaned (#12392)
  5105 					// Support: Webkit, IE
       
  5106 					tmp.textContent = "";
  5125 					tmp.textContent = "";
  5107 				}
  5126 				}
  5108 			}
  5127 			}
  5109 		}
  5128 		}
  5110 
  5129 
  5462 		elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),
  5481 		elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),
  5463 
  5482 
  5464 		// getDefaultComputedStyle might be reliably used only on attached element
  5483 		// getDefaultComputedStyle might be reliably used only on attached element
  5465 		display = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ?
  5484 		display = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ?
  5466 
  5485 
  5467 			// Use of this method is a temporary fix (more like optmization) until something better comes along,
  5486 			// Use of this method is a temporary fix (more like optimization) until something better comes along,
  5468 			// since it was removed from specification and supported only in FF
  5487 			// since it was removed from specification and supported only in FF
  5469 			style.display : jQuery.css( elem[ 0 ], "display" );
  5488 			style.display : jQuery.css( elem[ 0 ], "display" );
  5470 
  5489 
  5471 	// We don't have any data stored on the element,
  5490 	// We don't have any data stored on the element,
  5472 	// so use "detach" method as fast way to get rid of the element
  5491 	// so use "detach" method as fast way to get rid of the element
  5512 var rmargin = (/^margin/);
  5531 var rmargin = (/^margin/);
  5513 
  5532 
  5514 var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
  5533 var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
  5515 
  5534 
  5516 var getStyles = function( elem ) {
  5535 var getStyles = function( elem ) {
  5517 		return elem.ownerDocument.defaultView.getComputedStyle( elem, null );
  5536 		// Support: IE<=11+, Firefox<=30+ (#15098, #14150)
       
  5537 		// IE throws on elements created in popups
       
  5538 		// FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
       
  5539 		if ( elem.ownerDocument.defaultView.opener ) {
       
  5540 			return elem.ownerDocument.defaultView.getComputedStyle( elem, null );
       
  5541 		}
       
  5542 
       
  5543 		return window.getComputedStyle( elem, null );
  5518 	};
  5544 	};
  5519 
  5545 
  5520 
  5546 
  5521 
  5547 
  5522 function curCSS( elem, name, computed ) {
  5548 function curCSS( elem, name, computed ) {
  5524 		style = elem.style;
  5550 		style = elem.style;
  5525 
  5551 
  5526 	computed = computed || getStyles( elem );
  5552 	computed = computed || getStyles( elem );
  5527 
  5553 
  5528 	// Support: IE9
  5554 	// Support: IE9
  5529 	// getPropertyValue is only needed for .css('filter') in IE9, see #12537
  5555 	// getPropertyValue is only needed for .css('filter') (#12537)
  5530 	if ( computed ) {
  5556 	if ( computed ) {
  5531 		ret = computed.getPropertyValue( name ) || computed[ name ];
  5557 		ret = computed.getPropertyValue( name ) || computed[ name ];
  5532 	}
  5558 	}
  5533 
  5559 
  5534 	if ( computed ) {
  5560 	if ( computed ) {
  5570 function addGetHookIf( conditionFn, hookFn ) {
  5596 function addGetHookIf( conditionFn, hookFn ) {
  5571 	// Define the hook, we'll check on the first run if it's really needed.
  5597 	// Define the hook, we'll check on the first run if it's really needed.
  5572 	return {
  5598 	return {
  5573 		get: function() {
  5599 		get: function() {
  5574 			if ( conditionFn() ) {
  5600 			if ( conditionFn() ) {
  5575 				// Hook not needed (or it's not possible to use it due to missing dependency),
  5601 				// Hook not needed (or it's not possible to use it due
  5576 				// remove it.
  5602 				// to missing dependency), remove it.
  5577 				// Since there are no other hooks for marginRight, remove the whole object.
       
  5578 				delete this.get;
  5603 				delete this.get;
  5579 				return;
  5604 				return;
  5580 			}
  5605 			}
  5581 
  5606 
  5582 			// Hook needed; redefine it so that the support test is not executed again.
  5607 			// Hook needed; redefine it so that the support test is not executed again.
  5583 
       
  5584 			return (this.get = hookFn).apply( this, arguments );
  5608 			return (this.get = hookFn).apply( this, arguments );
  5585 		}
  5609 		}
  5586 	};
  5610 	};
  5587 }
  5611 }
  5588 
  5612 
  5595 
  5619 
  5596 	if ( !div.style ) {
  5620 	if ( !div.style ) {
  5597 		return;
  5621 		return;
  5598 	}
  5622 	}
  5599 
  5623 
       
  5624 	// Support: IE9-11+
       
  5625 	// Style of cloned element affects source element cloned (#8908)
  5600 	div.style.backgroundClip = "content-box";
  5626 	div.style.backgroundClip = "content-box";
  5601 	div.cloneNode( true ).style.backgroundClip = "";
  5627 	div.cloneNode( true ).style.backgroundClip = "";
  5602 	support.clearCloneStyle = div.style.backgroundClip === "content-box";
  5628 	support.clearCloneStyle = div.style.backgroundClip === "content-box";
  5603 
  5629 
  5604 	container.style.cssText = "border:0;width:0;height:0;top:0;left:-9999px;margin-top:1px;" +
  5630 	container.style.cssText = "border:0;width:0;height:0;top:0;left:-9999px;margin-top:1px;" +
  5627 	// Support: node.js jsdom
  5653 	// Support: node.js jsdom
  5628 	// Don't assume that getComputedStyle is a property of the global object
  5654 	// Don't assume that getComputedStyle is a property of the global object
  5629 	if ( window.getComputedStyle ) {
  5655 	if ( window.getComputedStyle ) {
  5630 		jQuery.extend( support, {
  5656 		jQuery.extend( support, {
  5631 			pixelPosition: function() {
  5657 			pixelPosition: function() {
       
  5658 
  5632 				// This test is executed only once but we still do memoizing
  5659 				// This test is executed only once but we still do memoizing
  5633 				// since we can use the boxSizingReliable pre-computing.
  5660 				// since we can use the boxSizingReliable pre-computing.
  5634 				// No need to check if the test was already performed, though.
  5661 				// No need to check if the test was already performed, though.
  5635 				computePixelPositionAndBoxSizingReliable();
  5662 				computePixelPositionAndBoxSizingReliable();
  5636 				return pixelPositionVal;
  5663 				return pixelPositionVal;
  5640 					computePixelPositionAndBoxSizingReliable();
  5667 					computePixelPositionAndBoxSizingReliable();
  5641 				}
  5668 				}
  5642 				return boxSizingReliableVal;
  5669 				return boxSizingReliableVal;
  5643 			},
  5670 			},
  5644 			reliableMarginRight: function() {
  5671 			reliableMarginRight: function() {
       
  5672 
  5645 				// Support: Android 2.3
  5673 				// Support: Android 2.3
  5646 				// Check if div with explicit width and no margin-right incorrectly
  5674 				// Check if div with explicit width and no margin-right incorrectly
  5647 				// gets computed margin-right based on width of container. (#3333)
  5675 				// gets computed margin-right based on width of container. (#3333)
  5648 				// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
  5676 				// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
  5649 				// This support function is only executed once so no memoizing is needed.
  5677 				// This support function is only executed once so no memoizing is needed.
  5661 				docElem.appendChild( container );
  5689 				docElem.appendChild( container );
  5662 
  5690 
  5663 				ret = !parseFloat( window.getComputedStyle( marginDiv, null ).marginRight );
  5691 				ret = !parseFloat( window.getComputedStyle( marginDiv, null ).marginRight );
  5664 
  5692 
  5665 				docElem.removeChild( container );
  5693 				docElem.removeChild( container );
       
  5694 				div.removeChild( marginDiv );
  5666 
  5695 
  5667 				return ret;
  5696 				return ret;
  5668 			}
  5697 			}
  5669 		});
  5698 		});
  5670 	}
  5699 	}
  5692 	return ret;
  5721 	return ret;
  5693 };
  5722 };
  5694 
  5723 
  5695 
  5724 
  5696 var
  5725 var
  5697 	// swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
  5726 	// Swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
  5698 	// see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
  5727 	// See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
  5699 	rdisplayswap = /^(none|table(?!-c[ea]).+)/,
  5728 	rdisplayswap = /^(none|table(?!-c[ea]).+)/,
  5700 	rnumsplit = new RegExp( "^(" + pnum + ")(.*)$", "i" ),
  5729 	rnumsplit = new RegExp( "^(" + pnum + ")(.*)$", "i" ),
  5701 	rrelNum = new RegExp( "^([+-])=(" + pnum + ")", "i" ),
  5730 	rrelNum = new RegExp( "^([+-])=(" + pnum + ")", "i" ),
  5702 
  5731 
  5703 	cssShow = { position: "absolute", visibility: "hidden", display: "block" },
  5732 	cssShow = { position: "absolute", visibility: "hidden", display: "block" },
  5706 		fontWeight: "400"
  5735 		fontWeight: "400"
  5707 	},
  5736 	},
  5708 
  5737 
  5709 	cssPrefixes = [ "Webkit", "O", "Moz", "ms" ];
  5738 	cssPrefixes = [ "Webkit", "O", "Moz", "ms" ];
  5710 
  5739 
  5711 // return a css property mapped to a potentially vendor prefixed property
  5740 // Return a css property mapped to a potentially vendor prefixed property
  5712 function vendorPropName( style, name ) {
  5741 function vendorPropName( style, name ) {
  5713 
  5742 
  5714 	// shortcut for names that are not vendor prefixed
  5743 	// Shortcut for names that are not vendor prefixed
  5715 	if ( name in style ) {
  5744 	if ( name in style ) {
  5716 		return name;
  5745 		return name;
  5717 	}
  5746 	}
  5718 
  5747 
  5719 	// check for vendor prefixed names
  5748 	// Check for vendor prefixed names
  5720 	var capName = name[0].toUpperCase() + name.slice(1),
  5749 	var capName = name[0].toUpperCase() + name.slice(1),
  5721 		origName = name,
  5750 		origName = name,
  5722 		i = cssPrefixes.length;
  5751 		i = cssPrefixes.length;
  5723 
  5752 
  5724 	while ( i-- ) {
  5753 	while ( i-- ) {
  5747 		name === "width" ? 1 : 0,
  5776 		name === "width" ? 1 : 0,
  5748 
  5777 
  5749 		val = 0;
  5778 		val = 0;
  5750 
  5779 
  5751 	for ( ; i < 4; i += 2 ) {
  5780 	for ( ; i < 4; i += 2 ) {
  5752 		// both box models exclude margin, so add it if we want it
  5781 		// Both box models exclude margin, so add it if we want it
  5753 		if ( extra === "margin" ) {
  5782 		if ( extra === "margin" ) {
  5754 			val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
  5783 			val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
  5755 		}
  5784 		}
  5756 
  5785 
  5757 		if ( isBorderBox ) {
  5786 		if ( isBorderBox ) {
  5758 			// border-box includes padding, so remove it if we want content
  5787 			// border-box includes padding, so remove it if we want content
  5759 			if ( extra === "content" ) {
  5788 			if ( extra === "content" ) {
  5760 				val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
  5789 				val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
  5761 			}
  5790 			}
  5762 
  5791 
  5763 			// at this point, extra isn't border nor margin, so remove border
  5792 			// At this point, extra isn't border nor margin, so remove border
  5764 			if ( extra !== "margin" ) {
  5793 			if ( extra !== "margin" ) {
  5765 				val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
  5794 				val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
  5766 			}
  5795 			}
  5767 		} else {
  5796 		} else {
  5768 			// at this point, extra isn't content, so add padding
  5797 			// At this point, extra isn't content, so add padding
  5769 			val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
  5798 			val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
  5770 
  5799 
  5771 			// at this point, extra isn't content nor padding, so add border
  5800 			// At this point, extra isn't content nor padding, so add border
  5772 			if ( extra !== "padding" ) {
  5801 			if ( extra !== "padding" ) {
  5773 				val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
  5802 				val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
  5774 			}
  5803 			}
  5775 		}
  5804 		}
  5776 	}
  5805 	}
  5784 	var valueIsBorderBox = true,
  5813 	var valueIsBorderBox = true,
  5785 		val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
  5814 		val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
  5786 		styles = getStyles( elem ),
  5815 		styles = getStyles( elem ),
  5787 		isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
  5816 		isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
  5788 
  5817 
  5789 	// some non-html elements return undefined for offsetWidth, so check for null/undefined
  5818 	// Some non-html elements return undefined for offsetWidth, so check for null/undefined
  5790 	// svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
  5819 	// svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
  5791 	// MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
  5820 	// MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
  5792 	if ( val <= 0 || val == null ) {
  5821 	if ( val <= 0 || val == null ) {
  5793 		// Fall back to computed then uncomputed css if necessary
  5822 		// Fall back to computed then uncomputed css if necessary
  5794 		val = curCSS( elem, name, styles );
  5823 		val = curCSS( elem, name, styles );
  5799 		// Computed unit is not pixels. Stop here and return.
  5828 		// Computed unit is not pixels. Stop here and return.
  5800 		if ( rnumnonpx.test(val) ) {
  5829 		if ( rnumnonpx.test(val) ) {
  5801 			return val;
  5830 			return val;
  5802 		}
  5831 		}
  5803 
  5832 
  5804 		// we need the check for style in case a browser which returns unreliable values
  5833 		// Check for style in case a browser which returns unreliable values
  5805 		// for getComputedStyle silently falls back to the reliable elem.style
  5834 		// for getComputedStyle silently falls back to the reliable elem.style
  5806 		valueIsBorderBox = isBorderBox &&
  5835 		valueIsBorderBox = isBorderBox &&
  5807 			( support.boxSizingReliable() || val === elem.style[ name ] );
  5836 			( support.boxSizingReliable() || val === elem.style[ name ] );
  5808 
  5837 
  5809 		// Normalize "", auto, and prepare for extra
  5838 		// Normalize "", auto, and prepare for extra
  5810 		val = parseFloat( val ) || 0;
  5839 		val = parseFloat( val ) || 0;
  5811 	}
  5840 	}
  5812 
  5841 
  5813 	// use the active box-sizing model to add/subtract irrelevant styles
  5842 	// Use the active box-sizing model to add/subtract irrelevant styles
  5814 	return ( val +
  5843 	return ( val +
  5815 		augmentWidthOrHeight(
  5844 		augmentWidthOrHeight(
  5816 			elem,
  5845 			elem,
  5817 			name,
  5846 			name,
  5818 			extra || ( isBorderBox ? "border" : "content" ),
  5847 			extra || ( isBorderBox ? "border" : "content" ),
  5872 
  5901 
  5873 	return elements;
  5902 	return elements;
  5874 }
  5903 }
  5875 
  5904 
  5876 jQuery.extend({
  5905 jQuery.extend({
       
  5906 
  5877 	// Add in style property hooks for overriding the default
  5907 	// Add in style property hooks for overriding the default
  5878 	// behavior of getting and setting a style property
  5908 	// behavior of getting and setting a style property
  5879 	cssHooks: {
  5909 	cssHooks: {
  5880 		opacity: {
  5910 		opacity: {
  5881 			get: function( elem, computed ) {
  5911 			get: function( elem, computed ) {
  5882 				if ( computed ) {
  5912 				if ( computed ) {
       
  5913 
  5883 					// We should always get a number back from opacity
  5914 					// We should always get a number back from opacity
  5884 					var ret = curCSS( elem, "opacity" );
  5915 					var ret = curCSS( elem, "opacity" );
  5885 					return ret === "" ? "1" : ret;
  5916 					return ret === "" ? "1" : ret;
  5886 				}
  5917 				}
  5887 			}
  5918 			}
  5905 	},
  5936 	},
  5906 
  5937 
  5907 	// Add in properties whose names you wish to fix before
  5938 	// Add in properties whose names you wish to fix before
  5908 	// setting or getting the value
  5939 	// setting or getting the value
  5909 	cssProps: {
  5940 	cssProps: {
  5910 		// normalize float css property
       
  5911 		"float": "cssFloat"
  5941 		"float": "cssFloat"
  5912 	},
  5942 	},
  5913 
  5943 
  5914 	// Get and set the style property on a DOM Node
  5944 	// Get and set the style property on a DOM Node
  5915 	style: function( elem, name, value, extra ) {
  5945 	style: function( elem, name, value, extra ) {
       
  5946 
  5916 		// Don't set styles on text and comment nodes
  5947 		// Don't set styles on text and comment nodes
  5917 		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
  5948 		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
  5918 			return;
  5949 			return;
  5919 		}
  5950 		}
  5920 
  5951 
  5923 			origName = jQuery.camelCase( name ),
  5954 			origName = jQuery.camelCase( name ),
  5924 			style = elem.style;
  5955 			style = elem.style;
  5925 
  5956 
  5926 		name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
  5957 		name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
  5927 
  5958 
  5928 		// gets hook for the prefixed version
  5959 		// Gets hook for the prefixed version, then unprefixed version
  5929 		// followed by the unprefixed version
       
  5930 		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
  5960 		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
  5931 
  5961 
  5932 		// Check if we're setting a value
  5962 		// Check if we're setting a value
  5933 		if ( value !== undefined ) {
  5963 		if ( value !== undefined ) {
  5934 			type = typeof value;
  5964 			type = typeof value;
  5935 
  5965 
  5936 			// convert relative number strings (+= or -=) to relative numbers. #7345
  5966 			// Convert "+=" or "-=" to relative numbers (#7345)
  5937 			if ( type === "string" && (ret = rrelNum.exec( value )) ) {
  5967 			if ( type === "string" && (ret = rrelNum.exec( value )) ) {
  5938 				value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
  5968 				value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
  5939 				// Fixes bug #9237
  5969 				// Fixes bug #9237
  5940 				type = "number";
  5970 				type = "number";
  5941 			}
  5971 			}
  5942 
  5972 
  5943 			// Make sure that null and NaN values aren't set. See: #7116
  5973 			// Make sure that null and NaN values aren't set (#7116)
  5944 			if ( value == null || value !== value ) {
  5974 			if ( value == null || value !== value ) {
  5945 				return;
  5975 				return;
  5946 			}
  5976 			}
  5947 
  5977 
  5948 			// If a number was passed in, add 'px' to the (except for certain CSS properties)
  5978 			// If a number, add 'px' to the (except for certain CSS properties)
  5949 			if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
  5979 			if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
  5950 				value += "px";
  5980 				value += "px";
  5951 			}
  5981 			}
  5952 
  5982 
  5953 			// Fixes #8908, it can be done more correctly by specifying setters in cssHooks,
  5983 			// Support: IE9-11+
  5954 			// but it would mean to define eight (for every problematic property) identical functions
  5984 			// background-* props affect original clone's values
  5955 			if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) {
  5985 			if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) {
  5956 				style[ name ] = "inherit";
  5986 				style[ name ] = "inherit";
  5957 			}
  5987 			}
  5958 
  5988 
  5959 			// If a hook was provided, use that value, otherwise just set the specified value
  5989 			// If a hook was provided, use that value, otherwise just set the specified value
  5977 			origName = jQuery.camelCase( name );
  6007 			origName = jQuery.camelCase( name );
  5978 
  6008 
  5979 		// Make sure that we're working with the right name
  6009 		// Make sure that we're working with the right name
  5980 		name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
  6010 		name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
  5981 
  6011 
  5982 		// gets hook for the prefixed version
  6012 		// Try prefixed name followed by the unprefixed name
  5983 		// followed by the unprefixed version
       
  5984 		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
  6013 		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
  5985 
  6014 
  5986 		// If a hook was provided get the computed value from there
  6015 		// If a hook was provided get the computed value from there
  5987 		if ( hooks && "get" in hooks ) {
  6016 		if ( hooks && "get" in hooks ) {
  5988 			val = hooks.get( elem, true, extra );
  6017 			val = hooks.get( elem, true, extra );
  5991 		// Otherwise, if a way to get the computed value exists, use that
  6020 		// Otherwise, if a way to get the computed value exists, use that
  5992 		if ( val === undefined ) {
  6021 		if ( val === undefined ) {
  5993 			val = curCSS( elem, name, styles );
  6022 			val = curCSS( elem, name, styles );
  5994 		}
  6023 		}
  5995 
  6024 
  5996 		//convert "normal" to computed value
  6025 		// Convert "normal" to computed value
  5997 		if ( val === "normal" && name in cssNormalTransform ) {
  6026 		if ( val === "normal" && name in cssNormalTransform ) {
  5998 			val = cssNormalTransform[ name ];
  6027 			val = cssNormalTransform[ name ];
  5999 		}
  6028 		}
  6000 
  6029 
  6001 		// Return, converting to number if forced or a qualifier was provided and val looks numeric
  6030 		// Make numeric if forced or a qualifier was provided and val looks numeric
  6002 		if ( extra === "" || extra ) {
  6031 		if ( extra === "" || extra ) {
  6003 			num = parseFloat( val );
  6032 			num = parseFloat( val );
  6004 			return extra === true || jQuery.isNumeric( num ) ? num || 0 : val;
  6033 			return extra === true || jQuery.isNumeric( num ) ? num || 0 : val;
  6005 		}
  6034 		}
  6006 		return val;
  6035 		return val;
  6009 
  6038 
  6010 jQuery.each([ "height", "width" ], function( i, name ) {
  6039 jQuery.each([ "height", "width" ], function( i, name ) {
  6011 	jQuery.cssHooks[ name ] = {
  6040 	jQuery.cssHooks[ name ] = {
  6012 		get: function( elem, computed, extra ) {
  6041 		get: function( elem, computed, extra ) {
  6013 			if ( computed ) {
  6042 			if ( computed ) {
  6014 				// certain elements can have dimension info if we invisibly show them
  6043 
  6015 				// however, it must have a current display style that would benefit from this
  6044 				// Certain elements can have dimension info if we invisibly show them
       
  6045 				// but it must have a current display style that would benefit
  6016 				return rdisplayswap.test( jQuery.css( elem, "display" ) ) && elem.offsetWidth === 0 ?
  6046 				return rdisplayswap.test( jQuery.css( elem, "display" ) ) && elem.offsetWidth === 0 ?
  6017 					jQuery.swap( elem, cssShow, function() {
  6047 					jQuery.swap( elem, cssShow, function() {
  6018 						return getWidthOrHeight( elem, name, extra );
  6048 						return getWidthOrHeight( elem, name, extra );
  6019 					}) :
  6049 					}) :
  6020 					getWidthOrHeight( elem, name, extra );
  6050 					getWidthOrHeight( elem, name, extra );
  6038 
  6068 
  6039 // Support: Android 2.3
  6069 // Support: Android 2.3
  6040 jQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,
  6070 jQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,
  6041 	function( elem, computed ) {
  6071 	function( elem, computed ) {
  6042 		if ( computed ) {
  6072 		if ( computed ) {
  6043 			// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
       
  6044 			// Work around by temporarily setting element display to inline-block
       
  6045 			return jQuery.swap( elem, { "display": "inline-block" },
  6073 			return jQuery.swap( elem, { "display": "inline-block" },
  6046 				curCSS, [ elem, "marginRight" ] );
  6074 				curCSS, [ elem, "marginRight" ] );
  6047 		}
  6075 		}
  6048 	}
  6076 	}
  6049 );
  6077 );
  6057 	jQuery.cssHooks[ prefix + suffix ] = {
  6085 	jQuery.cssHooks[ prefix + suffix ] = {
  6058 		expand: function( value ) {
  6086 		expand: function( value ) {
  6059 			var i = 0,
  6087 			var i = 0,
  6060 				expanded = {},
  6088 				expanded = {},
  6061 
  6089 
  6062 				// assumes a single number if not a string
  6090 				// Assumes a single number if not a string
  6063 				parts = typeof value === "string" ? value.split(" ") : [ value ];
  6091 				parts = typeof value === "string" ? value.split(" ") : [ value ];
  6064 
  6092 
  6065 			for ( ; i < 4; i++ ) {
  6093 			for ( ; i < 4; i++ ) {
  6066 				expanded[ prefix + cssExpand[ i ] + suffix ] =
  6094 				expanded[ prefix + cssExpand[ i ] + suffix ] =
  6067 					parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
  6095 					parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
  6180 			if ( tween.elem[ tween.prop ] != null &&
  6208 			if ( tween.elem[ tween.prop ] != null &&
  6181 				(!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
  6209 				(!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
  6182 				return tween.elem[ tween.prop ];
  6210 				return tween.elem[ tween.prop ];
  6183 			}
  6211 			}
  6184 
  6212 
  6185 			// passing an empty string as a 3rd parameter to .css will automatically
  6213 			// Passing an empty string as a 3rd parameter to .css will automatically
  6186 			// attempt a parseFloat and fallback to a string if the parse fails
  6214 			// attempt a parseFloat and fallback to a string if the parse fails.
  6187 			// so, simple values such as "10px" are parsed to Float.
  6215 			// Simple values such as "10px" are parsed to Float;
  6188 			// complex values such as "rotate(1rad)" are returned as is.
  6216 			// complex values such as "rotate(1rad)" are returned as-is.
  6189 			result = jQuery.css( tween.elem, tween.prop, "" );
  6217 			result = jQuery.css( tween.elem, tween.prop, "" );
  6190 			// Empty strings, null, undefined and "auto" are converted to 0.
  6218 			// Empty strings, null, undefined and "auto" are converted to 0.
  6191 			return !result || result === "auto" ? 0 : result;
  6219 			return !result || result === "auto" ? 0 : result;
  6192 		},
  6220 		},
  6193 		set: function( tween ) {
  6221 		set: function( tween ) {
  6194 			// use step hook for back compat - use cssHook if its there - use .style if its
  6222 			// Use step hook for back compat.
  6195 			// available and use plain properties where available
  6223 			// Use cssHook if its there.
       
  6224 			// Use .style if available and use plain properties where available.
  6196 			if ( jQuery.fx.step[ tween.prop ] ) {
  6225 			if ( jQuery.fx.step[ tween.prop ] ) {
  6197 				jQuery.fx.step[ tween.prop ]( tween );
  6226 				jQuery.fx.step[ tween.prop ]( tween );
  6198 			} else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
  6227 			} else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
  6199 				jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
  6228 				jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
  6200 			} else {
  6229 			} else {
  6204 	}
  6233 	}
  6205 };
  6234 };
  6206 
  6235 
  6207 // Support: IE9
  6236 // Support: IE9
  6208 // Panic based approach to setting things on disconnected nodes
  6237 // Panic based approach to setting things on disconnected nodes
  6209 
       
  6210 Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
  6238 Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
  6211 	set: function( tween ) {
  6239 	set: function( tween ) {
  6212 		if ( tween.elem.nodeType && tween.elem.parentNode ) {
  6240 		if ( tween.elem.nodeType && tween.elem.parentNode ) {
  6213 			tween.elem[ tween.prop ] = tween.now;
  6241 			tween.elem[ tween.prop ] = tween.now;
  6214 		}
  6242 		}
  6260 
  6288 
  6261 				// Iteratively approximate from a nonzero starting point
  6289 				// Iteratively approximate from a nonzero starting point
  6262 				start = +target || 1;
  6290 				start = +target || 1;
  6263 
  6291 
  6264 				do {
  6292 				do {
  6265 					// If previous iteration zeroed out, double until we get *something*
  6293 					// If previous iteration zeroed out, double until we get *something*.
  6266 					// Use a string for doubling factor so we don't accidentally see scale as unchanged below
  6294 					// Use string for doubling so we don't accidentally see scale as unchanged below
  6267 					scale = scale || ".5";
  6295 					scale = scale || ".5";
  6268 
  6296 
  6269 					// Adjust and apply
  6297 					// Adjust and apply
  6270 					start = start / scale;
  6298 					start = start / scale;
  6271 					jQuery.style( tween.elem, prop, start + unit );
  6299 					jQuery.style( tween.elem, prop, start + unit );
  6272 
  6300 
  6273 				// Update scale, tolerating zero or NaN from tween.cur()
  6301 				// Update scale, tolerating zero or NaN from tween.cur(),
  6274 				// And breaking the loop if scale is unchanged or perfect, or if we've just had enough
  6302 				// break the loop if scale is unchanged or perfect, or if we've just had enough
  6275 				} while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
  6303 				} while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
  6276 			}
  6304 			}
  6277 
  6305 
  6278 			// Update tween properties
  6306 			// Update tween properties
  6279 			if ( parts ) {
  6307 			if ( parts ) {
  6301 function genFx( type, includeWidth ) {
  6329 function genFx( type, includeWidth ) {
  6302 	var which,
  6330 	var which,
  6303 		i = 0,
  6331 		i = 0,
  6304 		attrs = { height: type };
  6332 		attrs = { height: type };
  6305 
  6333 
  6306 	// if we include width, step value is 1 to do all cssExpand values,
  6334 	// If we include width, step value is 1 to do all cssExpand values,
  6307 	// if we don't include width, step value is 2 to skip over Left and Right
  6335 	// otherwise step value is 2 to skip over Left and Right
  6308 	includeWidth = includeWidth ? 1 : 0;
  6336 	includeWidth = includeWidth ? 1 : 0;
  6309 	for ( ; i < 4 ; i += 2 - includeWidth ) {
  6337 	for ( ; i < 4 ; i += 2 - includeWidth ) {
  6310 		which = cssExpand[ i ];
  6338 		which = cssExpand[ i ];
  6311 		attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
  6339 		attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
  6312 	}
  6340 	}
  6324 		index = 0,
  6352 		index = 0,
  6325 		length = collection.length;
  6353 		length = collection.length;
  6326 	for ( ; index < length; index++ ) {
  6354 	for ( ; index < length; index++ ) {
  6327 		if ( (tween = collection[ index ].call( animation, prop, value )) ) {
  6355 		if ( (tween = collection[ index ].call( animation, prop, value )) ) {
  6328 
  6356 
  6329 			// we're done with this property
  6357 			// We're done with this property
  6330 			return tween;
  6358 			return tween;
  6331 		}
  6359 		}
  6332 	}
  6360 	}
  6333 }
  6361 }
  6334 
  6362 
  6339 		orig = {},
  6367 		orig = {},
  6340 		style = elem.style,
  6368 		style = elem.style,
  6341 		hidden = elem.nodeType && isHidden( elem ),
  6369 		hidden = elem.nodeType && isHidden( elem ),
  6342 		dataShow = data_priv.get( elem, "fxshow" );
  6370 		dataShow = data_priv.get( elem, "fxshow" );
  6343 
  6371 
  6344 	// handle queue: false promises
  6372 	// Handle queue: false promises
  6345 	if ( !opts.queue ) {
  6373 	if ( !opts.queue ) {
  6346 		hooks = jQuery._queueHooks( elem, "fx" );
  6374 		hooks = jQuery._queueHooks( elem, "fx" );
  6347 		if ( hooks.unqueued == null ) {
  6375 		if ( hooks.unqueued == null ) {
  6348 			hooks.unqueued = 0;
  6376 			hooks.unqueued = 0;
  6349 			oldfire = hooks.empty.fire;
  6377 			oldfire = hooks.empty.fire;
  6354 			};
  6382 			};
  6355 		}
  6383 		}
  6356 		hooks.unqueued++;
  6384 		hooks.unqueued++;
  6357 
  6385 
  6358 		anim.always(function() {
  6386 		anim.always(function() {
  6359 			// doing this makes sure that the complete handler will be called
  6387 			// Ensure the complete handler is called before this completes
  6360 			// before this completes
       
  6361 			anim.always(function() {
  6388 			anim.always(function() {
  6362 				hooks.unqueued--;
  6389 				hooks.unqueued--;
  6363 				if ( !jQuery.queue( elem, "fx" ).length ) {
  6390 				if ( !jQuery.queue( elem, "fx" ).length ) {
  6364 					hooks.empty.fire();
  6391 					hooks.empty.fire();
  6365 				}
  6392 				}
  6366 			});
  6393 			});
  6367 		});
  6394 		});
  6368 	}
  6395 	}
  6369 
  6396 
  6370 	// height/width overflow pass
  6397 	// Height/width overflow pass
  6371 	if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
  6398 	if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
  6372 		// Make sure that nothing sneaks out
  6399 		// Make sure that nothing sneaks out
  6373 		// Record all 3 overflow attributes because IE9-10 do not
  6400 		// Record all 3 overflow attributes because IE9-10 do not
  6374 		// change the overflow attribute when overflowX and
  6401 		// change the overflow attribute when overflowX and
  6375 		// overflowY are set to the same value
  6402 		// overflowY are set to the same value
  6427 			}
  6454 			}
  6428 		} else {
  6455 		} else {
  6429 			dataShow = data_priv.access( elem, "fxshow", {} );
  6456 			dataShow = data_priv.access( elem, "fxshow", {} );
  6430 		}
  6457 		}
  6431 
  6458 
  6432 		// store state if its toggle - enables .stop().toggle() to "reverse"
  6459 		// Store state if its toggle - enables .stop().toggle() to "reverse"
  6433 		if ( toggle ) {
  6460 		if ( toggle ) {
  6434 			dataShow.hidden = !hidden;
  6461 			dataShow.hidden = !hidden;
  6435 		}
  6462 		}
  6436 		if ( hidden ) {
  6463 		if ( hidden ) {
  6437 			jQuery( elem ).show();
  6464 			jQuery( elem ).show();
  6487 		hooks = jQuery.cssHooks[ name ];
  6514 		hooks = jQuery.cssHooks[ name ];
  6488 		if ( hooks && "expand" in hooks ) {
  6515 		if ( hooks && "expand" in hooks ) {
  6489 			value = hooks.expand( value );
  6516 			value = hooks.expand( value );
  6490 			delete props[ name ];
  6517 			delete props[ name ];
  6491 
  6518 
  6492 			// not quite $.extend, this wont overwrite keys already present.
  6519 			// Not quite $.extend, this won't overwrite existing keys.
  6493 			// also - reusing 'index' from above because we have the correct "name"
  6520 			// Reusing 'index' because we have the correct "name"
  6494 			for ( index in value ) {
  6521 			for ( index in value ) {
  6495 				if ( !( index in props ) ) {
  6522 				if ( !( index in props ) ) {
  6496 					props[ index ] = value[ index ];
  6523 					props[ index ] = value[ index ];
  6497 					specialEasing[ index ] = easing;
  6524 					specialEasing[ index ] = easing;
  6498 				}
  6525 				}
  6507 	var result,
  6534 	var result,
  6508 		stopped,
  6535 		stopped,
  6509 		index = 0,
  6536 		index = 0,
  6510 		length = animationPrefilters.length,
  6537 		length = animationPrefilters.length,
  6511 		deferred = jQuery.Deferred().always( function() {
  6538 		deferred = jQuery.Deferred().always( function() {
  6512 			// don't match elem in the :animated selector
  6539 			// Don't match elem in the :animated selector
  6513 			delete tick.elem;
  6540 			delete tick.elem;
  6514 		}),
  6541 		}),
  6515 		tick = function() {
  6542 		tick = function() {
  6516 			if ( stopped ) {
  6543 			if ( stopped ) {
  6517 				return false;
  6544 				return false;
  6518 			}
  6545 			}
  6519 			var currentTime = fxNow || createFxNow(),
  6546 			var currentTime = fxNow || createFxNow(),
  6520 				remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
  6547 				remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
  6521 				// archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
  6548 				// Support: Android 2.3
       
  6549 				// Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)
  6522 				temp = remaining / animation.duration || 0,
  6550 				temp = remaining / animation.duration || 0,
  6523 				percent = 1 - temp,
  6551 				percent = 1 - temp,
  6524 				index = 0,
  6552 				index = 0,
  6525 				length = animation.tweens.length;
  6553 				length = animation.tweens.length;
  6526 
  6554 
  6552 				animation.tweens.push( tween );
  6580 				animation.tweens.push( tween );
  6553 				return tween;
  6581 				return tween;
  6554 			},
  6582 			},
  6555 			stop: function( gotoEnd ) {
  6583 			stop: function( gotoEnd ) {
  6556 				var index = 0,
  6584 				var index = 0,
  6557 					// if we are going to the end, we want to run all the tweens
  6585 					// If we are going to the end, we want to run all the tweens
  6558 					// otherwise we skip this part
  6586 					// otherwise we skip this part
  6559 					length = gotoEnd ? animation.tweens.length : 0;
  6587 					length = gotoEnd ? animation.tweens.length : 0;
  6560 				if ( stopped ) {
  6588 				if ( stopped ) {
  6561 					return this;
  6589 					return this;
  6562 				}
  6590 				}
  6563 				stopped = true;
  6591 				stopped = true;
  6564 				for ( ; index < length ; index++ ) {
  6592 				for ( ; index < length ; index++ ) {
  6565 					animation.tweens[ index ].run( 1 );
  6593 					animation.tweens[ index ].run( 1 );
  6566 				}
  6594 				}
  6567 
  6595 
  6568 				// resolve when we played the last frame
  6596 				// Resolve when we played the last frame; otherwise, reject
  6569 				// otherwise, reject
       
  6570 				if ( gotoEnd ) {
  6597 				if ( gotoEnd ) {
  6571 					deferred.resolveWith( elem, [ animation, gotoEnd ] );
  6598 					deferred.resolveWith( elem, [ animation, gotoEnd ] );
  6572 				} else {
  6599 				} else {
  6573 					deferred.rejectWith( elem, [ animation, gotoEnd ] );
  6600 					deferred.rejectWith( elem, [ animation, gotoEnd ] );
  6574 				}
  6601 				}
  6646 	};
  6673 	};
  6647 
  6674 
  6648 	opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
  6675 	opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
  6649 		opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
  6676 		opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
  6650 
  6677 
  6651 	// normalize opt.queue - true/undefined/null -> "fx"
  6678 	// Normalize opt.queue - true/undefined/null -> "fx"
  6652 	if ( opt.queue == null || opt.queue === true ) {
  6679 	if ( opt.queue == null || opt.queue === true ) {
  6653 		opt.queue = "fx";
  6680 		opt.queue = "fx";
  6654 	}
  6681 	}
  6655 
  6682 
  6656 	// Queueing
  6683 	// Queueing
  6670 };
  6697 };
  6671 
  6698 
  6672 jQuery.fn.extend({
  6699 jQuery.fn.extend({
  6673 	fadeTo: function( speed, to, easing, callback ) {
  6700 	fadeTo: function( speed, to, easing, callback ) {
  6674 
  6701 
  6675 		// show any hidden elements after setting opacity to 0
  6702 		// Show any hidden elements after setting opacity to 0
  6676 		return this.filter( isHidden ).css( "opacity", 0 ).show()
  6703 		return this.filter( isHidden ).css( "opacity", 0 ).show()
  6677 
  6704 
  6678 			// animate to the value specified
  6705 			// Animate to the value specified
  6679 			.end().animate({ opacity: to }, speed, easing, callback );
  6706 			.end().animate({ opacity: to }, speed, easing, callback );
  6680 	},
  6707 	},
  6681 	animate: function( prop, speed, easing, callback ) {
  6708 	animate: function( prop, speed, easing, callback ) {
  6682 		var empty = jQuery.isEmptyObject( prop ),
  6709 		var empty = jQuery.isEmptyObject( prop ),
  6683 			optall = jQuery.speed( speed, easing, callback ),
  6710 			optall = jQuery.speed( speed, easing, callback ),
  6736 					dequeue = false;
  6763 					dequeue = false;
  6737 					timers.splice( index, 1 );
  6764 					timers.splice( index, 1 );
  6738 				}
  6765 				}
  6739 			}
  6766 			}
  6740 
  6767 
  6741 			// start the next in the queue if the last step wasn't forced
  6768 			// Start the next in the queue if the last step wasn't forced.
  6742 			// timers currently will call their complete callbacks, which will dequeue
  6769 			// Timers currently will call their complete callbacks, which
  6743 			// but only if they were gotoEnd
  6770 			// will dequeue but only if they were gotoEnd.
  6744 			if ( dequeue || !gotoEnd ) {
  6771 			if ( dequeue || !gotoEnd ) {
  6745 				jQuery.dequeue( this, type );
  6772 				jQuery.dequeue( this, type );
  6746 			}
  6773 			}
  6747 		});
  6774 		});
  6748 	},
  6775 	},
  6756 				queue = data[ type + "queue" ],
  6783 				queue = data[ type + "queue" ],
  6757 				hooks = data[ type + "queueHooks" ],
  6784 				hooks = data[ type + "queueHooks" ],
  6758 				timers = jQuery.timers,
  6785 				timers = jQuery.timers,
  6759 				length = queue ? queue.length : 0;
  6786 				length = queue ? queue.length : 0;
  6760 
  6787 
  6761 			// enable finishing flag on private data
  6788 			// Enable finishing flag on private data
  6762 			data.finish = true;
  6789 			data.finish = true;
  6763 
  6790 
  6764 			// empty the queue first
  6791 			// Empty the queue first
  6765 			jQuery.queue( this, type, [] );
  6792 			jQuery.queue( this, type, [] );
  6766 
  6793 
  6767 			if ( hooks && hooks.stop ) {
  6794 			if ( hooks && hooks.stop ) {
  6768 				hooks.stop.call( this, true );
  6795 				hooks.stop.call( this, true );
  6769 			}
  6796 			}
  6770 
  6797 
  6771 			// look for any active animations, and finish them
  6798 			// Look for any active animations, and finish them
  6772 			for ( index = timers.length; index--; ) {
  6799 			for ( index = timers.length; index--; ) {
  6773 				if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
  6800 				if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
  6774 					timers[ index ].anim.stop( true );
  6801 					timers[ index ].anim.stop( true );
  6775 					timers.splice( index, 1 );
  6802 					timers.splice( index, 1 );
  6776 				}
  6803 				}
  6777 			}
  6804 			}
  6778 
  6805 
  6779 			// look for any animations in the old queue and finish them
  6806 			// Look for any animations in the old queue and finish them
  6780 			for ( index = 0; index < length; index++ ) {
  6807 			for ( index = 0; index < length; index++ ) {
  6781 				if ( queue[ index ] && queue[ index ].finish ) {
  6808 				if ( queue[ index ] && queue[ index ].finish ) {
  6782 					queue[ index ].finish.call( this );
  6809 					queue[ index ].finish.call( this );
  6783 				}
  6810 				}
  6784 			}
  6811 			}
  6785 
  6812 
  6786 			// turn off finishing flag
  6813 			// Turn off finishing flag
  6787 			delete data.finish;
  6814 			delete data.finish;
  6788 		});
  6815 		});
  6789 	}
  6816 	}
  6790 });
  6817 });
  6791 
  6818 
  6884 		select = document.createElement( "select" ),
  6911 		select = document.createElement( "select" ),
  6885 		opt = select.appendChild( document.createElement( "option" ) );
  6912 		opt = select.appendChild( document.createElement( "option" ) );
  6886 
  6913 
  6887 	input.type = "checkbox";
  6914 	input.type = "checkbox";
  6888 
  6915 
  6889 	// Support: iOS 5.1, Android 4.x, Android 2.3
  6916 	// Support: iOS<=5.1, Android<=4.2+
  6890 	// Check the default checkbox/radio value ("" on old WebKit; "on" elsewhere)
  6917 	// Default value for a checkbox should be "on"
  6891 	support.checkOn = input.value !== "";
  6918 	support.checkOn = input.value !== "";
  6892 
  6919 
  6893 	// Must access the parent to make an option select properly
  6920 	// Support: IE<=11+
  6894 	// Support: IE9, IE10
  6921 	// Must access selectedIndex to make default options select
  6895 	support.optSelected = opt.selected;
  6922 	support.optSelected = opt.selected;
  6896 
  6923 
  6897 	// Make sure that the options inside disabled selects aren't marked as disabled
  6924 	// Support: Android<=2.3
  6898 	// (WebKit marks them as disabled)
  6925 	// Options inside disabled selects are incorrectly marked as disabled
  6899 	select.disabled = true;
  6926 	select.disabled = true;
  6900 	support.optDisabled = !opt.disabled;
  6927 	support.optDisabled = !opt.disabled;
  6901 
  6928 
  6902 	// Check if an input maintains its value after becoming a radio
  6929 	// Support: IE<=11+
  6903 	// Support: IE9, IE10
  6930 	// An input loses its value after becoming a radio
  6904 	input = document.createElement( "input" );
  6931 	input = document.createElement( "input" );
  6905 	input.value = "t";
  6932 	input.value = "t";
  6906 	input.type = "radio";
  6933 	input.type = "radio";
  6907 	support.radioValue = input.value === "t";
  6934 	support.radioValue = input.value === "t";
  6908 })();
  6935 })();
  6995 	attrHooks: {
  7022 	attrHooks: {
  6996 		type: {
  7023 		type: {
  6997 			set: function( elem, value ) {
  7024 			set: function( elem, value ) {
  6998 				if ( !support.radioValue && value === "radio" &&
  7025 				if ( !support.radioValue && value === "radio" &&
  6999 					jQuery.nodeName( elem, "input" ) ) {
  7026 					jQuery.nodeName( elem, "input" ) ) {
  7000 					// Setting the type on a radio button after the value resets the value in IE6-9
       
  7001 					// Reset value to default in case type is set after value during creation
       
  7002 					var val = elem.value;
  7027 					var val = elem.value;
  7003 					elem.setAttribute( "type", value );
  7028 					elem.setAttribute( "type", value );
  7004 					if ( val ) {
  7029 					if ( val ) {
  7005 						elem.value = val;
  7030 						elem.value = val;
  7006 					}
  7031 					}
  7066 
  7091 
  7067 	prop: function( elem, name, value ) {
  7092 	prop: function( elem, name, value ) {
  7068 		var ret, hooks, notxml,
  7093 		var ret, hooks, notxml,
  7069 			nType = elem.nodeType;
  7094 			nType = elem.nodeType;
  7070 
  7095 
  7071 		// don't get/set properties on text, comment and attribute nodes
  7096 		// Don't get/set properties on text, comment and attribute nodes
  7072 		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
  7097 		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
  7073 			return;
  7098 			return;
  7074 		}
  7099 		}
  7075 
  7100 
  7076 		notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
  7101 		notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
  7102 			}
  7127 			}
  7103 		}
  7128 		}
  7104 	}
  7129 	}
  7105 });
  7130 });
  7106 
  7131 
  7107 // Support: IE9+
       
  7108 // Selectedness for an option in an optgroup can be inaccurate
       
  7109 if ( !support.optSelected ) {
  7132 if ( !support.optSelected ) {
  7110 	jQuery.propHooks.selected = {
  7133 	jQuery.propHooks.selected = {
  7111 		get: function( elem ) {
  7134 		get: function( elem ) {
  7112 			var parent = elem.parentNode;
  7135 			var parent = elem.parentNode;
  7113 			if ( parent && parent.parentNode ) {
  7136 			if ( parent && parent.parentNode ) {
  7211 						while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
  7234 						while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
  7212 							cur = cur.replace( " " + clazz + " ", " " );
  7235 							cur = cur.replace( " " + clazz + " ", " " );
  7213 						}
  7236 						}
  7214 					}
  7237 					}
  7215 
  7238 
  7216 					// only assign if different to avoid unneeded rendering.
  7239 					// Only assign if different to avoid unneeded rendering.
  7217 					finalValue = value ? jQuery.trim( cur ) : "";
  7240 					finalValue = value ? jQuery.trim( cur ) : "";
  7218 					if ( elem.className !== finalValue ) {
  7241 					if ( elem.className !== finalValue ) {
  7219 						elem.className = finalValue;
  7242 						elem.className = finalValue;
  7220 					}
  7243 					}
  7221 				}
  7244 				}
  7238 			});
  7261 			});
  7239 		}
  7262 		}
  7240 
  7263 
  7241 		return this.each(function() {
  7264 		return this.each(function() {
  7242 			if ( type === "string" ) {
  7265 			if ( type === "string" ) {
  7243 				// toggle individual class names
  7266 				// Toggle individual class names
  7244 				var className,
  7267 				var className,
  7245 					i = 0,
  7268 					i = 0,
  7246 					self = jQuery( this ),
  7269 					self = jQuery( this ),
  7247 					classNames = value.match( rnotwhite ) || [];
  7270 					classNames = value.match( rnotwhite ) || [];
  7248 
  7271 
  7249 				while ( (className = classNames[ i++ ]) ) {
  7272 				while ( (className = classNames[ i++ ]) ) {
  7250 					// check each className given, space separated list
  7273 					// Check each className given, space separated list
  7251 					if ( self.hasClass( className ) ) {
  7274 					if ( self.hasClass( className ) ) {
  7252 						self.removeClass( className );
  7275 						self.removeClass( className );
  7253 					} else {
  7276 					} else {
  7254 						self.addClass( className );
  7277 						self.addClass( className );
  7255 					}
  7278 					}
  7260 				if ( this.className ) {
  7283 				if ( this.className ) {
  7261 					// store className if set
  7284 					// store className if set
  7262 					data_priv.set( this, "__className__", this.className );
  7285 					data_priv.set( this, "__className__", this.className );
  7263 				}
  7286 				}
  7264 
  7287 
  7265 				// If the element has a class name or if we're passed "false",
  7288 				// If the element has a class name or if we're passed `false`,
  7266 				// then remove the whole classname (if there was one, the above saved it).
  7289 				// then remove the whole classname (if there was one, the above saved it).
  7267 				// Otherwise bring back whatever was previously saved (if anything),
  7290 				// Otherwise bring back whatever was previously saved (if anything),
  7268 				// falling back to the empty string if nothing was stored.
  7291 				// falling back to the empty string if nothing was stored.
  7269 				this.className = this.className || value === false ? "" : data_priv.get( this, "__className__" ) || "";
  7292 				this.className = this.className || value === false ? "" : data_priv.get( this, "__className__" ) || "";
  7270 			}
  7293 			}
  7304 				}
  7327 				}
  7305 
  7328 
  7306 				ret = elem.value;
  7329 				ret = elem.value;
  7307 
  7330 
  7308 				return typeof ret === "string" ?
  7331 				return typeof ret === "string" ?
  7309 					// handle most common string cases
  7332 					// Handle most common string cases
  7310 					ret.replace(rreturn, "") :
  7333 					ret.replace(rreturn, "") :
  7311 					// handle cases where value is null/undef or number
  7334 					// Handle cases where value is null/undef or number
  7312 					ret == null ? "" : ret;
  7335 					ret == null ? "" : ret;
  7313 			}
  7336 			}
  7314 
  7337 
  7315 			return;
  7338 			return;
  7316 		}
  7339 		}
  7414 					if ( (option.selected = jQuery.inArray( option.value, values ) >= 0) ) {
  7437 					if ( (option.selected = jQuery.inArray( option.value, values ) >= 0) ) {
  7415 						optionSet = true;
  7438 						optionSet = true;
  7416 					}
  7439 					}
  7417 				}
  7440 				}
  7418 
  7441 
  7419 				// force browsers to behave consistently when non-matching value is set
  7442 				// Force browsers to behave consistently when non-matching value is set
  7420 				if ( !optionSet ) {
  7443 				if ( !optionSet ) {
  7421 					elem.selectedIndex = -1;
  7444 					elem.selectedIndex = -1;
  7422 				}
  7445 				}
  7423 				return values;
  7446 				return values;
  7424 			}
  7447 			}
  7435 			}
  7458 			}
  7436 		}
  7459 		}
  7437 	};
  7460 	};
  7438 	if ( !support.checkOn ) {
  7461 	if ( !support.checkOn ) {
  7439 		jQuery.valHooks[ this ].get = function( elem ) {
  7462 		jQuery.valHooks[ this ].get = function( elem ) {
  7440 			// Support: Webkit
       
  7441 			// "" is returned instead of "on" if a value isn't specified
       
  7442 			return elem.getAttribute("value") === null ? "on" : elem.value;
  7463 			return elem.getAttribute("value") === null ? "on" : elem.value;
  7443 		};
  7464 		};
  7444 	}
  7465 	}
  7445 });
  7466 });
  7446 
  7467 
  7518 	return xml;
  7539 	return xml;
  7519 };
  7540 };
  7520 
  7541 
  7521 
  7542 
  7522 var
  7543 var
  7523 	// Document location
       
  7524 	ajaxLocParts,
       
  7525 	ajaxLocation,
       
  7526 
       
  7527 	rhash = /#.*$/,
  7544 	rhash = /#.*$/,
  7528 	rts = /([?&])_=[^&]*/,
  7545 	rts = /([?&])_=[^&]*/,
  7529 	rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg,
  7546 	rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg,
  7530 	// #7653, #8125, #8152: local protocol detection
  7547 	// #7653, #8125, #8152: local protocol detection
  7531 	rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
  7548 	rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
  7550 	 * 3) selection will start with transport dataType and THEN go to "*" if needed
  7567 	 * 3) selection will start with transport dataType and THEN go to "*" if needed
  7551 	 */
  7568 	 */
  7552 	transports = {},
  7569 	transports = {},
  7553 
  7570 
  7554 	// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
  7571 	// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
  7555 	allTypes = "*/".concat("*");
  7572 	allTypes = "*/".concat( "*" ),
  7556 
  7573 
  7557 // #8138, IE may throw an exception when accessing
  7574 	// Document location
  7558 // a field from window.location if document.domain has been set
  7575 	ajaxLocation = window.location.href,
  7559 try {
  7576 
  7560 	ajaxLocation = location.href;
  7577 	// Segment location into parts
  7561 } catch( e ) {
  7578 	ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
  7562 	// Use the href attribute of an A element
       
  7563 	// since IE will modify it given document.location
       
  7564 	ajaxLocation = document.createElement( "a" );
       
  7565 	ajaxLocation.href = "";
       
  7566 	ajaxLocation = ajaxLocation.href;
       
  7567 }
       
  7568 
       
  7569 // Segment location into parts
       
  7570 ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
       
  7571 
  7579 
  7572 // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
  7580 // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
  7573 function addToPrefiltersOrTransports( structure ) {
  7581 function addToPrefiltersOrTransports( structure ) {
  7574 
  7582 
  7575 	// dataTypeExpression is optional and defaults to "*"
  7583 	// dataTypeExpression is optional and defaults to "*"
  8044 		if ( state === 2 ) {
  8052 		if ( state === 2 ) {
  8045 			return jqXHR;
  8053 			return jqXHR;
  8046 		}
  8054 		}
  8047 
  8055 
  8048 		// We can fire global events as of now if asked to
  8056 		// We can fire global events as of now if asked to
  8049 		fireGlobals = s.global;
  8057 		// Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)
       
  8058 		fireGlobals = jQuery.event && s.global;
  8050 
  8059 
  8051 		// Watch for a new set of requests
  8060 		// Watch for a new set of requests
  8052 		if ( fireGlobals && jQuery.active++ === 0 ) {
  8061 		if ( fireGlobals && jQuery.active++ === 0 ) {
  8053 			jQuery.event.trigger("ajaxStart");
  8062 			jQuery.event.trigger("ajaxStart");
  8054 		}
  8063 		}
  8117 		if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
  8126 		if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
  8118 			// Abort if not done already and return
  8127 			// Abort if not done already and return
  8119 			return jqXHR.abort();
  8128 			return jqXHR.abort();
  8120 		}
  8129 		}
  8121 
  8130 
  8122 		// aborting is no longer a cancellation
  8131 		// Aborting is no longer a cancellation
  8123 		strAbort = "abort";
  8132 		strAbort = "abort";
  8124 
  8133 
  8125 		// Install callbacks on deferreds
  8134 		// Install callbacks on deferreds
  8126 		for ( i in { success: 1, error: 1, complete: 1 } ) {
  8135 		for ( i in { success: 1, error: 1, complete: 1 } ) {
  8127 			jqXHR[ i ]( s[ i ] );
  8136 			jqXHR[ i ]( s[ i ] );
  8229 					success = response.data;
  8238 					success = response.data;
  8230 					error = response.error;
  8239 					error = response.error;
  8231 					isSuccess = !error;
  8240 					isSuccess = !error;
  8232 				}
  8241 				}
  8233 			} else {
  8242 			} else {
  8234 				// We extract error from statusText
  8243 				// Extract error from statusText and normalize for non-aborts
  8235 				// then normalize statusText and status for non-aborts
       
  8236 				error = statusText;
  8244 				error = statusText;
  8237 				if ( status || !statusText ) {
  8245 				if ( status || !statusText ) {
  8238 					statusText = "error";
  8246 					statusText = "error";
  8239 					if ( status < 0 ) {
  8247 					if ( status < 0 ) {
  8240 						status = 0;
  8248 						status = 0;
  8286 	}
  8294 	}
  8287 });
  8295 });
  8288 
  8296 
  8289 jQuery.each( [ "get", "post" ], function( i, method ) {
  8297 jQuery.each( [ "get", "post" ], function( i, method ) {
  8290 	jQuery[ method ] = function( url, data, callback, type ) {
  8298 	jQuery[ method ] = function( url, data, callback, type ) {
  8291 		// shift arguments if data argument was omitted
  8299 		// Shift arguments if data argument was omitted
  8292 		if ( jQuery.isFunction( data ) ) {
  8300 		if ( jQuery.isFunction( data ) ) {
  8293 			type = type || callback;
  8301 			type = type || callback;
  8294 			callback = data;
  8302 			callback = data;
  8295 			data = undefined;
  8303 			data = undefined;
  8296 		}
  8304 		}
  8300 			type: method,
  8308 			type: method,
  8301 			dataType: type,
  8309 			dataType: type,
  8302 			data: data,
  8310 			data: data,
  8303 			success: callback
  8311 			success: callback
  8304 		});
  8312 		});
  8305 	};
       
  8306 });
       
  8307 
       
  8308 // Attach a bunch of functions for handling common AJAX events
       
  8309 jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ) {
       
  8310 	jQuery.fn[ type ] = function( fn ) {
       
  8311 		return this.on( type, fn );
       
  8312 	};
  8313 	};
  8313 });
  8314 });
  8314 
  8315 
  8315 
  8316 
  8316 jQuery._evalUrl = function( url ) {
  8317 jQuery._evalUrl = function( url ) {
  8527 	},
  8528 	},
  8528 	xhrSupported = jQuery.ajaxSettings.xhr();
  8529 	xhrSupported = jQuery.ajaxSettings.xhr();
  8529 
  8530 
  8530 // Support: IE9
  8531 // Support: IE9
  8531 // Open requests must be manually aborted on unload (#5280)
  8532 // Open requests must be manually aborted on unload (#5280)
  8532 if ( window.ActiveXObject ) {
  8533 // See https://support.microsoft.com/kb/2856746 for more info
  8533 	jQuery( window ).on( "unload", function() {
  8534 if ( window.attachEvent ) {
       
  8535 	window.attachEvent( "onunload", function() {
  8534 		for ( var key in xhrCallbacks ) {
  8536 		for ( var key in xhrCallbacks ) {
  8535 			xhrCallbacks[ key ]();
  8537 			xhrCallbacks[ key ]();
  8536 		}
  8538 		}
  8537 	});
  8539 	});
  8538 }
  8540 }
  8881 };
  8883 };
  8882 
  8884 
  8883 
  8885 
  8884 
  8886 
  8885 
  8887 
       
  8888 // Attach a bunch of functions for handling common AJAX events
       
  8889 jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ) {
       
  8890 	jQuery.fn[ type ] = function( fn ) {
       
  8891 		return this.on( type, fn );
       
  8892 	};
       
  8893 });
       
  8894 
       
  8895 
       
  8896 
       
  8897 
  8886 jQuery.expr.filters.animated = function( elem ) {
  8898 jQuery.expr.filters.animated = function( elem ) {
  8887 	return jQuery.grep(jQuery.timers, function( fn ) {
  8899 	return jQuery.grep(jQuery.timers, function( fn ) {
  8888 		return elem === fn.elem;
  8900 		return elem === fn.elem;
  8889 	}).length;
  8901 	}).length;
  8890 };
  8902 };
  8917 		curCSSTop = jQuery.css( elem, "top" );
  8929 		curCSSTop = jQuery.css( elem, "top" );
  8918 		curCSSLeft = jQuery.css( elem, "left" );
  8930 		curCSSLeft = jQuery.css( elem, "left" );
  8919 		calculatePosition = ( position === "absolute" || position === "fixed" ) &&
  8931 		calculatePosition = ( position === "absolute" || position === "fixed" ) &&
  8920 			( curCSSTop + curCSSLeft ).indexOf("auto") > -1;
  8932 			( curCSSTop + curCSSLeft ).indexOf("auto") > -1;
  8921 
  8933 
  8922 		// Need to be able to calculate position if either top or left is auto and position is either absolute or fixed
  8934 		// Need to be able to calculate position if either
       
  8935 		// top or left is auto and position is either absolute or fixed
  8923 		if ( calculatePosition ) {
  8936 		if ( calculatePosition ) {
  8924 			curPosition = curElem.position();
  8937 			curPosition = curElem.position();
  8925 			curTop = curPosition.top;
  8938 			curTop = curPosition.top;
  8926 			curLeft = curPosition.left;
  8939 			curLeft = curPosition.left;
  8927 
  8940 
  8974 		// Make sure it's not a disconnected DOM node
  8987 		// Make sure it's not a disconnected DOM node
  8975 		if ( !jQuery.contains( docElem, elem ) ) {
  8988 		if ( !jQuery.contains( docElem, elem ) ) {
  8976 			return box;
  8989 			return box;
  8977 		}
  8990 		}
  8978 
  8991 
       
  8992 		// Support: BlackBerry 5, iOS 3 (original iPhone)
  8979 		// If we don't have gBCR, just use 0,0 rather than error
  8993 		// If we don't have gBCR, just use 0,0 rather than error
  8980 		// BlackBerry 5, iOS 3 (original iPhone)
       
  8981 		if ( typeof elem.getBoundingClientRect !== strundefined ) {
  8994 		if ( typeof elem.getBoundingClientRect !== strundefined ) {
  8982 			box = elem.getBoundingClientRect();
  8995 			box = elem.getBoundingClientRect();
  8983 		}
  8996 		}
  8984 		win = getWindow( doc );
  8997 		win = getWindow( doc );
  8985 		return {
  8998 		return {
  8997 			elem = this[ 0 ],
  9010 			elem = this[ 0 ],
  8998 			parentOffset = { top: 0, left: 0 };
  9011 			parentOffset = { top: 0, left: 0 };
  8999 
  9012 
  9000 		// Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent
  9013 		// Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent
  9001 		if ( jQuery.css( elem, "position" ) === "fixed" ) {
  9014 		if ( jQuery.css( elem, "position" ) === "fixed" ) {
  9002 			// We assume that getBoundingClientRect is available when computed position is fixed
  9015 			// Assume getBoundingClientRect is there when computed position is fixed
  9003 			offset = elem.getBoundingClientRect();
  9016 			offset = elem.getBoundingClientRect();
  9004 
  9017 
  9005 		} else {
  9018 		} else {
  9006 			// Get *real* offsetParent
  9019 			// Get *real* offsetParent
  9007 			offsetParent = this.offsetParent();
  9020 			offsetParent = this.offsetParent();
  9060 			}
  9073 			}
  9061 		}, method, val, arguments.length, null );
  9074 		}, method, val, arguments.length, null );
  9062 	};
  9075 	};
  9063 });
  9076 });
  9064 
  9077 
       
  9078 // Support: Safari<7+, Chrome<37+
  9065 // Add the top/left cssHooks using jQuery.fn.position
  9079 // Add the top/left cssHooks using jQuery.fn.position
  9066 // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
  9080 // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
  9067 // getComputedStyle returns percent when specified for top/left/bottom/right
  9081 // Blink bug: https://code.google.com/p/chromium/issues/detail?id=229280
  9068 // rather than make the css module depend on the offset module, we just check for it here
  9082 // getComputedStyle returns percent when specified for top/left/bottom/right;
       
  9083 // rather than make the css module depend on the offset module, just check for it here
  9069 jQuery.each( [ "top", "left" ], function( i, prop ) {
  9084 jQuery.each( [ "top", "left" ], function( i, prop ) {
  9070 	jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
  9085 	jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
  9071 		function( elem, computed ) {
  9086 		function( elem, computed ) {
  9072 			if ( computed ) {
  9087 			if ( computed ) {
  9073 				computed = curCSS( elem, prop );
  9088 				computed = curCSS( elem, prop );
  9074 				// if curCSS returns percentage, fallback to offset
  9089 				// If curCSS returns percentage, fallback to offset
  9075 				return rnumnonpx.test( computed ) ?
  9090 				return rnumnonpx.test( computed ) ?
  9076 					jQuery( elem ).position()[ prop ] + "px" :
  9091 					jQuery( elem ).position()[ prop ] + "px" :
  9077 					computed;
  9092 					computed;
  9078 			}
  9093 			}
  9079 		}
  9094 		}
  9082 
  9097 
  9083 
  9098 
  9084 // Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
  9099 // Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
  9085 jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
  9100 jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
  9086 	jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
  9101 	jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
  9087 		// margin is only for outerHeight, outerWidth
  9102 		// Margin is only for outerHeight, outerWidth
  9088 		jQuery.fn[ funcName ] = function( margin, value ) {
  9103 		jQuery.fn[ funcName ] = function( margin, value ) {
  9089 			var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
  9104 			var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
  9090 				extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
  9105 				extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
  9091 
  9106 
  9092 			return access( this, function( elem, type, value ) {
  9107 			return access( this, function( elem, type, value ) {
  9173 	}
  9188 	}
  9174 
  9189 
  9175 	return jQuery;
  9190 	return jQuery;
  9176 };
  9191 };
  9177 
  9192 
  9178 // Expose jQuery and $ identifiers, even in
  9193 // Expose jQuery and $ identifiers, even in AMD
  9179 // AMD (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
  9194 // (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
  9180 // and CommonJS for browser emulators (#13566)
  9195 // and CommonJS for browser emulators (#13566)
  9181 if ( typeof noGlobal === strundefined ) {
  9196 if ( typeof noGlobal === strundefined ) {
  9182 	window.jQuery = window.$ = jQuery;
  9197 	window.jQuery = window.$ = jQuery;
  9183 }
  9198 }
  9184 
  9199 
  9188 return jQuery;
  9203 return jQuery;
  9189 
  9204 
  9190 }));
  9205 }));
  9191 
  9206 
  9192 /**
  9207 /**
  9193  * @license AngularJS v1.3.0-rc.5
  9208  * @license AngularJS v1.3.8
  9194  * (c) 2010-2014 Google, Inc. http://angularjs.org
  9209  * (c) 2010-2014 Google, Inc. http://angularjs.org
  9195  * License: MIT
  9210  * License: MIT
  9196  */
  9211  */
  9197 (function(window, document, undefined) {'use strict';
  9212 (function(window, document, undefined) {'use strict';
  9198 
  9213 
  9226  * @returns {function(code:string, template:string, ...templateArgs): Error} minErr instance
  9241  * @returns {function(code:string, template:string, ...templateArgs): Error} minErr instance
  9227  */
  9242  */
  9228 
  9243 
  9229 function minErr(module, ErrorConstructor) {
  9244 function minErr(module, ErrorConstructor) {
  9230   ErrorConstructor = ErrorConstructor || Error;
  9245   ErrorConstructor = ErrorConstructor || Error;
  9231   return function () {
  9246   return function() {
  9232     var code = arguments[0],
  9247     var code = arguments[0],
  9233       prefix = '[' + (module ? module + ':' : '') + code + '] ',
  9248       prefix = '[' + (module ? module + ':' : '') + code + '] ',
  9234       template = arguments[1],
  9249       template = arguments[1],
  9235       templateArgs = arguments,
  9250       templateArgs = arguments,
  9236       stringify = function (obj) {
  9251 
  9237         if (typeof obj === 'function') {
       
  9238           return obj.toString().replace(/ \{[\s\S]*$/, '');
       
  9239         } else if (typeof obj === 'undefined') {
       
  9240           return 'undefined';
       
  9241         } else if (typeof obj !== 'string') {
       
  9242           return JSON.stringify(obj);
       
  9243         }
       
  9244         return obj;
       
  9245       },
       
  9246       message, i;
  9252       message, i;
  9247 
  9253 
  9248     message = prefix + template.replace(/\{\d+\}/g, function (match) {
  9254     message = prefix + template.replace(/\{\d+\}/g, function(match) {
  9249       var index = +match.slice(1, -1), arg;
  9255       var index = +match.slice(1, -1), arg;
  9250 
  9256 
  9251       if (index + 2 < templateArgs.length) {
  9257       if (index + 2 < templateArgs.length) {
  9252         arg = templateArgs[index + 2];
  9258         return toDebugString(templateArgs[index + 2]);
  9253         if (typeof arg === 'function') {
       
  9254           return arg.toString().replace(/ ?\{[\s\S]*$/, '');
       
  9255         } else if (typeof arg === 'undefined') {
       
  9256           return 'undefined';
       
  9257         } else if (typeof arg !== 'string') {
       
  9258           return toJson(arg);
       
  9259         }
       
  9260         return arg;
       
  9261       }
  9259       }
  9262       return match;
  9260       return match;
  9263     });
  9261     });
  9264 
  9262 
  9265     message = message + '\nhttp://errors.angularjs.org/1.3.0-rc.5/' +
  9263     message = message + '\nhttp://errors.angularjs.org/1.3.8/' +
  9266       (module ? module + '/' : '') + code;
  9264       (module ? module + '/' : '') + code;
  9267     for (i = 2; i < arguments.length; i++) {
  9265     for (i = 2; i < arguments.length; i++) {
  9268       message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' +
  9266       message = message + (i == 2 ? '?' : '&') + 'p' + (i - 2) + '=' +
  9269         encodeURIComponent(stringify(arguments[i]));
  9267         encodeURIComponent(toDebugString(arguments[i]));
  9270     }
  9268     }
  9271     return new ErrorConstructor(message);
  9269     return new ErrorConstructor(message);
  9272   };
  9270   };
  9273 }
  9271 }
  9274 
  9272 
  9315   isFunction: true,
  9313   isFunction: true,
  9316   isRegExp: true,
  9314   isRegExp: true,
  9317   isWindow: true,
  9315   isWindow: true,
  9318   isScope: true,
  9316   isScope: true,
  9319   isFile: true,
  9317   isFile: true,
       
  9318   isFormData: true,
  9320   isBlob: true,
  9319   isBlob: true,
  9321   isBoolean: true,
  9320   isBoolean: true,
  9322   isPromiseLike: true,
  9321   isPromiseLike: true,
  9323   trim: true,
  9322   trim: true,
       
  9323   escapeForRegexp: true,
  9324   isElement: true,
  9324   isElement: true,
  9325   makeMap: true,
  9325   makeMap: true,
  9326   size: true,
       
  9327   includes: true,
  9326   includes: true,
  9328   arrayRemove: true,
  9327   arrayRemove: true,
  9329   isLeafNode: true,
       
  9330   copy: true,
  9328   copy: true,
  9331   shallowCopy: true,
  9329   shallowCopy: true,
  9332   equals: true,
  9330   equals: true,
  9333   csp: true,
  9331   csp: true,
  9334   concat: true,
  9332   concat: true,
  9394  *
  9392  *
  9395  * @description Converts the specified string to lowercase.
  9393  * @description Converts the specified string to lowercase.
  9396  * @param {string} string String to be converted to lowercase.
  9394  * @param {string} string String to be converted to lowercase.
  9397  * @returns {string} Lowercased string.
  9395  * @returns {string} Lowercased string.
  9398  */
  9396  */
  9399 var lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};
  9397 var lowercase = function(string) {return isString(string) ? string.toLowerCase() : string;};
  9400 var hasOwnProperty = Object.prototype.hasOwnProperty;
  9398 var hasOwnProperty = Object.prototype.hasOwnProperty;
  9401 
  9399 
  9402 /**
  9400 /**
  9403  * @ngdoc function
  9401  * @ngdoc function
  9404  * @name angular.uppercase
  9402  * @name angular.uppercase
  9407  *
  9405  *
  9408  * @description Converts the specified string to uppercase.
  9406  * @description Converts the specified string to uppercase.
  9409  * @param {string} string String to be converted to uppercase.
  9407  * @param {string} string String to be converted to uppercase.
  9410  * @returns {string} Uppercased string.
  9408  * @returns {string} Uppercased string.
  9411  */
  9409  */
  9412 var uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};
  9410 var uppercase = function(string) {return isString(string) ? string.toUpperCase() : string;};
  9413 
  9411 
  9414 
  9412 
  9415 var manualLowercase = function(s) {
  9413 var manualLowercase = function(s) {
  9416   /* jshint bitwise: false */
  9414   /* jshint bitwise: false */
  9417   return isString(s)
  9415   return isString(s)
  9433   lowercase = manualLowercase;
  9431   lowercase = manualLowercase;
  9434   uppercase = manualUppercase;
  9432   uppercase = manualUppercase;
  9435 }
  9433 }
  9436 
  9434 
  9437 
  9435 
  9438 var /** holds major version number for IE or NaN for real browsers */
  9436 var
  9439     msie,
  9437     msie,             // holds major version number for IE, or NaN if UA is not IE.
  9440     jqLite,           // delay binding since jQuery could be loaded after us.
  9438     jqLite,           // delay binding since jQuery could be loaded after us.
  9441     jQuery,           // delay binding
  9439     jQuery,           // delay binding
  9442     slice             = [].slice,
  9440     slice             = [].slice,
  9443     splice            = [].splice,
  9441     splice            = [].splice,
  9444     push              = [].push,
  9442     push              = [].push,
  9490  * is the value of an object property or an array element, `key` is the object property key or
  9488  * is the value of an object property or an array element, `key` is the object property key or
  9491  * array element index and obj is the `obj` itself. Specifying a `context` for the function is optional.
  9489  * array element index and obj is the `obj` itself. Specifying a `context` for the function is optional.
  9492  *
  9490  *
  9493  * It is worth noting that `.forEach` does not iterate over inherited properties because it filters
  9491  * It is worth noting that `.forEach` does not iterate over inherited properties because it filters
  9494  * using the `hasOwnProperty` method.
  9492  * using the `hasOwnProperty` method.
       
  9493  *
       
  9494  * Unlike ES262's
       
  9495  * [Array.prototype.forEach](http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.18),
       
  9496  * Providing 'undefined' or 'null' values for `obj` will not throw a TypeError, but rather just
       
  9497  * return the value provided.
  9495  *
  9498  *
  9496    ```js
  9499    ```js
  9497      var values = {name: 'misko', gender: 'male'};
  9500      var values = {name: 'misko', gender: 'male'};
  9498      var log = [];
  9501      var log = [];
  9499      angular.forEach(values, function(value, key) {
  9502      angular.forEach(values, function(value, key) {
  9538   }
  9541   }
  9539   return obj;
  9542   return obj;
  9540 }
  9543 }
  9541 
  9544 
  9542 function sortedKeys(obj) {
  9545 function sortedKeys(obj) {
  9543   var keys = [];
  9546   return Object.keys(obj).sort();
  9544   for (var key in obj) {
       
  9545     if (obj.hasOwnProperty(key)) {
       
  9546       keys.push(key);
       
  9547     }
       
  9548   }
       
  9549   return keys.sort();
       
  9550 }
  9547 }
  9551 
  9548 
  9552 function forEachSorted(obj, iterator, context) {
  9549 function forEachSorted(obj, iterator, context) {
  9553   var keys = sortedKeys(obj);
  9550   var keys = sortedKeys(obj);
  9554   for ( var i = 0; i < keys.length; i++) {
  9551   for (var i = 0; i < keys.length; i++) {
  9555     iterator.call(context, obj[keys[i]], keys[i]);
  9552     iterator.call(context, obj[keys[i]], keys[i]);
  9556   }
  9553   }
  9557   return keys;
  9554   return keys;
  9558 }
  9555 }
  9559 
  9556 
  9602  * @module ng
  9599  * @module ng
  9603  * @kind function
  9600  * @kind function
  9604  *
  9601  *
  9605  * @description
  9602  * @description
  9606  * Extends the destination object `dst` by copying own enumerable properties from the `src` object(s)
  9603  * Extends the destination object `dst` by copying own enumerable properties from the `src` object(s)
  9607  * to `dst`. You can specify multiple `src` objects.
  9604  * to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so
       
  9605  * by passing an empty object as the target: `var object = angular.extend({}, object1, object2)`.
       
  9606  * Note: Keep in mind that `angular.extend` does not support recursive merge (deep copy).
  9608  *
  9607  *
  9609  * @param {Object} dst Destination object.
  9608  * @param {Object} dst Destination object.
  9610  * @param {...Object} src Source object(s).
  9609  * @param {...Object} src Source object(s).
  9611  * @returns {Object} Reference to `dst`.
  9610  * @returns {Object} Reference to `dst`.
  9612  */
  9611  */
  9632   return parseInt(str, 10);
  9631   return parseInt(str, 10);
  9633 }
  9632 }
  9634 
  9633 
  9635 
  9634 
  9636 function inherit(parent, extra) {
  9635 function inherit(parent, extra) {
  9637   return extend(new (extend(function() {}, {prototype:parent}))(), extra);
  9636   return extend(Object.create(parent), extra);
  9638 }
  9637 }
  9639 
  9638 
  9640 /**
  9639 /**
  9641  * @ngdoc function
  9640  * @ngdoc function
  9642  * @name angular.noop
  9641  * @name angular.noop
  9670    ```js
  9669    ```js
  9671      function transformer(transformationFn, value) {
  9670      function transformer(transformationFn, value) {
  9672        return (transformationFn || angular.identity)(value);
  9671        return (transformationFn || angular.identity)(value);
  9673      };
  9672      };
  9674    ```
  9673    ```
       
  9674   * @param {*} value to be returned.
       
  9675   * @returns {*} the value passed in.
  9675  */
  9676  */
  9676 function identity($) {return $;}
  9677 function identity($) {return $;}
  9677 identity.$inject = [];
  9678 identity.$inject = [];
  9678 
  9679 
  9679 
  9680 
  9689  * Determines if a reference is undefined.
  9690  * Determines if a reference is undefined.
  9690  *
  9691  *
  9691  * @param {*} value Reference to check.
  9692  * @param {*} value Reference to check.
  9692  * @returns {boolean} True if `value` is undefined.
  9693  * @returns {boolean} True if `value` is undefined.
  9693  */
  9694  */
  9694 function isUndefined(value){return typeof value === 'undefined';}
  9695 function isUndefined(value) {return typeof value === 'undefined';}
  9695 
  9696 
  9696 
  9697 
  9697 /**
  9698 /**
  9698  * @ngdoc function
  9699  * @ngdoc function
  9699  * @name angular.isDefined
  9700  * @name angular.isDefined
  9704  * Determines if a reference is defined.
  9705  * Determines if a reference is defined.
  9705  *
  9706  *
  9706  * @param {*} value Reference to check.
  9707  * @param {*} value Reference to check.
  9707  * @returns {boolean} True if `value` is defined.
  9708  * @returns {boolean} True if `value` is defined.
  9708  */
  9709  */
  9709 function isDefined(value){return typeof value !== 'undefined';}
  9710 function isDefined(value) {return typeof value !== 'undefined';}
  9710 
  9711 
  9711 
  9712 
  9712 /**
  9713 /**
  9713  * @ngdoc function
  9714  * @ngdoc function
  9714  * @name angular.isObject
  9715  * @name angular.isObject
  9720  * considered to be objects. Note that JavaScript arrays are objects.
  9721  * considered to be objects. Note that JavaScript arrays are objects.
  9721  *
  9722  *
  9722  * @param {*} value Reference to check.
  9723  * @param {*} value Reference to check.
  9723  * @returns {boolean} True if `value` is an `Object` but not `null`.
  9724  * @returns {boolean} True if `value` is an `Object` but not `null`.
  9724  */
  9725  */
  9725 function isObject(value){
  9726 function isObject(value) {
  9726   // http://jsperf.com/isobject4
  9727   // http://jsperf.com/isobject4
  9727   return value !== null && typeof value === 'object';
  9728   return value !== null && typeof value === 'object';
  9728 }
  9729 }
  9729 
  9730 
  9730 
  9731 
  9738  * Determines if a reference is a `String`.
  9739  * Determines if a reference is a `String`.
  9739  *
  9740  *
  9740  * @param {*} value Reference to check.
  9741  * @param {*} value Reference to check.
  9741  * @returns {boolean} True if `value` is a `String`.
  9742  * @returns {boolean} True if `value` is a `String`.
  9742  */
  9743  */
  9743 function isString(value){return typeof value === 'string';}
  9744 function isString(value) {return typeof value === 'string';}
  9744 
  9745 
  9745 
  9746 
  9746 /**
  9747 /**
  9747  * @ngdoc function
  9748  * @ngdoc function
  9748  * @name angular.isNumber
  9749  * @name angular.isNumber
  9753  * Determines if a reference is a `Number`.
  9754  * Determines if a reference is a `Number`.
  9754  *
  9755  *
  9755  * @param {*} value Reference to check.
  9756  * @param {*} value Reference to check.
  9756  * @returns {boolean} True if `value` is a `Number`.
  9757  * @returns {boolean} True if `value` is a `Number`.
  9757  */
  9758  */
  9758 function isNumber(value){return typeof value === 'number';}
  9759 function isNumber(value) {return typeof value === 'number';}
  9759 
  9760 
  9760 
  9761 
  9761 /**
  9762 /**
  9762  * @ngdoc function
  9763  * @ngdoc function
  9763  * @name angular.isDate
  9764  * @name angular.isDate
  9799  * Determines if a reference is a `Function`.
  9800  * Determines if a reference is a `Function`.
  9800  *
  9801  *
  9801  * @param {*} value Reference to check.
  9802  * @param {*} value Reference to check.
  9802  * @returns {boolean} True if `value` is a `Function`.
  9803  * @returns {boolean} True if `value` is a `Function`.
  9803  */
  9804  */
  9804 function isFunction(value){return typeof value === 'function';}
  9805 function isFunction(value) {return typeof value === 'function';}
  9805 
  9806 
  9806 
  9807 
  9807 /**
  9808 /**
  9808  * Determines if a value is a regular expression object.
  9809  * Determines if a value is a regular expression object.
  9809  *
  9810  *
  9836 function isFile(obj) {
  9837 function isFile(obj) {
  9837   return toString.call(obj) === '[object File]';
  9838   return toString.call(obj) === '[object File]';
  9838 }
  9839 }
  9839 
  9840 
  9840 
  9841 
       
  9842 function isFormData(obj) {
       
  9843   return toString.call(obj) === '[object FormData]';
       
  9844 }
       
  9845 
       
  9846 
  9841 function isBlob(obj) {
  9847 function isBlob(obj) {
  9842   return toString.call(obj) === '[object Blob]';
  9848   return toString.call(obj) === '[object Blob]';
  9843 }
  9849 }
  9844 
  9850 
  9845 
  9851 
  9853 }
  9859 }
  9854 
  9860 
  9855 
  9861 
  9856 var trim = function(value) {
  9862 var trim = function(value) {
  9857   return isString(value) ? value.trim() : value;
  9863   return isString(value) ? value.trim() : value;
       
  9864 };
       
  9865 
       
  9866 // Copied from:
       
  9867 // http://docs.closure-library.googlecode.com/git/local_closure_goog_string_string.js.source.html#line1021
       
  9868 // Prereq: s is a string.
       
  9869 var escapeForRegexp = function(s) {
       
  9870   return s.replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g, '\\$1').
       
  9871            replace(/\x08/g, '\\x08');
  9858 };
  9872 };
  9859 
  9873 
  9860 
  9874 
  9861 /**
  9875 /**
  9862  * @ngdoc function
  9876  * @ngdoc function
  9880  * @param str 'key1,key2,...'
  9894  * @param str 'key1,key2,...'
  9881  * @returns {object} in the form of {key1:true, key2:true, ...}
  9895  * @returns {object} in the form of {key1:true, key2:true, ...}
  9882  */
  9896  */
  9883 function makeMap(str) {
  9897 function makeMap(str) {
  9884   var obj = {}, items = str.split(","), i;
  9898   var obj = {}, items = str.split(","), i;
  9885   for ( i = 0; i < items.length; i++ )
  9899   for (i = 0; i < items.length; i++)
  9886     obj[ items[i] ] = true;
  9900     obj[ items[i] ] = true;
  9887   return obj;
  9901   return obj;
  9888 }
  9902 }
  9889 
  9903 
  9890 
  9904 
  9891 function nodeName_(element) {
  9905 function nodeName_(element) {
  9892   return lowercase(element.nodeName || element[0].nodeName);
  9906   return lowercase(element.nodeName || (element[0] && element[0].nodeName));
  9893 }
  9907 }
  9894 
       
  9895 
       
  9896 /**
       
  9897  * @description
       
  9898  * Determines the number of elements in an array, the number of properties an object has, or
       
  9899  * the length of a string.
       
  9900  *
       
  9901  * Note: This function is used to augment the Object type in Angular expressions. See
       
  9902  * {@link angular.Object} for more information about Angular arrays.
       
  9903  *
       
  9904  * @param {Object|Array|string} obj Object, array, or string to inspect.
       
  9905  * @param {boolean} [ownPropsOnly=false] Count only "own" properties in an object
       
  9906  * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.
       
  9907  */
       
  9908 function size(obj, ownPropsOnly) {
       
  9909   var count = 0, key;
       
  9910 
       
  9911   if (isArray(obj) || isString(obj)) {
       
  9912     return obj.length;
       
  9913   } else if (isObject(obj)) {
       
  9914     for (key in obj)
       
  9915       if (!ownPropsOnly || obj.hasOwnProperty(key))
       
  9916         count++;
       
  9917   }
       
  9918 
       
  9919   return count;
       
  9920 }
       
  9921 
       
  9922 
  9908 
  9923 function includes(array, obj) {
  9909 function includes(array, obj) {
  9924   return Array.prototype.indexOf.call(array, obj) != -1;
  9910   return Array.prototype.indexOf.call(array, obj) != -1;
  9925 }
  9911 }
  9926 
  9912 
  9927 function arrayRemove(array, value) {
  9913 function arrayRemove(array, value) {
  9928   var index = array.indexOf(value);
  9914   var index = array.indexOf(value);
  9929   if (index >=0)
  9915   if (index >= 0)
  9930     array.splice(index, 1);
  9916     array.splice(index, 1);
  9931   return value;
  9917   return value;
  9932 }
       
  9933 
       
  9934 function isLeafNode (node) {
       
  9935   if (node) {
       
  9936     switch (nodeName_(node)) {
       
  9937     case "option":
       
  9938     case "pre":
       
  9939     case "title":
       
  9940       return true;
       
  9941     }
       
  9942   }
       
  9943   return false;
       
  9944 }
  9918 }
  9945 
  9919 
  9946 /**
  9920 /**
  9947  * @ngdoc function
  9921  * @ngdoc function
  9948  * @name angular.copy
  9922  * @name angular.copy
  9951  *
  9925  *
  9952  * @description
  9926  * @description
  9953  * Creates a deep copy of `source`, which should be an object or an array.
  9927  * Creates a deep copy of `source`, which should be an object or an array.
  9954  *
  9928  *
  9955  * * If no destination is supplied, a copy of the object or array is created.
  9929  * * If no destination is supplied, a copy of the object or array is created.
  9956  * * If a destination is provided, all of its elements (for array) or properties (for objects)
  9930  * * If a destination is provided, all of its elements (for arrays) or properties (for objects)
  9957  *   are deleted and then all elements/properties from the source are copied to it.
  9931  *   are deleted and then all elements/properties from the source are copied to it.
  9958  * * If `source` is not an object or array (inc. `null` and `undefined`), `source` is returned.
  9932  * * If `source` is not an object or array (inc. `null` and `undefined`), `source` is returned.
  9959  * * If `source` is identical to 'destination' an exception will be thrown.
  9933  * * If `source` is identical to 'destination' an exception will be thrown.
  9960  *
  9934  *
  9961  * @param {*} source The source that will be used to make a copy.
  9935  * @param {*} source The source that will be used to make a copy.
 10038     }
 10012     }
 10039 
 10013 
 10040     var result;
 10014     var result;
 10041     if (isArray(source)) {
 10015     if (isArray(source)) {
 10042       destination.length = 0;
 10016       destination.length = 0;
 10043       for ( var i = 0; i < source.length; i++) {
 10017       for (var i = 0; i < source.length; i++) {
 10044         result = copy(source[i], null, stackSource, stackDest);
 10018         result = copy(source[i], null, stackSource, stackDest);
 10045         if (isObject(source[i])) {
 10019         if (isObject(source[i])) {
 10046           stackSource.push(source[i]);
 10020           stackSource.push(source[i]);
 10047           stackDest.push(result);
 10021           stackDest.push(result);
 10048         }
 10022         }
 10055       } else {
 10029       } else {
 10056         forEach(destination, function(value, key) {
 10030         forEach(destination, function(value, key) {
 10057           delete destination[key];
 10031           delete destination[key];
 10058         });
 10032         });
 10059       }
 10033       }
 10060       for ( var key in source) {
 10034       for (var key in source) {
 10061         if(source.hasOwnProperty(key)) {
 10035         if (source.hasOwnProperty(key)) {
 10062           result = copy(source[key], null, stackSource, stackDest);
 10036           result = copy(source[key], null, stackSource, stackDest);
 10063           if (isObject(source[key])) {
 10037           if (isObject(source[key])) {
 10064             stackSource.push(source[key]);
 10038             stackSource.push(source[key]);
 10065             stackDest.push(result);
 10039             stackDest.push(result);
 10066           }
 10040           }
 10137   if (t1 == t2) {
 10111   if (t1 == t2) {
 10138     if (t1 == 'object') {
 10112     if (t1 == 'object') {
 10139       if (isArray(o1)) {
 10113       if (isArray(o1)) {
 10140         if (!isArray(o2)) return false;
 10114         if (!isArray(o2)) return false;
 10141         if ((length = o1.length) == o2.length) {
 10115         if ((length = o1.length) == o2.length) {
 10142           for(key=0; key<length; key++) {
 10116           for (key = 0; key < length; key++) {
 10143             if (!equals(o1[key], o2[key])) return false;
 10117             if (!equals(o1[key], o2[key])) return false;
 10144           }
 10118           }
 10145           return true;
 10119           return true;
 10146         }
 10120         }
 10147       } else if (isDate(o1)) {
 10121       } else if (isDate(o1)) {
 10150       } else if (isRegExp(o1) && isRegExp(o2)) {
 10124       } else if (isRegExp(o1) && isRegExp(o2)) {
 10151         return o1.toString() == o2.toString();
 10125         return o1.toString() == o2.toString();
 10152       } else {
 10126       } else {
 10153         if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) || isArray(o2)) return false;
 10127         if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) || isArray(o2)) return false;
 10154         keySet = {};
 10128         keySet = {};
 10155         for(key in o1) {
 10129         for (key in o1) {
 10156           if (key.charAt(0) === '$' || isFunction(o1[key])) continue;
 10130           if (key.charAt(0) === '$' || isFunction(o1[key])) continue;
 10157           if (!equals(o1[key], o2[key])) return false;
 10131           if (!equals(o1[key], o2[key])) return false;
 10158           keySet[key] = true;
 10132           keySet[key] = true;
 10159         }
 10133         }
 10160         for(key in o2) {
 10134         for (key in o2) {
 10161           if (!keySet.hasOwnProperty(key) &&
 10135           if (!keySet.hasOwnProperty(key) &&
 10162               key.charAt(0) !== '$' &&
 10136               key.charAt(0) !== '$' &&
 10163               o2[key] !== undefined &&
 10137               o2[key] !== undefined &&
 10164               !isFunction(o2[key])) return false;
 10138               !isFunction(o2[key])) return false;
 10165         }
 10139         }
 10223   var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];
 10197   var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];
 10224   if (isFunction(fn) && !(fn instanceof RegExp)) {
 10198   if (isFunction(fn) && !(fn instanceof RegExp)) {
 10225     return curryArgs.length
 10199     return curryArgs.length
 10226       ? function() {
 10200       ? function() {
 10227           return arguments.length
 10201           return arguments.length
 10228             ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))
 10202             ? fn.apply(self, concat(curryArgs, arguments, 0))
 10229             : fn.apply(self, curryArgs);
 10203             : fn.apply(self, curryArgs);
 10230         }
 10204         }
 10231       : function() {
 10205       : function() {
 10232           return arguments.length
 10206           return arguments.length
 10233             ? fn.apply(self, arguments)
 10207             ? fn.apply(self, arguments)
 10266  * @description
 10240  * @description
 10267  * Serializes input into a JSON-formatted string. Properties with leading $$ characters will be
 10241  * Serializes input into a JSON-formatted string. Properties with leading $$ characters will be
 10268  * stripped since angular uses this notation internally.
 10242  * stripped since angular uses this notation internally.
 10269  *
 10243  *
 10270  * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.
 10244  * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.
 10271  * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.
 10245  * @param {boolean|number=} pretty If set to true, the JSON output will contain newlines and whitespace.
       
 10246  *    If set to an integer, the JSON output will contain that many spaces per indentation (the default is 2).
 10272  * @returns {string|undefined} JSON-ified string representing `obj`.
 10247  * @returns {string|undefined} JSON-ified string representing `obj`.
 10273  */
 10248  */
 10274 function toJson(obj, pretty) {
 10249 function toJson(obj, pretty) {
 10275   if (typeof obj === 'undefined') return undefined;
 10250   if (typeof obj === 'undefined') return undefined;
 10276   return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);
 10251   if (!isNumber(pretty)) {
       
 10252     pretty = pretty ? 2 : null;
       
 10253   }
       
 10254   return JSON.stringify(obj, toJsonReplacer, pretty);
 10277 }
 10255 }
 10278 
 10256 
 10279 
 10257 
 10280 /**
 10258 /**
 10281  * @ngdoc function
 10259  * @ngdoc function
 10285  *
 10263  *
 10286  * @description
 10264  * @description
 10287  * Deserializes a JSON string.
 10265  * Deserializes a JSON string.
 10288  *
 10266  *
 10289  * @param {string} json JSON string to deserialize.
 10267  * @param {string} json JSON string to deserialize.
 10290  * @returns {Object|Array|string|number} Deserialized thingy.
 10268  * @returns {Object|Array|string|number} Deserialized JSON string.
 10291  */
 10269  */
 10292 function fromJson(json) {
 10270 function fromJson(json) {
 10293   return isString(json)
 10271   return isString(json)
 10294       ? JSON.parse(json)
 10272       ? JSON.parse(json)
 10295       : json;
 10273       : json;
 10303   element = jqLite(element).clone();
 10281   element = jqLite(element).clone();
 10304   try {
 10282   try {
 10305     // turns out IE does not let you set .html() on elements which
 10283     // turns out IE does not let you set .html() on elements which
 10306     // are not allowed to have children. So we just ignore it.
 10284     // are not allowed to have children. So we just ignore it.
 10307     element.empty();
 10285     element.empty();
 10308   } catch(e) {}
 10286   } catch (e) {}
 10309   var elemHtml = jqLite('<div>').append(element).html();
 10287   var elemHtml = jqLite('<div>').append(element).html();
 10310   try {
 10288   try {
 10311     return element[0].nodeType === NODE_TYPE_TEXT ? lowercase(elemHtml) :
 10289     return element[0].nodeType === NODE_TYPE_TEXT ? lowercase(elemHtml) :
 10312         elemHtml.
 10290         elemHtml.
 10313           match(/^(<[^>]+>)/)[1].
 10291           match(/^(<[^>]+>)/)[1].
 10314           replace(/^<([\w\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });
 10292           replace(/^<([\w\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });
 10315   } catch(e) {
 10293   } catch (e) {
 10316     return lowercase(elemHtml);
 10294     return lowercase(elemHtml);
 10317   }
 10295   }
 10318 
 10296 
 10319 }
 10297 }
 10320 
 10298 
 10330  * with the decodeURIComponent function.
 10308  * with the decodeURIComponent function.
 10331  */
 10309  */
 10332 function tryDecodeURIComponent(value) {
 10310 function tryDecodeURIComponent(value) {
 10333   try {
 10311   try {
 10334     return decodeURIComponent(value);
 10312     return decodeURIComponent(value);
 10335   } catch(e) {
 10313   } catch (e) {
 10336     // Ignore any invalid uri component
 10314     // Ignore any invalid uri component
 10337   }
 10315   }
 10338 }
 10316 }
 10339 
 10317 
 10340 
 10318 
 10343  * @returns {Object.<string,boolean|Array>}
 10321  * @returns {Object.<string,boolean|Array>}
 10344  */
 10322  */
 10345 function parseKeyValue(/**string*/keyValue) {
 10323 function parseKeyValue(/**string*/keyValue) {
 10346   var obj = {}, key_value, key;
 10324   var obj = {}, key_value, key;
 10347   forEach((keyValue || "").split('&'), function(keyValue) {
 10325   forEach((keyValue || "").split('&'), function(keyValue) {
 10348     if ( keyValue ) {
 10326     if (keyValue) {
 10349       key_value = keyValue.replace(/\+/g,'%20').split('=');
 10327       key_value = keyValue.replace(/\+/g,'%20').split('=');
 10350       key = tryDecodeURIComponent(key_value[0]);
 10328       key = tryDecodeURIComponent(key_value[0]);
 10351       if ( isDefined(key) ) {
 10329       if (isDefined(key)) {
 10352         var val = isDefined(key_value[1]) ? tryDecodeURIComponent(key_value[1]) : true;
 10330         var val = isDefined(key_value[1]) ? tryDecodeURIComponent(key_value[1]) : true;
 10353         if (!hasOwnProperty.call(obj, key)) {
 10331         if (!hasOwnProperty.call(obj, key)) {
 10354           obj[key] = val;
 10332           obj[key] = val;
 10355         } else if(isArray(obj[key])) {
 10333         } else if (isArray(obj[key])) {
 10356           obj[key].push(val);
 10334           obj[key].push(val);
 10357         } else {
 10335         } else {
 10358           obj[key] = [obj[key],val];
 10336           obj[key] = [obj[key],val];
 10359         }
 10337         }
 10360       }
 10338       }
 10423 var ngAttrPrefixes = ['ng-', 'data-ng-', 'ng:', 'x-ng-'];
 10401 var ngAttrPrefixes = ['ng-', 'data-ng-', 'ng:', 'x-ng-'];
 10424 
 10402 
 10425 function getNgAttribute(element, ngAttr) {
 10403 function getNgAttribute(element, ngAttr) {
 10426   var attr, i, ii = ngAttrPrefixes.length;
 10404   var attr, i, ii = ngAttrPrefixes.length;
 10427   element = jqLite(element);
 10405   element = jqLite(element);
 10428   for (i=0; i<ii; ++i) {
 10406   for (i = 0; i < ii; ++i) {
 10429     attr = ngAttrPrefixes[i] + ngAttr;
 10407     attr = ngAttrPrefixes[i] + ngAttr;
 10430     if (isString(attr = element.attr(attr))) {
 10408     if (isString(attr = element.attr(attr))) {
 10431       return attr;
 10409       return attr;
 10432     }
 10410     }
 10433   }
 10411   }
 10458  * found in the document will be used to define the root element to auto-bootstrap as an
 10436  * found in the document will be used to define the root element to auto-bootstrap as an
 10459  * application. To run multiple applications in an HTML document you must manually bootstrap them using
 10437  * application. To run multiple applications in an HTML document you must manually bootstrap them using
 10460  * {@link angular.bootstrap} instead. AngularJS applications cannot be nested within each other.
 10438  * {@link angular.bootstrap} instead. AngularJS applications cannot be nested within each other.
 10461  *
 10439  *
 10462  * You can specify an **AngularJS module** to be used as the root module for the application.  This
 10440  * You can specify an **AngularJS module** to be used as the root module for the application.  This
 10463  * module will be loaded into the {@link auto.$injector} when the application is bootstrapped and
 10441  * module will be loaded into the {@link auto.$injector} when the application is bootstrapped. It
 10464  * should contain the application code needed or have dependencies on other modules that will
 10442  * should contain the application code needed or have dependencies on other modules that will
 10465  * contain the code. See {@link angular.module} for more information.
 10443  * contain the code. See {@link angular.module} for more information.
 10466  *
 10444  *
 10467  * In the example below if the `ngApp` directive were not placed on the `html` element then the
 10445  * In the example below if the `ngApp` directive were not placed on the `html` element then the
 10468  * document would not be compiled, the `AppController` would not be instantiated and the `{{ a+b }}`
 10446  * document would not be compiled, the `AppController` would not be instantiated and the `{{ a+b }}`
 10469  * would not be resolved to `3`.
 10447  * would not be resolved to `3`.
 10470  *
 10448  *
 10471  * `ngApp` is the easiest, and most common, way to bootstrap an application.
 10449  * `ngApp` is the easiest, and most common way to bootstrap an application.
 10472  *
 10450  *
 10473  <example module="ngAppDemo">
 10451  <example module="ngAppDemo">
 10474    <file name="index.html">
 10452    <file name="index.html">
 10475    <div ng-controller="ngAppDemoController">
 10453    <div ng-controller="ngAppDemoController">
 10476      I can add: {{a}} + {{b}} =  {{ a+b }}
 10454      I can add: {{a}} + {{b}} =  {{ a+b }}
 10633  *     function that will be invoked by the injector as a run block.
 10611  *     function that will be invoked by the injector as a run block.
 10634  *     See: {@link angular.module modules}
 10612  *     See: {@link angular.module modules}
 10635  * @param {Object=} config an object for defining configuration options for the application. The
 10613  * @param {Object=} config an object for defining configuration options for the application. The
 10636  *     following keys are supported:
 10614  *     following keys are supported:
 10637  *
 10615  *
 10638  *     - `strictDi`: disable automatic function annotation for the application. This is meant to
 10616  * * `strictDi` - disable automatic function annotation for the application. This is meant to
 10639  *       assist in finding bugs which break minified code.
 10617  *   assist in finding bugs which break minified code. Defaults to `false`.
 10640  *
 10618  *
 10641  * @returns {auto.$injector} Returns the newly created injector for this app.
 10619  * @returns {auto.$injector} Returns the newly created injector for this app.
 10642  */
 10620  */
 10643 function bootstrap(element, modules, config) {
 10621 function bootstrap(element, modules, config) {
 10644   if (!isObject(config)) config = {};
 10622   if (!isObject(config)) config = {};
 10726  * Get the testability service for the instance of Angular on the given
 10704  * Get the testability service for the instance of Angular on the given
 10727  * element.
 10705  * element.
 10728  * @param {DOMElement} element DOM element which is the root of angular application.
 10706  * @param {DOMElement} element DOM element which is the root of angular application.
 10729  */
 10707  */
 10730 function getTestability(rootElement) {
 10708 function getTestability(rootElement) {
 10731   return angular.element(rootElement).injector().get('$$testability');
 10709   var injector = angular.element(rootElement).injector();
       
 10710   if (!injector) {
       
 10711     throw ngMinErr('test',
       
 10712       'no injector found for element argument to getTestability');
       
 10713   }
       
 10714   return injector.get('$$testability');
 10732 }
 10715 }
 10733 
 10716 
 10734 var SNAKE_CASE_REGEXP = /[A-Z]/g;
 10717 var SNAKE_CASE_REGEXP = /[A-Z]/g;
 10735 function snake_case(name, separator) {
 10718 function snake_case(name, separator) {
 10736   separator = separator || '_';
 10719   separator = separator || '_';
 11113            *     }
 11096            *     }
 11114            *   }
 11097            *   }
 11115            * })
 11098            * })
 11116            * ```
 11099            * ```
 11117            *
 11100            *
 11118            * See {@link ngAnimate.$animateProvider#register $animateProvider.register()} and
 11101            * See {@link ng.$animateProvider#register $animateProvider.register()} and
 11119            * {@link ngAnimate ngAnimate module} for more information.
 11102            * {@link ngAnimate ngAnimate module} for more information.
 11120            */
 11103            */
 11121           animation: invokeLater('$animateProvider', 'register'),
 11104           animation: invokeLater('$animateProvider', 'register'),
 11122 
 11105 
 11123           /**
 11106           /**
 11163            * @param {Function} configFn Execute this function on module load. Useful for service
 11146            * @param {Function} configFn Execute this function on module load. Useful for service
 11164            *    configuration.
 11147            *    configuration.
 11165            * @description
 11148            * @description
 11166            * Use this method to register work which needs to be performed on module loading.
 11149            * Use this method to register work which needs to be performed on module loading.
 11167            * For more about how to configure services, see
 11150            * For more about how to configure services, see
 11168            * {@link providers#providers_provider-recipe Provider Recipe}.
 11151            * {@link providers#provider-recipe Provider Recipe}.
 11169            */
 11152            */
 11170           config: config,
 11153           config: config,
 11171 
 11154 
 11172           /**
 11155           /**
 11173            * @ngdoc method
 11156            * @ngdoc method
 11187 
 11170 
 11188         if (configFn) {
 11171         if (configFn) {
 11189           config(configFn);
 11172           config(configFn);
 11190         }
 11173         }
 11191 
 11174 
 11192         return  moduleInstance;
 11175         return moduleInstance;
 11193 
 11176 
 11194         /**
 11177         /**
 11195          * @param {string} provider
 11178          * @param {string} provider
 11196          * @param {string} method
 11179          * @param {string} method
 11197          * @param {String=} insertMethod
 11180          * @param {String=} insertMethod
 11206         }
 11189         }
 11207       });
 11190       });
 11208     };
 11191     };
 11209   });
 11192   });
 11210 
 11193 
       
 11194 }
       
 11195 
       
 11196 /* global: toDebugString: true */
       
 11197 
       
 11198 function serializeObject(obj) {
       
 11199   var seen = [];
       
 11200 
       
 11201   return JSON.stringify(obj, function(key, val) {
       
 11202     val = toJsonReplacer(key, val);
       
 11203     if (isObject(val)) {
       
 11204 
       
 11205       if (seen.indexOf(val) >= 0) return '<<already seen>>';
       
 11206 
       
 11207       seen.push(val);
       
 11208     }
       
 11209     return val;
       
 11210   });
       
 11211 }
       
 11212 
       
 11213 function toDebugString(obj) {
       
 11214   if (typeof obj === 'function') {
       
 11215     return obj.toString().replace(/ \{[\s\S]*$/, '');
       
 11216   } else if (typeof obj === 'undefined') {
       
 11217     return 'undefined';
       
 11218   } else if (typeof obj !== 'string') {
       
 11219     return serializeObject(obj);
       
 11220   }
       
 11221   return obj;
 11211 }
 11222 }
 11212 
 11223 
 11213 /* global angularModule: true,
 11224 /* global angularModule: true,
 11214   version: true,
 11225   version: true,
 11215 
 11226 
 11291   $TemplateRequestProvider,
 11302   $TemplateRequestProvider,
 11292   $$TestabilityProvider,
 11303   $$TestabilityProvider,
 11293   $TimeoutProvider,
 11304   $TimeoutProvider,
 11294   $$RAFProvider,
 11305   $$RAFProvider,
 11295   $$AsyncCallbackProvider,
 11306   $$AsyncCallbackProvider,
 11296   $WindowProvider
 11307   $WindowProvider,
       
 11308   $$jqLiteProvider
 11297 */
 11309 */
 11298 
 11310 
 11299 
 11311 
 11300 /**
 11312 /**
 11301  * @ngdoc object
 11313  * @ngdoc object
 11310  * - `minor` – `{number}` – Minor version number, such as "9".
 11322  * - `minor` – `{number}` – Minor version number, such as "9".
 11311  * - `dot` – `{number}` – Dot version number, such as "18".
 11323  * - `dot` – `{number}` – Dot version number, such as "18".
 11312  * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
 11324  * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
 11313  */
 11325  */
 11314 var version = {
 11326 var version = {
 11315   full: '1.3.0-rc.5',    // all of these placeholder strings will be replaced by grunt's
 11327   full: '1.3.8',    // all of these placeholder strings will be replaced by grunt's
 11316   major: 1,    // package task
 11328   major: 1,    // package task
 11317   minor: 3,
 11329   minor: 3,
 11318   dot: 0,
 11330   dot: 8,
 11319   codeName: 'impossible-choreography'
 11331   codeName: 'prophetic-narwhal'
 11320 };
 11332 };
 11321 
 11333 
 11322 
 11334 
 11323 function publishExternalAPI(angular){
 11335 function publishExternalAPI(angular) {
 11324   extend(angular, {
 11336   extend(angular, {
 11325     'bootstrap': bootstrap,
 11337     'bootstrap': bootstrap,
 11326     'copy': copy,
 11338     'copy': copy,
 11327     'extend': extend,
 11339     'extend': extend,
 11328     'equals': equals,
 11340     'equals': equals,
 11444         $templateRequest: $TemplateRequestProvider,
 11456         $templateRequest: $TemplateRequestProvider,
 11445         $$testability: $$TestabilityProvider,
 11457         $$testability: $$TestabilityProvider,
 11446         $timeout: $TimeoutProvider,
 11458         $timeout: $TimeoutProvider,
 11447         $window: $WindowProvider,
 11459         $window: $WindowProvider,
 11448         $$rAF: $$RAFProvider,
 11460         $$rAF: $$RAFProvider,
 11449         $$asyncCallback : $$AsyncCallbackProvider
 11461         $$asyncCallback: $$AsyncCallbackProvider,
       
 11462         $$jqLite: $$jqLiteProvider
 11450       });
 11463       });
 11451     }
 11464     }
 11452   ]);
 11465   ]);
 11453 }
 11466 }
 11454 
 11467 
 11489  * jqLite provides only the following jQuery methods:
 11502  * jqLite provides only the following jQuery methods:
 11490  *
 11503  *
 11491  * - [`addClass()`](http://api.jquery.com/addClass/)
 11504  * - [`addClass()`](http://api.jquery.com/addClass/)
 11492  * - [`after()`](http://api.jquery.com/after/)
 11505  * - [`after()`](http://api.jquery.com/after/)
 11493  * - [`append()`](http://api.jquery.com/append/)
 11506  * - [`append()`](http://api.jquery.com/append/)
 11494  * - [`attr()`](http://api.jquery.com/attr/)
 11507  * - [`attr()`](http://api.jquery.com/attr/) - Does not support functions as parameters
 11495  * - [`bind()`](http://api.jquery.com/bind/) - Does not support namespaces, selectors or eventData
 11508  * - [`bind()`](http://api.jquery.com/bind/) - Does not support namespaces, selectors or eventData
 11496  * - [`children()`](http://api.jquery.com/children/) - Does not support selectors
 11509  * - [`children()`](http://api.jquery.com/children/) - Does not support selectors
 11497  * - [`clone()`](http://api.jquery.com/clone/)
 11510  * - [`clone()`](http://api.jquery.com/clone/)
 11498  * - [`contents()`](http://api.jquery.com/contents/)
 11511  * - [`contents()`](http://api.jquery.com/contents/)
 11499  * - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyles()`
 11512  * - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyle()`
 11500  * - [`data()`](http://api.jquery.com/data/)
 11513  * - [`data()`](http://api.jquery.com/data/)
 11501  * - [`detach()`](http://api.jquery.com/detach/)
 11514  * - [`detach()`](http://api.jquery.com/detach/)
 11502  * - [`empty()`](http://api.jquery.com/empty/)
 11515  * - [`empty()`](http://api.jquery.com/empty/)
 11503  * - [`eq()`](http://api.jquery.com/eq/)
 11516  * - [`eq()`](http://api.jquery.com/eq/)
 11504  * - [`find()`](http://api.jquery.com/find/) - Limited to lookups by tag name
 11517  * - [`find()`](http://api.jquery.com/find/) - Limited to lookups by tag name
 11537  *   retrieves controller associated with the `ngController` directive. If `name` is provided as
 11550  *   retrieves controller associated with the `ngController` directive. If `name` is provided as
 11538  *   camelCase directive name, then the controller for this directive will be retrieved (e.g.
 11551  *   camelCase directive name, then the controller for this directive will be retrieved (e.g.
 11539  *   `'ngModel'`).
 11552  *   `'ngModel'`).
 11540  * - `injector()` - retrieves the injector of the current element or its parent.
 11553  * - `injector()` - retrieves the injector of the current element or its parent.
 11541  * - `scope()` - retrieves the {@link ng.$rootScope.Scope scope} of the current
 11554  * - `scope()` - retrieves the {@link ng.$rootScope.Scope scope} of the current
 11542  *   element or its parent.
 11555  *   element or its parent. Requires {@link guide/production#disabling-debug-data Debug Data} to
       
 11556  *   be enabled.
 11543  * - `isolateScope()` - retrieves an isolate {@link ng.$rootScope.Scope scope} if one is attached directly to the
 11557  * - `isolateScope()` - retrieves an isolate {@link ng.$rootScope.Scope scope} if one is attached directly to the
 11544  *   current element. This getter should be used only on elements that contain a directive which starts a new isolate
 11558  *   current element. This getter should be used only on elements that contain a directive which starts a new isolate
 11545  *   scope. Calling `scope()` on this element always returns the original non-isolate scope.
 11559  *   scope. Calling `scope()` on this element always returns the original non-isolate scope.
       
 11560  *   Requires {@link guide/production#disabling-debug-data Debug Data} to be enabled.
 11546  * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top
 11561  * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top
 11547  *   parent element is reached.
 11562  *   parent element is reached.
 11548  *
 11563  *
 11549  * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.
 11564  * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.
 11550  * @returns {Object} jQuery object.
 11565  * @returns {Object} jQuery object.
 11572 function jqNextId() { return ++jqId; }
 11587 function jqNextId() { return ++jqId; }
 11573 
 11588 
 11574 
 11589 
 11575 var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g;
 11590 var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g;
 11576 var MOZ_HACK_REGEXP = /^moz([A-Z])/;
 11591 var MOZ_HACK_REGEXP = /^moz([A-Z])/;
 11577 var MOUSE_EVENT_MAP= { mouseleave : "mouseout", mouseenter : "mouseover"};
 11592 var MOUSE_EVENT_MAP= { mouseleave: "mouseout", mouseenter: "mouseover"};
 11578 var jqLiteMinErr = minErr('jqLite');
 11593 var jqLiteMinErr = minErr('jqLite');
 11579 
 11594 
 11580 /**
 11595 /**
 11581  * Converts snake_case to camelCase.
 11596  * Converts snake_case to camelCase.
 11582  * Also there is special case for Moz prefix starting with upper case letter.
 11597  * Also there is special case for Moz prefix starting with upper case letter.
 11701 
 11716 
 11702 function jqLiteClone(element) {
 11717 function jqLiteClone(element) {
 11703   return element.cloneNode(true);
 11718   return element.cloneNode(true);
 11704 }
 11719 }
 11705 
 11720 
 11706 function jqLiteDealoc(element, onlyDescendants){
 11721 function jqLiteDealoc(element, onlyDescendants) {
 11707   if (!onlyDescendants) jqLiteRemoveData(element);
 11722   if (!onlyDescendants) jqLiteRemoveData(element);
 11708 
 11723 
 11709   if (element.querySelectorAll) {
 11724   if (element.querySelectorAll) {
 11710     var descendants = element.querySelectorAll('*');
 11725     var descendants = element.querySelectorAll('*');
 11711     for (var i = 0, l = descendants.length; i < l; i++) {
 11726     for (var i = 0, l = descendants.length; i < l; i++) {
 11724   if (!handle) return; //no listeners registered
 11739   if (!handle) return; //no listeners registered
 11725 
 11740 
 11726   if (!type) {
 11741   if (!type) {
 11727     for (type in events) {
 11742     for (type in events) {
 11728       if (type !== '$destroy') {
 11743       if (type !== '$destroy') {
 11729         removeEventListenerFn(element, type, events[type]);
 11744         removeEventListenerFn(element, type, handle);
 11730       }
 11745       }
 11731       delete events[type];
 11746       delete events[type];
 11732     }
 11747     }
 11733   } else {
 11748   } else {
 11734     forEach(type.split(' '), function(type) {
 11749     forEach(type.split(' '), function(type) {
 11735       if (isUndefined(fn)) {
 11750       if (isDefined(fn)) {
 11736         removeEventListenerFn(element, type, events[type]);
 11751         var listenerFns = events[type];
 11737         delete events[type];
 11752         arrayRemove(listenerFns || [], fn);
 11738       } else {
 11753         if (listenerFns && listenerFns.length > 0) {
 11739         arrayRemove(events[type] || [], fn);
 11754           return;
       
 11755         }
 11740       }
 11756       }
       
 11757 
       
 11758       removeEventListenerFn(element, type, handle);
       
 11759       delete events[type];
 11741     });
 11760     });
 11742   }
 11761   }
 11743 }
 11762 }
 11744 
 11763 
 11745 function jqLiteRemoveData(element, name) {
 11764 function jqLiteRemoveData(element, name) {
 11804 }
 11823 }
 11805 
 11824 
 11806 function jqLiteHasClass(element, selector) {
 11825 function jqLiteHasClass(element, selector) {
 11807   if (!element.getAttribute) return false;
 11826   if (!element.getAttribute) return false;
 11808   return ((" " + (element.getAttribute('class') || '') + " ").replace(/[\n\t]/g, " ").
 11827   return ((" " + (element.getAttribute('class') || '') + " ").replace(/[\n\t]/g, " ").
 11809       indexOf( " " + selector + " " ) > -1);
 11828       indexOf(" " + selector + " ") > -1);
 11810 }
 11829 }
 11811 
 11830 
 11812 function jqLiteRemoveClass(element, cssClasses) {
 11831 function jqLiteRemoveClass(element, cssClasses) {
 11813   if (cssClasses && element.setAttribute) {
 11832   if (cssClasses && element.setAttribute) {
 11814     forEach(cssClasses.split(' '), function(cssClass) {
 11833     forEach(cssClasses.split(' '), function(cssClass) {
 11863   }
 11882   }
 11864 }
 11883 }
 11865 
 11884 
 11866 
 11885 
 11867 function jqLiteController(element, name) {
 11886 function jqLiteController(element, name) {
 11868   return jqLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');
 11887   return jqLiteInheritedData(element, '$' + (name || 'ngController') + 'Controller');
 11869 }
 11888 }
 11870 
 11889 
 11871 function jqLiteInheritedData(element, name, value) {
 11890 function jqLiteInheritedData(element, name, value) {
 11872   // if element is the document object work with the html element instead
 11891   // if element is the document object work with the html element instead
 11873   // this makes $(document).scope() possible
 11892   // this makes $(document).scope() possible
 11874   if(element.nodeType == NODE_TYPE_DOCUMENT) {
 11893   if (element.nodeType == NODE_TYPE_DOCUMENT) {
 11875     element = element.documentElement;
 11894     element = element.documentElement;
 11876   }
 11895   }
 11877   var names = isArray(name) ? name : [name];
 11896   var names = isArray(name) ? name : [name];
 11878 
 11897 
 11879   while (element) {
 11898   while (element) {
 11899   if (!keepData) jqLiteDealoc(element);
 11918   if (!keepData) jqLiteDealoc(element);
 11900   var parent = element.parentNode;
 11919   var parent = element.parentNode;
 11901   if (parent) parent.removeChild(element);
 11920   if (parent) parent.removeChild(element);
 11902 }
 11921 }
 11903 
 11922 
       
 11923 
       
 11924 function jqLiteDocumentLoaded(action, win) {
       
 11925   win = win || window;
       
 11926   if (win.document.readyState === 'complete') {
       
 11927     // Force the action to be run async for consistent behaviour
       
 11928     // from the action's point of view
       
 11929     // i.e. it will definitely not be in a $apply
       
 11930     win.setTimeout(action);
       
 11931   } else {
       
 11932     // No need to unbind this handler as load is only ever called once
       
 11933     jqLite(win).on('load', action);
       
 11934   }
       
 11935 }
       
 11936 
 11904 //////////////////////////////////////////
 11937 //////////////////////////////////////////
 11905 // Functions which are declared directly.
 11938 // Functions which are declared directly.
 11906 //////////////////////////////////////////
 11939 //////////////////////////////////////////
 11907 var JQLitePrototype = JQLite.prototype = {
 11940 var JQLitePrototype = JQLite.prototype = {
 11908   ready: function(fn) {
 11941   ready: function(fn) {
 11913       fired = true;
 11946       fired = true;
 11914       fn();
 11947       fn();
 11915     }
 11948     }
 11916 
 11949 
 11917     // check if document is already loaded
 11950     // check if document is already loaded
 11918     if (document.readyState === 'complete'){
 11951     if (document.readyState === 'complete') {
 11919       setTimeout(trigger);
 11952       setTimeout(trigger);
 11920     } else {
 11953     } else {
 11921       this.on('DOMContentLoaded', trigger); // works for modern browsers and IE9
 11954       this.on('DOMContentLoaded', trigger); // works for modern browsers and IE9
 11922       // we can not use jqLite since we are not done loading and jQuery could be loaded later.
 11955       // we can not use jqLite since we are not done loading and jQuery could be loaded later.
 11923       // jshint -W064
 11956       // jshint -W064
 11924       JQLite(window).on('load', trigger); // fallback to window.onload for others
 11957       JQLite(window).on('load', trigger); // fallback to window.onload for others
 11925       // jshint +W064
 11958       // jshint +W064
 11926       this.on('DOMContentLoaded', trigger);
       
 11927     }
 11959     }
 11928   },
 11960   },
 11929   toString: function() {
 11961   toString: function() {
 11930     var value = [];
 11962     var value = [];
 11931     forEach(this, function(e){ value.push('' + e);});
 11963     forEach(this, function(e) { value.push('' + e);});
 11932     return '[' + value.join(', ') + ']';
 11964     return '[' + value.join(', ') + ']';
 11933   },
 11965   },
 11934 
 11966 
 11935   eq: function(index) {
 11967   eq: function(index) {
 11936       return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);
 11968       return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);
 11954 var BOOLEAN_ELEMENTS = {};
 11986 var BOOLEAN_ELEMENTS = {};
 11955 forEach('input,select,option,textarea,button,form,details'.split(','), function(value) {
 11987 forEach('input,select,option,textarea,button,form,details'.split(','), function(value) {
 11956   BOOLEAN_ELEMENTS[value] = true;
 11988   BOOLEAN_ELEMENTS[value] = true;
 11957 });
 11989 });
 11958 var ALIASED_ATTR = {
 11990 var ALIASED_ATTR = {
 11959   'ngMinlength' : 'minlength',
 11991   'ngMinlength': 'minlength',
 11960   'ngMaxlength' : 'maxlength',
 11992   'ngMaxlength': 'maxlength',
 11961   'ngMin' : 'min',
 11993   'ngMin': 'min',
 11962   'ngMax' : 'max',
 11994   'ngMax': 'max',
 11963   'ngPattern' : 'pattern'
 11995   'ngPattern': 'pattern'
 11964 };
 11996 };
 11965 
 11997 
 11966 function getBooleanAttrName(element, name) {
 11998 function getBooleanAttrName(element, name) {
 11967   // check dom last since we will most likely fail on name
 11999   // check dom last since we will most likely fail on name
 11968   var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];
 12000   var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];
 12017     } else {
 12049     } else {
 12018       return element.style[name];
 12050       return element.style[name];
 12019     }
 12051     }
 12020   },
 12052   },
 12021 
 12053 
 12022   attr: function(element, name, value){
 12054   attr: function(element, name, value) {
 12023     var lowercasedName = lowercase(name);
 12055     var lowercasedName = lowercase(name);
 12024     if (BOOLEAN_ATTR[lowercasedName]) {
 12056     if (BOOLEAN_ATTR[lowercasedName]) {
 12025       if (isDefined(value)) {
 12057       if (isDefined(value)) {
 12026         if (!!value) {
 12058         if (!!value) {
 12027           element[name] = true;
 12059           element[name] = true;
 12030           element[name] = false;
 12062           element[name] = false;
 12031           element.removeAttribute(lowercasedName);
 12063           element.removeAttribute(lowercasedName);
 12032         }
 12064         }
 12033       } else {
 12065       } else {
 12034         return (element[name] ||
 12066         return (element[name] ||
 12035                  (element.attributes.getNamedItem(name)|| noop).specified)
 12067                  (element.attributes.getNamedItem(name) || noop).specified)
 12036                ? lowercasedName
 12068                ? lowercasedName
 12037                : undefined;
 12069                : undefined;
 12038       }
 12070       }
 12039     } else if (isDefined(value)) {
 12071     } else if (isDefined(value)) {
 12040       element.setAttribute(name, value);
 12072       element.setAttribute(name, value);
 12070 
 12102 
 12071   val: function(element, value) {
 12103   val: function(element, value) {
 12072     if (isUndefined(value)) {
 12104     if (isUndefined(value)) {
 12073       if (element.multiple && nodeName_(element) === 'select') {
 12105       if (element.multiple && nodeName_(element) === 'select') {
 12074         var result = [];
 12106         var result = [];
 12075         forEach(element.options, function (option) {
 12107         forEach(element.options, function(option) {
 12076           if (option.selected) {
 12108           if (option.selected) {
 12077             result.push(option.value || option.text);
 12109             result.push(option.value || option.text);
 12078           }
 12110           }
 12079         });
 12111         });
 12080         return result.length === 0 ? null : result;
 12112         return result.length === 0 ? null : result;
 12091     jqLiteDealoc(element, true);
 12123     jqLiteDealoc(element, true);
 12092     element.innerHTML = value;
 12124     element.innerHTML = value;
 12093   },
 12125   },
 12094 
 12126 
 12095   empty: jqLiteEmpty
 12127   empty: jqLiteEmpty
 12096 }, function(fn, name){
 12128 }, function(fn, name) {
 12097   /**
 12129   /**
 12098    * Properties: writes return selection, reads return first value
 12130    * Properties: writes return selection, reads return first value
 12099    */
 12131    */
 12100   JQLite.prototype[name] = function(arg1, arg2) {
 12132   JQLite.prototype[name] = function(arg1, arg2) {
 12101     var i, key;
 12133     var i, key;
 12143     }
 12175     }
 12144   };
 12176   };
 12145 });
 12177 });
 12146 
 12178 
 12147 function createEventHandler(element, events) {
 12179 function createEventHandler(element, events) {
 12148   var eventHandler = function (event, type) {
 12180   var eventHandler = function(event, type) {
 12149     // jQuery specific api
 12181     // jQuery specific api
 12150     event.isDefaultPrevented = function() {
 12182     event.isDefaultPrevented = function() {
 12151       return event.defaultPrevented;
 12183       return event.defaultPrevented;
 12152     };
 12184     };
 12153 
 12185 
 12199 // selector.
 12231 // selector.
 12200 //////////////////////////////////////////
 12232 //////////////////////////////////////////
 12201 forEach({
 12233 forEach({
 12202   removeData: jqLiteRemoveData,
 12234   removeData: jqLiteRemoveData,
 12203 
 12235 
 12204   on: function jqLiteOn(element, type, fn, unsupported){
 12236   on: function jqLiteOn(element, type, fn, unsupported) {
 12205     if (isDefined(unsupported)) throw jqLiteMinErr('onargs', 'jqLite#on() does not support the `selector` or `eventData` parameters');
 12237     if (isDefined(unsupported)) throw jqLiteMinErr('onargs', 'jqLite#on() does not support the `selector` or `eventData` parameters');
 12206 
 12238 
 12207     // Do not add event handlers to non-elements because they will not be cleaned up.
 12239     // Do not add event handlers to non-elements because they will not be cleaned up.
 12208     if (!jqLiteAcceptsData(element)) {
 12240     if (!jqLiteAcceptsData(element)) {
 12209       return;
 12241       return;
 12235 
 12267 
 12236           jqLiteOn(element, MOUSE_EVENT_MAP[type], function(event) {
 12268           jqLiteOn(element, MOUSE_EVENT_MAP[type], function(event) {
 12237             var target = this, related = event.relatedTarget;
 12269             var target = this, related = event.relatedTarget;
 12238             // For mousenter/leave call the handler if related is outside the target.
 12270             // For mousenter/leave call the handler if related is outside the target.
 12239             // NB: No relatedTarget if the mouse left/entered the browser window
 12271             // NB: No relatedTarget if the mouse left/entered the browser window
 12240             if ( !related || (related !== target && !target.contains(related)) ){
 12272             if (!related || (related !== target && !target.contains(related))) {
 12241               handle(event, type);
 12273               handle(event, type);
 12242             }
 12274             }
 12243           });
 12275           });
 12244 
 12276 
 12245         } else {
 12277         } else {
 12269   },
 12301   },
 12270 
 12302 
 12271   replaceWith: function(element, replaceNode) {
 12303   replaceWith: function(element, replaceNode) {
 12272     var index, parent = element.parentNode;
 12304     var index, parent = element.parentNode;
 12273     jqLiteDealoc(element);
 12305     jqLiteDealoc(element);
 12274     forEach(new JQLite(replaceNode), function(node){
 12306     forEach(new JQLite(replaceNode), function(node) {
 12275       if (index) {
 12307       if (index) {
 12276         parent.insertBefore(node, index.nextSibling);
 12308         parent.insertBefore(node, index.nextSibling);
 12277       } else {
 12309       } else {
 12278         parent.replaceChild(node, element);
 12310         parent.replaceChild(node, element);
 12279       }
 12311       }
 12281     });
 12313     });
 12282   },
 12314   },
 12283 
 12315 
 12284   children: function(element) {
 12316   children: function(element) {
 12285     var children = [];
 12317     var children = [];
 12286     forEach(element.childNodes, function(element){
 12318     forEach(element.childNodes, function(element) {
 12287       if (element.nodeType === NODE_TYPE_ELEMENT)
 12319       if (element.nodeType === NODE_TYPE_ELEMENT)
 12288         children.push(element);
 12320         children.push(element);
 12289     });
 12321     });
 12290     return children;
 12322     return children;
 12291   },
 12323   },
 12307   },
 12339   },
 12308 
 12340 
 12309   prepend: function(element, node) {
 12341   prepend: function(element, node) {
 12310     if (element.nodeType === NODE_TYPE_ELEMENT) {
 12342     if (element.nodeType === NODE_TYPE_ELEMENT) {
 12311       var index = element.firstChild;
 12343       var index = element.firstChild;
 12312       forEach(new JQLite(node), function(child){
 12344       forEach(new JQLite(node), function(child) {
 12313         element.insertBefore(child, index);
 12345         element.insertBefore(child, index);
 12314       });
 12346       });
 12315     }
 12347     }
 12316   },
 12348   },
 12317 
 12349 
 12344   addClass: jqLiteAddClass,
 12376   addClass: jqLiteAddClass,
 12345   removeClass: jqLiteRemoveClass,
 12377   removeClass: jqLiteRemoveClass,
 12346 
 12378 
 12347   toggleClass: function(element, selector, condition) {
 12379   toggleClass: function(element, selector, condition) {
 12348     if (selector) {
 12380     if (selector) {
 12349       forEach(selector.split(' '), function(className){
 12381       forEach(selector.split(' '), function(className) {
 12350         var classCondition = condition;
 12382         var classCondition = condition;
 12351         if (isUndefined(classCondition)) {
 12383         if (isUndefined(classCondition)) {
 12352           classCondition = !jqLiteHasClass(element, className);
 12384           classCondition = !jqLiteHasClass(element, className);
 12353         }
 12385         }
 12354         (classCondition ? jqLiteAddClass : jqLiteRemoveClass)(element, className);
 12386         (classCondition ? jqLiteAddClass : jqLiteRemoveClass)(element, className);
 12409           fn.apply(element, handlerArgs);
 12441           fn.apply(element, handlerArgs);
 12410         }
 12442         }
 12411       });
 12443       });
 12412     }
 12444     }
 12413   }
 12445   }
 12414 }, function(fn, name){
 12446 }, function(fn, name) {
 12415   /**
 12447   /**
 12416    * chaining functions
 12448    * chaining functions
 12417    */
 12449    */
 12418   JQLite.prototype[name] = function(arg1, arg2, arg3) {
 12450   JQLite.prototype[name] = function(arg1, arg2, arg3) {
 12419     var value;
 12451     var value;
 12420 
 12452 
 12421     for(var i = 0, ii = this.length; i < ii; i++) {
 12453     for (var i = 0, ii = this.length; i < ii; i++) {
 12422       if (isUndefined(value)) {
 12454       if (isUndefined(value)) {
 12423         value = fn(this[i], arg1, arg2, arg3);
 12455         value = fn(this[i], arg1, arg2, arg3);
 12424         if (isDefined(value)) {
 12456         if (isDefined(value)) {
 12425           // any function which returns a value needs to be wrapped
 12457           // any function which returns a value needs to be wrapped
 12426           value = jqLite(value);
 12458           value = jqLite(value);
 12434 
 12466 
 12435   // bind legacy bind/unbind to on/off
 12467   // bind legacy bind/unbind to on/off
 12436   JQLite.prototype.bind = JQLite.prototype.on;
 12468   JQLite.prototype.bind = JQLite.prototype.on;
 12437   JQLite.prototype.unbind = JQLite.prototype.off;
 12469   JQLite.prototype.unbind = JQLite.prototype.off;
 12438 });
 12470 });
       
 12471 
       
 12472 
       
 12473 // Provider for private $$jqLite service
       
 12474 function $$jqLiteProvider() {
       
 12475   this.$get = function $$jqLite() {
       
 12476     return extend(JQLite, {
       
 12477       hasClass: function(node, classes) {
       
 12478         if (node.attr) node = node[0];
       
 12479         return jqLiteHasClass(node, classes);
       
 12480       },
       
 12481       addClass: function(node, classes) {
       
 12482         if (node.attr) node = node[0];
       
 12483         return jqLiteAddClass(node, classes);
       
 12484       },
       
 12485       removeClass: function(node, classes) {
       
 12486         if (node.attr) node = node[0];
       
 12487         return jqLiteRemoveClass(node, classes);
       
 12488       }
       
 12489     });
       
 12490   };
       
 12491 }
 12439 
 12492 
 12440 /**
 12493 /**
 12441  * Computes a hash of an 'obj'.
 12494  * Computes a hash of an 'obj'.
 12442  * Hash of a:
 12495  * Hash of a:
 12443  *  string is string
 12496  *  string is string
 12518  *
 12571  *
 12519  * @description
 12572  * @description
 12520  * Creates an injector object that can be used for retrieving services as well as for
 12573  * Creates an injector object that can be used for retrieving services as well as for
 12521  * dependency injection (see {@link guide/di dependency injection}).
 12574  * dependency injection (see {@link guide/di dependency injection}).
 12522  *
 12575  *
 12523 
       
 12524  * @param {Array.<string|Function>} modules A list of module functions or their aliases. See
 12576  * @param {Array.<string|Function>} modules A list of module functions or their aliases. See
 12525  *        {@link angular.module}. The `ng` module must be explicitly added.
 12577  *     {@link angular.module}. The `ng` module must be explicitly added.
 12526  * @returns {function()} Injector object. See {@link auto.$injector $injector}.
 12578  * @param {boolean=} [strictDi=false] Whether the injector should be in strict mode, which
       
 12579  *     disallows argument name annotation inference.
       
 12580  * @returns {injector} Injector object. See {@link auto.$injector $injector}.
 12527  *
 12581  *
 12528  * @example
 12582  * @example
 12529  * Typical usage
 12583  * Typical usage
 12530  * ```js
 12584  * ```js
 12531  *   // create an injector
 12585  *   // create an injector
 12666  * ```
 12720  * ```
 12667  *
 12721  *
 12668  * ## Inference
 12722  * ## Inference
 12669  *
 12723  *
 12670  * In JavaScript calling `toString()` on a function returns the function definition. The definition
 12724  * In JavaScript calling `toString()` on a function returns the function definition. The definition
 12671  * can then be parsed and the function arguments can be extracted. *NOTE:* This does not work with
 12725  * can then be parsed and the function arguments can be extracted. This method of discovering
 12672  * minification, and obfuscation tools since these tools change the argument names.
 12726  * annotations is disallowed when the injector is in strict mode.
       
 12727  * *NOTE:* This does not work with minification, and obfuscation tools since these tools change the
       
 12728  * argument names.
 12673  *
 12729  *
 12674  * ## `$inject` Annotation
 12730  * ## `$inject` Annotation
 12675  * By adding an `$inject` property onto a function the injection parameters can be specified.
 12731  * By adding an `$inject` property onto a function the injection parameters can be specified.
 12676  *
 12732  *
 12677  * ## Inline
 12733  * ## Inline
 12684  *
 12740  *
 12685  * @description
 12741  * @description
 12686  * Return an instance of the service.
 12742  * Return an instance of the service.
 12687  *
 12743  *
 12688  * @param {string} name The name of the instance to retrieve.
 12744  * @param {string} name The name of the instance to retrieve.
       
 12745  * @param {string} caller An optional string to provide the origin of the function call for error messages.
 12689  * @return {*} The instance.
 12746  * @return {*} The instance.
 12690  */
 12747  */
 12691 
 12748 
 12692 /**
 12749 /**
 12693  * @ngdoc method
 12750  * @ngdoc method
 12751  *   }
 12808  *   }
 12752  *
 12809  *
 12753  *   // Then
 12810  *   // Then
 12754  *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
 12811  *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
 12755  * ```
 12812  * ```
       
 12813  *
       
 12814  * You can disallow this method by using strict injection mode.
 12756  *
 12815  *
 12757  * This method does not work with code minification / obfuscation. For this reason the following
 12816  * This method does not work with code minification / obfuscation. For this reason the following
 12758  * annotation strategies are supported.
 12817  * annotation strategies are supported.
 12759  *
 12818  *
 12760  * # The `$inject` property
 12819  * # The `$inject` property
 12803  *    ).toEqual(['$compile', '$rootScope']);
 12862  *    ).toEqual(['$compile', '$rootScope']);
 12804  * ```
 12863  * ```
 12805  *
 12864  *
 12806  * @param {Function|Array.<string|Function>} fn Function for which dependent service names need to
 12865  * @param {Function|Array.<string|Function>} fn Function for which dependent service names need to
 12807  * be retrieved as described above.
 12866  * be retrieved as described above.
       
 12867  *
       
 12868  * @param {boolean=} [strictDi=false] Disallow argument name annotation inference.
 12808  *
 12869  *
 12809  * @returns {Array.<string>} The names of the services which the function requires.
 12870  * @returns {Array.<string>} The names of the services which the function requires.
 12810  */
 12871  */
 12811 
 12872 
 12812 
 12873 
 13130             constant: supportObject(constant),
 13191             constant: supportObject(constant),
 13131             decorator: decorator
 13192             decorator: decorator
 13132           }
 13193           }
 13133       },
 13194       },
 13134       providerInjector = (providerCache.$injector =
 13195       providerInjector = (providerCache.$injector =
 13135           createInternalInjector(providerCache, function() {
 13196           createInternalInjector(providerCache, function(serviceName, caller) {
       
 13197             if (angular.isString(caller)) {
       
 13198               path.push(caller);
       
 13199             }
 13136             throw $injectorMinErr('unpr', "Unknown provider: {0}", path.join(' <- '));
 13200             throw $injectorMinErr('unpr', "Unknown provider: {0}", path.join(' <- '));
 13137           })),
 13201           })),
 13138       instanceCache = {},
 13202       instanceCache = {},
 13139       instanceInjector = (instanceCache.$injector =
 13203       instanceInjector = (instanceCache.$injector =
 13140           createInternalInjector(instanceCache, function(servicename) {
 13204           createInternalInjector(instanceCache, function(serviceName, caller) {
 13141             var provider = providerInjector.get(servicename + providerSuffix);
 13205             var provider = providerInjector.get(serviceName + providerSuffix, caller);
 13142             return instanceInjector.invoke(provider.$get, provider, undefined, servicename);
 13206             return instanceInjector.invoke(provider.$get, provider, undefined, serviceName);
 13143           }));
 13207           }));
 13144 
 13208 
 13145 
 13209 
 13146   forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });
 13210   forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });
 13147 
 13211 
 13172     return providerCache[name + providerSuffix] = provider_;
 13236     return providerCache[name + providerSuffix] = provider_;
 13173   }
 13237   }
 13174 
 13238 
 13175   function enforceReturnValue(name, factory) {
 13239   function enforceReturnValue(name, factory) {
 13176     return function enforcedReturnValue() {
 13240     return function enforcedReturnValue() {
 13177       var result = instanceInjector.invoke(factory);
 13241       var result = instanceInjector.invoke(factory, this);
 13178       if (isUndefined(result)) {
 13242       if (isUndefined(result)) {
 13179         throw $injectorMinErr('undef', "Provider '{0}' must return a value from $get factory method.", name);
 13243         throw $injectorMinErr('undef', "Provider '{0}' must return a value from $get factory method.", name);
 13180       }
 13244       }
 13181       return result;
 13245       return result;
 13182     };
 13246     };
 13213   }
 13277   }
 13214 
 13278 
 13215   ////////////////////////////////////
 13279   ////////////////////////////////////
 13216   // Module Loading
 13280   // Module Loading
 13217   ////////////////////////////////////
 13281   ////////////////////////////////////
 13218   function loadModules(modulesToLoad){
 13282   function loadModules(modulesToLoad) {
 13219     var runBlocks = [], moduleFn;
 13283     var runBlocks = [], moduleFn;
 13220     forEach(modulesToLoad, function(module) {
 13284     forEach(modulesToLoad, function(module) {
 13221       if (loadedModules.get(module)) return;
 13285       if (loadedModules.get(module)) return;
 13222       loadedModules.put(module, true);
 13286       loadedModules.put(module, true);
 13223 
 13287 
 13224       function runInvokeQueue(queue) {
 13288       function runInvokeQueue(queue) {
 13225         var i, ii;
 13289         var i, ii;
 13226         for(i = 0, ii = queue.length; i < ii; i++) {
 13290         for (i = 0, ii = queue.length; i < ii; i++) {
 13227           var invokeArgs = queue[i],
 13291           var invokeArgs = queue[i],
 13228               provider = providerInjector.get(invokeArgs[0]);
 13292               provider = providerInjector.get(invokeArgs[0]);
 13229 
 13293 
 13230           provider[invokeArgs[1]].apply(provider, invokeArgs[2]);
 13294           provider[invokeArgs[1]].apply(provider, invokeArgs[2]);
 13231         }
 13295         }
 13267   // internal Injector
 13331   // internal Injector
 13268   ////////////////////////////////////
 13332   ////////////////////////////////////
 13269 
 13333 
 13270   function createInternalInjector(cache, factory) {
 13334   function createInternalInjector(cache, factory) {
 13271 
 13335 
 13272     function getService(serviceName) {
 13336     function getService(serviceName, caller) {
 13273       if (cache.hasOwnProperty(serviceName)) {
 13337       if (cache.hasOwnProperty(serviceName)) {
 13274         if (cache[serviceName] === INSTANTIATING) {
 13338         if (cache[serviceName] === INSTANTIATING) {
 13275           throw $injectorMinErr('cdep', 'Circular dependency found: {0}',
 13339           throw $injectorMinErr('cdep', 'Circular dependency found: {0}',
 13276                     serviceName + ' <- ' + path.join(' <- '));
 13340                     serviceName + ' <- ' + path.join(' <- '));
 13277         }
 13341         }
 13278         return cache[serviceName];
 13342         return cache[serviceName];
 13279       } else {
 13343       } else {
 13280         try {
 13344         try {
 13281           path.unshift(serviceName);
 13345           path.unshift(serviceName);
 13282           cache[serviceName] = INSTANTIATING;
 13346           cache[serviceName] = INSTANTIATING;
 13283           return cache[serviceName] = factory(serviceName);
 13347           return cache[serviceName] = factory(serviceName, caller);
 13284         } catch (err) {
 13348         } catch (err) {
 13285           if (cache[serviceName] === INSTANTIATING) {
 13349           if (cache[serviceName] === INSTANTIATING) {
 13286             delete cache[serviceName];
 13350             delete cache[serviceName];
 13287           }
 13351           }
 13288           throw err;
 13352           throw err;
 13301       var args = [],
 13365       var args = [],
 13302           $inject = annotate(fn, strictDi, serviceName),
 13366           $inject = annotate(fn, strictDi, serviceName),
 13303           length, i,
 13367           length, i,
 13304           key;
 13368           key;
 13305 
 13369 
 13306       for(i = 0, length = $inject.length; i < length; i++) {
 13370       for (i = 0, length = $inject.length; i < length; i++) {
 13307         key = $inject[i];
 13371         key = $inject[i];
 13308         if (typeof key !== 'string') {
 13372         if (typeof key !== 'string') {
 13309           throw $injectorMinErr('itkn',
 13373           throw $injectorMinErr('itkn',
 13310                   'Incorrect injection token! Expected service name as string, got {0}', key);
 13374                   'Incorrect injection token! Expected service name as string, got {0}', key);
 13311         }
 13375         }
 13312         args.push(
 13376         args.push(
 13313           locals && locals.hasOwnProperty(key)
 13377           locals && locals.hasOwnProperty(key)
 13314           ? locals[key]
 13378           ? locals[key]
 13315           : getService(key)
 13379           : getService(key, serviceName)
 13316         );
 13380         );
 13317       }
 13381       }
 13318       if (isArray(fn)) {
 13382       if (isArray(fn)) {
 13319         fn = fn[length];
 13383         fn = fn[length];
 13320       }
 13384       }
 13323       // #5388
 13387       // #5388
 13324       return fn.apply(self, args);
 13388       return fn.apply(self, args);
 13325     }
 13389     }
 13326 
 13390 
 13327     function instantiate(Type, locals, serviceName) {
 13391     function instantiate(Type, locals, serviceName) {
 13328       var Constructor = function() {},
       
 13329           instance, returnedValue;
       
 13330 
       
 13331       // Check if Type is annotated and use just the given function at n-1 as parameter
 13392       // Check if Type is annotated and use just the given function at n-1 as parameter
 13332       // e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]);
 13393       // e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]);
 13333       Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;
 13394       // Object creation: http://jsperf.com/create-constructor/2
 13334       instance = new Constructor();
 13395       var instance = Object.create((isArray(Type) ? Type[Type.length - 1] : Type).prototype);
 13335       returnedValue = invoke(Type, instance, locals, serviceName);
 13396       var returnedValue = invoke(Type, instance, locals, serviceName);
 13336 
 13397 
 13337       return isObject(returnedValue) || isFunction(returnedValue) ? returnedValue : instance;
 13398       return isObject(returnedValue) || isFunction(returnedValue) ? returnedValue : instance;
 13338     }
 13399     }
 13339 
 13400 
 13340     return {
 13401     return {
 13350 }
 13411 }
 13351 
 13412 
 13352 createInjector.$$annotate = annotate;
 13413 createInjector.$$annotate = annotate;
 13353 
 13414 
 13354 /**
 13415 /**
 13355  * @ngdoc service
 13416  * @ngdoc provider
 13356  * @name $anchorScroll
 13417  * @name $anchorScrollProvider
 13357  * @kind function
       
 13358  * @requires $window
       
 13359  * @requires $location
       
 13360  * @requires $rootScope
       
 13361  *
 13418  *
 13362  * @description
 13419  * @description
 13363  * When called, it checks current value of `$location.hash()` and scrolls to the related element,
 13420  * Use `$anchorScrollProvider` to disable automatic scrolling whenever
 13364  * according to rules specified in
 13421  * {@link ng.$location#hash $location.hash()} changes.
 13365  * [Html5 spec](http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document).
       
 13366  *
       
 13367  * It also watches the `$location.hash()` and scrolls whenever it changes to match any anchor.
       
 13368  * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.
       
 13369  *
       
 13370  * @example
       
 13371    <example module="anchorScrollExample">
       
 13372      <file name="index.html">
       
 13373        <div id="scrollArea" ng-controller="ScrollController">
       
 13374          <a ng-click="gotoBottom()">Go to bottom</a>
       
 13375          <a id="bottom"></a> You're at the bottom!
       
 13376        </div>
       
 13377      </file>
       
 13378      <file name="script.js">
       
 13379        angular.module('anchorScrollExample', [])
       
 13380          .controller('ScrollController', ['$scope', '$location', '$anchorScroll',
       
 13381            function ($scope, $location, $anchorScroll) {
       
 13382              $scope.gotoBottom = function() {
       
 13383                // set the location.hash to the id of
       
 13384                // the element you wish to scroll to.
       
 13385                $location.hash('bottom');
       
 13386 
       
 13387                // call $anchorScroll()
       
 13388                $anchorScroll();
       
 13389              };
       
 13390            }]);
       
 13391      </file>
       
 13392      <file name="style.css">
       
 13393        #scrollArea {
       
 13394          height: 350px;
       
 13395          overflow: auto;
       
 13396        }
       
 13397 
       
 13398        #bottom {
       
 13399          display: block;
       
 13400          margin-top: 2000px;
       
 13401        }
       
 13402      </file>
       
 13403    </example>
       
 13404  */
 13422  */
 13405 function $AnchorScrollProvider() {
 13423 function $AnchorScrollProvider() {
 13406 
 13424 
 13407   var autoScrollingEnabled = true;
 13425   var autoScrollingEnabled = true;
 13408 
 13426 
       
 13427   /**
       
 13428    * @ngdoc method
       
 13429    * @name $anchorScrollProvider#disableAutoScrolling
       
 13430    *
       
 13431    * @description
       
 13432    * By default, {@link ng.$anchorScroll $anchorScroll()} will automatically detect changes to
       
 13433    * {@link ng.$location#hash $location.hash()} and scroll to the element matching the new hash.<br />
       
 13434    * Use this method to disable automatic scrolling.
       
 13435    *
       
 13436    * If automatic scrolling is disabled, one must explicitly call
       
 13437    * {@link ng.$anchorScroll $anchorScroll()} in order to scroll to the element related to the
       
 13438    * current hash.
       
 13439    */
 13409   this.disableAutoScrolling = function() {
 13440   this.disableAutoScrolling = function() {
 13410     autoScrollingEnabled = false;
 13441     autoScrollingEnabled = false;
 13411   };
 13442   };
 13412 
 13443 
       
 13444   /**
       
 13445    * @ngdoc service
       
 13446    * @name $anchorScroll
       
 13447    * @kind function
       
 13448    * @requires $window
       
 13449    * @requires $location
       
 13450    * @requires $rootScope
       
 13451    *
       
 13452    * @description
       
 13453    * When called, it checks the current value of {@link ng.$location#hash $location.hash()} and
       
 13454    * scrolls to the related element, according to the rules specified in the
       
 13455    * [Html5 spec](http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document).
       
 13456    *
       
 13457    * It also watches the {@link ng.$location#hash $location.hash()} and automatically scrolls to
       
 13458    * match any anchor whenever it changes. This can be disabled by calling
       
 13459    * {@link ng.$anchorScrollProvider#disableAutoScrolling $anchorScrollProvider.disableAutoScrolling()}.
       
 13460    *
       
 13461    * Additionally, you can use its {@link ng.$anchorScroll#yOffset yOffset} property to specify a
       
 13462    * vertical scroll-offset (either fixed or dynamic).
       
 13463    *
       
 13464    * @property {(number|function|jqLite)} yOffset
       
 13465    * If set, specifies a vertical scroll-offset. This is often useful when there are fixed
       
 13466    * positioned elements at the top of the page, such as navbars, headers etc.
       
 13467    *
       
 13468    * `yOffset` can be specified in various ways:
       
 13469    * - **number**: A fixed number of pixels to be used as offset.<br /><br />
       
 13470    * - **function**: A getter function called everytime `$anchorScroll()` is executed. Must return
       
 13471    *   a number representing the offset (in pixels).<br /><br />
       
 13472    * - **jqLite**: A jqLite/jQuery element to be used for specifying the offset. The distance from
       
 13473    *   the top of the page to the element's bottom will be used as offset.<br />
       
 13474    *   **Note**: The element will be taken into account only as long as its `position` is set to
       
 13475    *   `fixed`. This option is useful, when dealing with responsive navbars/headers that adjust
       
 13476    *   their height and/or positioning according to the viewport's size.
       
 13477    *
       
 13478    * <br />
       
 13479    * <div class="alert alert-warning">
       
 13480    * In order for `yOffset` to work properly, scrolling should take place on the document's root and
       
 13481    * not some child element.
       
 13482    * </div>
       
 13483    *
       
 13484    * @example
       
 13485      <example module="anchorScrollExample">
       
 13486        <file name="index.html">
       
 13487          <div id="scrollArea" ng-controller="ScrollController">
       
 13488            <a ng-click="gotoBottom()">Go to bottom</a>
       
 13489            <a id="bottom"></a> You're at the bottom!
       
 13490          </div>
       
 13491        </file>
       
 13492        <file name="script.js">
       
 13493          angular.module('anchorScrollExample', [])
       
 13494            .controller('ScrollController', ['$scope', '$location', '$anchorScroll',
       
 13495              function ($scope, $location, $anchorScroll) {
       
 13496                $scope.gotoBottom = function() {
       
 13497                  // set the location.hash to the id of
       
 13498                  // the element you wish to scroll to.
       
 13499                  $location.hash('bottom');
       
 13500 
       
 13501                  // call $anchorScroll()
       
 13502                  $anchorScroll();
       
 13503                };
       
 13504              }]);
       
 13505        </file>
       
 13506        <file name="style.css">
       
 13507          #scrollArea {
       
 13508            height: 280px;
       
 13509            overflow: auto;
       
 13510          }
       
 13511 
       
 13512          #bottom {
       
 13513            display: block;
       
 13514            margin-top: 2000px;
       
 13515          }
       
 13516        </file>
       
 13517      </example>
       
 13518    *
       
 13519    * <hr />
       
 13520    * The example below illustrates the use of a vertical scroll-offset (specified as a fixed value).
       
 13521    * See {@link ng.$anchorScroll#yOffset $anchorScroll.yOffset} for more details.
       
 13522    *
       
 13523    * @example
       
 13524      <example module="anchorScrollOffsetExample">
       
 13525        <file name="index.html">
       
 13526          <div class="fixed-header" ng-controller="headerCtrl">
       
 13527            <a href="" ng-click="gotoAnchor(x)" ng-repeat="x in [1,2,3,4,5]">
       
 13528              Go to anchor {{x}}
       
 13529            </a>
       
 13530          </div>
       
 13531          <div id="anchor{{x}}" class="anchor" ng-repeat="x in [1,2,3,4,5]">
       
 13532            Anchor {{x}} of 5
       
 13533          </div>
       
 13534        </file>
       
 13535        <file name="script.js">
       
 13536          angular.module('anchorScrollOffsetExample', [])
       
 13537            .run(['$anchorScroll', function($anchorScroll) {
       
 13538              $anchorScroll.yOffset = 50;   // always scroll by 50 extra pixels
       
 13539            }])
       
 13540            .controller('headerCtrl', ['$anchorScroll', '$location', '$scope',
       
 13541              function ($anchorScroll, $location, $scope) {
       
 13542                $scope.gotoAnchor = function(x) {
       
 13543                  var newHash = 'anchor' + x;
       
 13544                  if ($location.hash() !== newHash) {
       
 13545                    // set the $location.hash to `newHash` and
       
 13546                    // $anchorScroll will automatically scroll to it
       
 13547                    $location.hash('anchor' + x);
       
 13548                  } else {
       
 13549                    // call $anchorScroll() explicitly,
       
 13550                    // since $location.hash hasn't changed
       
 13551                    $anchorScroll();
       
 13552                  }
       
 13553                };
       
 13554              }
       
 13555            ]);
       
 13556        </file>
       
 13557        <file name="style.css">
       
 13558          body {
       
 13559            padding-top: 50px;
       
 13560          }
       
 13561 
       
 13562          .anchor {
       
 13563            border: 2px dashed DarkOrchid;
       
 13564            padding: 10px 10px 200px 10px;
       
 13565          }
       
 13566 
       
 13567          .fixed-header {
       
 13568            background-color: rgba(0, 0, 0, 0.2);
       
 13569            height: 50px;
       
 13570            position: fixed;
       
 13571            top: 0; left: 0; right: 0;
       
 13572          }
       
 13573 
       
 13574          .fixed-header > a {
       
 13575            display: inline-block;
       
 13576            margin: 5px 15px;
       
 13577          }
       
 13578        </file>
       
 13579      </example>
       
 13580    */
 13413   this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {
 13581   this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {
 13414     var document = $window.document;
 13582     var document = $window.document;
 13415 
 13583 
 13416     // helper function to get first anchor from a NodeList
 13584     // Helper function to get first anchor from a NodeList
 13417     // can't use filter.filter, as it accepts only instances of Array
 13585     // (using `Array#some()` instead of `angular#forEach()` since it's more performant
 13418     // and IE can't convert NodeList to an array using [].slice
 13586     //  and working in all supported browsers.)
 13419     // TODO(vojta): use filter if we change it to accept lists as well
       
 13420     function getFirstAnchor(list) {
 13587     function getFirstAnchor(list) {
 13421       var result = null;
 13588       var result = null;
 13422       forEach(list, function(element) {
 13589       Array.prototype.some.call(list, function(element) {
 13423         if (!result && nodeName_(element) === 'a') result = element;
 13590         if (nodeName_(element) === 'a') {
       
 13591           result = element;
       
 13592           return true;
       
 13593         }
 13424       });
 13594       });
 13425       return result;
 13595       return result;
 13426     }
 13596     }
 13427 
 13597 
       
 13598     function getYOffset() {
       
 13599 
       
 13600       var offset = scroll.yOffset;
       
 13601 
       
 13602       if (isFunction(offset)) {
       
 13603         offset = offset();
       
 13604       } else if (isElement(offset)) {
       
 13605         var elem = offset[0];
       
 13606         var style = $window.getComputedStyle(elem);
       
 13607         if (style.position !== 'fixed') {
       
 13608           offset = 0;
       
 13609         } else {
       
 13610           offset = elem.getBoundingClientRect().bottom;
       
 13611         }
       
 13612       } else if (!isNumber(offset)) {
       
 13613         offset = 0;
       
 13614       }
       
 13615 
       
 13616       return offset;
       
 13617     }
       
 13618 
       
 13619     function scrollTo(elem) {
       
 13620       if (elem) {
       
 13621         elem.scrollIntoView();
       
 13622 
       
 13623         var offset = getYOffset();
       
 13624 
       
 13625         if (offset) {
       
 13626           // `offset` is the number of pixels we should scroll UP in order to align `elem` properly.
       
 13627           // This is true ONLY if the call to `elem.scrollIntoView()` initially aligns `elem` at the
       
 13628           // top of the viewport.
       
 13629           //
       
 13630           // IF the number of pixels from the top of `elem` to the end of the page's content is less
       
 13631           // than the height of the viewport, then `elem.scrollIntoView()` will align the `elem` some
       
 13632           // way down the page.
       
 13633           //
       
 13634           // This is often the case for elements near the bottom of the page.
       
 13635           //
       
 13636           // In such cases we do not need to scroll the whole `offset` up, just the difference between
       
 13637           // the top of the element and the offset, which is enough to align the top of `elem` at the
       
 13638           // desired position.
       
 13639           var elemTop = elem.getBoundingClientRect().top;
       
 13640           $window.scrollBy(0, elemTop - offset);
       
 13641         }
       
 13642       } else {
       
 13643         $window.scrollTo(0, 0);
       
 13644       }
       
 13645     }
       
 13646 
 13428     function scroll() {
 13647     function scroll() {
 13429       var hash = $location.hash(), elm;
 13648       var hash = $location.hash(), elm;
 13430 
 13649 
 13431       // empty hash, scroll to the top of the page
 13650       // empty hash, scroll to the top of the page
 13432       if (!hash) $window.scrollTo(0, 0);
 13651       if (!hash) scrollTo(null);
 13433 
 13652 
 13434       // element with given id
 13653       // element with given id
 13435       else if ((elm = document.getElementById(hash))) elm.scrollIntoView();
 13654       else if ((elm = document.getElementById(hash))) scrollTo(elm);
 13436 
 13655 
 13437       // first anchor with given name :-D
 13656       // first anchor with given name :-D
 13438       else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();
 13657       else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) scrollTo(elm);
 13439 
 13658 
 13440       // no element and hash == 'top', scroll to the top of the page
 13659       // no element and hash == 'top', scroll to the top of the page
 13441       else if (hash === 'top') $window.scrollTo(0, 0);
 13660       else if (hash === 'top') scrollTo(null);
 13442     }
 13661     }
 13443 
 13662 
 13444     // does not scroll when user clicks on anchor link that is currently on
 13663     // does not scroll when user clicks on anchor link that is currently on
 13445     // (no url change, no $location.hash() change), browser native does scroll
 13664     // (no url change, no $location.hash() change), browser native does scroll
 13446     if (autoScrollingEnabled) {
 13665     if (autoScrollingEnabled) {
 13447       $rootScope.$watch(function autoScrollWatch() {return $location.hash();},
 13666       $rootScope.$watch(function autoScrollWatch() {return $location.hash();},
 13448         function autoScrollWatchAction(newVal, oldVal) {
 13667         function autoScrollWatchAction(newVal, oldVal) {
 13449           // skip the initial scroll if $location.hash is empty
 13668           // skip the initial scroll if $location.hash is empty
 13450           if (newVal === oldVal && newVal === '') return;
 13669           if (newVal === oldVal && newVal === '') return;
 13451 
 13670 
 13452           $rootScope.$evalAsync(scroll);
 13671           jqLiteDocumentLoaded(function() {
       
 13672             $rootScope.$evalAsync(scroll);
       
 13673           });
 13453         });
 13674         });
 13454     }
 13675     }
 13455 
 13676 
 13456     return scroll;
 13677     return scroll;
 13457   }];
 13678   }];
 13530    * for low-powered devices as well as applications containing a lot of structural operations.
 13751    * for low-powered devices as well as applications containing a lot of structural operations.
 13531    * @param {RegExp=} expression The className expression which will be checked against all animations
 13752    * @param {RegExp=} expression The className expression which will be checked against all animations
 13532    * @return {RegExp} The current CSS className expression value. If null then there is no expression value
 13753    * @return {RegExp} The current CSS className expression value. If null then there is no expression value
 13533    */
 13754    */
 13534   this.classNameFilter = function(expression) {
 13755   this.classNameFilter = function(expression) {
 13535     if(arguments.length === 1) {
 13756     if (arguments.length === 1) {
 13536       this.$$classNameFilter = (expression instanceof RegExp) ? expression : null;
 13757       this.$$classNameFilter = (expression instanceof RegExp) ? expression : null;
 13537     }
 13758     }
 13538     return this.$$classNameFilter;
 13759     return this.$$classNameFilter;
 13539   };
 13760   };
 13540 
 13761 
 13555       });
 13776       });
 13556 
 13777 
 13557       return defer.promise;
 13778       return defer.promise;
 13558     }
 13779     }
 13559 
 13780 
 13560     function resolveElementClasses(element, cache) {
 13781     function resolveElementClasses(element, classes) {
 13561       var toAdd = [], toRemove = [];
 13782       var toAdd = [], toRemove = [];
 13562 
 13783 
 13563       var hasClasses = createMap();
 13784       var hasClasses = createMap();
 13564       forEach((element.attr('class') || '').split(/\s+/), function(className) {
 13785       forEach((element.attr('class') || '').split(/\s+/), function(className) {
 13565         hasClasses[className] = true;
 13786         hasClasses[className] = true;
 13566       });
 13787       });
 13567 
 13788 
 13568       forEach(cache.classes, function(status, className) {
 13789       forEach(classes, function(status, className) {
 13569         var hasClass = hasClasses[className];
 13790         var hasClass = hasClasses[className];
 13570 
 13791 
 13571         // If the most recent class manipulation (via $animate) was to remove the class, and the
 13792         // If the most recent class manipulation (via $animate) was to remove the class, and the
 13572         // element currently has the class, the class is scheduled for removal. Otherwise, if
 13793         // element currently has the class, the class is scheduled for removal. Otherwise, if
 13573         // the most recent class manipulation (via $animate) was to add the class, and the
 13794         // the most recent class manipulation (via $animate) was to add the class, and the
 13577         } else if (status === true && !hasClass) {
 13798         } else if (status === true && !hasClass) {
 13578           toAdd.push(className);
 13799           toAdd.push(className);
 13579         }
 13800         }
 13580       });
 13801       });
 13581 
 13802 
 13582       return (toAdd.length + toRemove.length) > 0 && [toAdd.length && toAdd, toRemove.length && toRemove];
 13803       return (toAdd.length + toRemove.length) > 0 &&
       
 13804         [toAdd.length ? toAdd : null, toRemove.length ? toRemove : null];
 13583     }
 13805     }
 13584 
 13806 
 13585     function cachedClassManipulation(cache, classes, op) {
 13807     function cachedClassManipulation(cache, classes, op) {
 13586       for (var i=0, ii = classes.length; i < ii; ++i) {
 13808       for (var i=0, ii = classes.length; i < ii; ++i) {
 13587         var className = classes[i];
 13809         var className = classes[i];
 13597           currentDefer.resolve();
 13819           currentDefer.resolve();
 13598           currentDefer = null;
 13820           currentDefer = null;
 13599         });
 13821         });
 13600       }
 13822       }
 13601       return currentDefer.promise;
 13823       return currentDefer.promise;
       
 13824     }
       
 13825 
       
 13826     function applyStyles(element, options) {
       
 13827       if (angular.isObject(options)) {
       
 13828         var styles = extend(options.from || {}, options.to || {});
       
 13829         element.css(styles);
       
 13830       }
 13602     }
 13831     }
 13603 
 13832 
 13604     /**
 13833     /**
 13605      *
 13834      *
 13606      * @ngdoc service
 13835      * @ngdoc service
 13617      * To learn more about enabling animation support, click here to visit the {@link ngAnimate
 13846      * To learn more about enabling animation support, click here to visit the {@link ngAnimate
 13618      * ngAnimate module page} as well as the {@link ngAnimate.$animate ngAnimate $animate service
 13847      * ngAnimate module page} as well as the {@link ngAnimate.$animate ngAnimate $animate service
 13619      * page}.
 13848      * page}.
 13620      */
 13849      */
 13621     return {
 13850     return {
       
 13851       animate: function(element, from, to) {
       
 13852         applyStyles(element, { from: from, to: to });
       
 13853         return asyncPromise();
       
 13854       },
 13622 
 13855 
 13623       /**
 13856       /**
 13624        *
 13857        *
 13625        * @ngdoc method
 13858        * @ngdoc method
 13626        * @name $animate#enter
 13859        * @name $animate#enter
 13631        * @param {DOMElement} element the element which will be inserted into the DOM
 13864        * @param {DOMElement} element the element which will be inserted into the DOM
 13632        * @param {DOMElement} parent the parent element which will append the element as
 13865        * @param {DOMElement} parent the parent element which will append the element as
 13633        *   a child (if the after element is not present)
 13866        *   a child (if the after element is not present)
 13634        * @param {DOMElement} after the sibling element which will append the element
 13867        * @param {DOMElement} after the sibling element which will append the element
 13635        *   after itself
 13868        *   after itself
       
 13869        * @param {object=} options an optional collection of styles that will be applied to the element.
 13636        * @return {Promise} the animation callback promise
 13870        * @return {Promise} the animation callback promise
 13637        */
 13871        */
 13638       enter : function(element, parent, after) {
 13872       enter: function(element, parent, after, options) {
       
 13873         applyStyles(element, options);
 13639         after ? after.after(element)
 13874         after ? after.after(element)
 13640               : parent.prepend(element);
 13875               : parent.prepend(element);
 13641         return asyncPromise();
 13876         return asyncPromise();
 13642       },
 13877       },
 13643 
 13878 
 13647        * @name $animate#leave
 13882        * @name $animate#leave
 13648        * @kind function
 13883        * @kind function
 13649        * @description Removes the element from the DOM. When the function is called a promise
 13884        * @description Removes the element from the DOM. When the function is called a promise
 13650        * is returned that will be resolved at a later time.
 13885        * is returned that will be resolved at a later time.
 13651        * @param {DOMElement} element the element which will be removed from the DOM
 13886        * @param {DOMElement} element the element which will be removed from the DOM
       
 13887        * @param {object=} options an optional collection of options that will be applied to the element.
 13652        * @return {Promise} the animation callback promise
 13888        * @return {Promise} the animation callback promise
 13653        */
 13889        */
 13654       leave : function(element) {
 13890       leave: function(element, options) {
 13655         element.remove();
 13891         element.remove();
 13656         return asyncPromise();
 13892         return asyncPromise();
 13657       },
 13893       },
 13658 
 13894 
 13659       /**
 13895       /**
 13669        *   DOM
 13905        *   DOM
 13670        * @param {DOMElement} parent the parent element where the element will be
 13906        * @param {DOMElement} parent the parent element where the element will be
 13671        *   inserted into (if the after element is not present)
 13907        *   inserted into (if the after element is not present)
 13672        * @param {DOMElement} after the sibling element where the element will be
 13908        * @param {DOMElement} after the sibling element where the element will be
 13673        *   positioned next to
 13909        *   positioned next to
       
 13910        * @param {object=} options an optional collection of options that will be applied to the element.
 13674        * @return {Promise} the animation callback promise
 13911        * @return {Promise} the animation callback promise
 13675        */
 13912        */
 13676       move : function(element, parent, after) {
 13913       move: function(element, parent, after, options) {
 13677         // Do not remove element before insert. Removing will cause data associated with the
 13914         // Do not remove element before insert. Removing will cause data associated with the
 13678         // element to be dropped. Insert will implicitly do the remove.
 13915         // element to be dropped. Insert will implicitly do the remove.
 13679         return this.enter(element, parent, after);
 13916         return this.enter(element, parent, after, options);
 13680       },
 13917       },
 13681 
 13918 
 13682       /**
 13919       /**
 13683        *
 13920        *
 13684        * @ngdoc method
 13921        * @ngdoc method
 13687        * @description Adds the provided className CSS class value to the provided element.
 13924        * @description Adds the provided className CSS class value to the provided element.
 13688        * When the function is called a promise is returned that will be resolved at a later time.
 13925        * When the function is called a promise is returned that will be resolved at a later time.
 13689        * @param {DOMElement} element the element which will have the className value
 13926        * @param {DOMElement} element the element which will have the className value
 13690        *   added to it
 13927        *   added to it
 13691        * @param {string} className the CSS class which will be added to the element
 13928        * @param {string} className the CSS class which will be added to the element
       
 13929        * @param {object=} options an optional collection of options that will be applied to the element.
 13692        * @return {Promise} the animation callback promise
 13930        * @return {Promise} the animation callback promise
 13693        */
 13931        */
 13694       addClass : function(element, className) {
 13932       addClass: function(element, className, options) {
 13695         return this.setClass(element, className, []);
 13933         return this.setClass(element, className, [], options);
 13696       },
 13934       },
 13697 
 13935 
 13698       $$addClassImmediately : function addClassImmediately(element, className) {
 13936       $$addClassImmediately: function(element, className, options) {
 13699         element = jqLite(element);
 13937         element = jqLite(element);
 13700         className = !isString(className)
 13938         className = !isString(className)
 13701                         ? (isArray(className) ? className.join(' ') : '')
 13939                         ? (isArray(className) ? className.join(' ') : '')
 13702                         : className;
 13940                         : className;
 13703         forEach(element, function (element) {
 13941         forEach(element, function(element) {
 13704           jqLiteAddClass(element, className);
 13942           jqLiteAddClass(element, className);
 13705         });
 13943         });
       
 13944         applyStyles(element, options);
       
 13945         return asyncPromise();
 13706       },
 13946       },
 13707 
 13947 
 13708       /**
 13948       /**
 13709        *
 13949        *
 13710        * @ngdoc method
 13950        * @ngdoc method
 13713        * @description Removes the provided className CSS class value from the provided element.
 13953        * @description Removes the provided className CSS class value from the provided element.
 13714        * When the function is called a promise is returned that will be resolved at a later time.
 13954        * When the function is called a promise is returned that will be resolved at a later time.
 13715        * @param {DOMElement} element the element which will have the className value
 13955        * @param {DOMElement} element the element which will have the className value
 13716        *   removed from it
 13956        *   removed from it
 13717        * @param {string} className the CSS class which will be removed from the element
 13957        * @param {string} className the CSS class which will be removed from the element
       
 13958        * @param {object=} options an optional collection of options that will be applied to the element.
 13718        * @return {Promise} the animation callback promise
 13959        * @return {Promise} the animation callback promise
 13719        */
 13960        */
 13720       removeClass : function(element, className) {
 13961       removeClass: function(element, className, options) {
 13721         return this.setClass(element, [], className);
 13962         return this.setClass(element, [], className, options);
 13722       },
 13963       },
 13723 
 13964 
 13724       $$removeClassImmediately : function removeClassImmediately(element, className) {
 13965       $$removeClassImmediately: function(element, className, options) {
 13725         element = jqLite(element);
 13966         element = jqLite(element);
 13726         className = !isString(className)
 13967         className = !isString(className)
 13727                         ? (isArray(className) ? className.join(' ') : '')
 13968                         ? (isArray(className) ? className.join(' ') : '')
 13728                         : className;
 13969                         : className;
 13729         forEach(element, function (element) {
 13970         forEach(element, function(element) {
 13730           jqLiteRemoveClass(element, className);
 13971           jqLiteRemoveClass(element, className);
 13731         });
 13972         });
       
 13973         applyStyles(element, options);
 13732         return asyncPromise();
 13974         return asyncPromise();
 13733       },
 13975       },
 13734 
 13976 
 13735       /**
 13977       /**
 13736        *
 13978        *
 13741        * When the function is called a promise is returned that will be resolved at a later time.
 13983        * When the function is called a promise is returned that will be resolved at a later time.
 13742        * @param {DOMElement} element the element which will have its CSS classes changed
 13984        * @param {DOMElement} element the element which will have its CSS classes changed
 13743        *   removed from it
 13985        *   removed from it
 13744        * @param {string} add the CSS classes which will be added to the element
 13986        * @param {string} add the CSS classes which will be added to the element
 13745        * @param {string} remove the CSS class which will be removed from the element
 13987        * @param {string} remove the CSS class which will be removed from the element
       
 13988        * @param {object=} options an optional collection of options that will be applied to the element.
 13746        * @return {Promise} the animation callback promise
 13989        * @return {Promise} the animation callback promise
 13747        */
 13990        */
 13748       setClass : function(element, add, remove, runSynchronously) {
 13991       setClass: function(element, add, remove, options) {
 13749         var self = this;
 13992         var self = this;
 13750         var STORAGE_KEY = '$$animateClasses';
 13993         var STORAGE_KEY = '$$animateClasses';
 13751         var createdCache = false;
 13994         var createdCache = false;
 13752         element = jqLite(element);
 13995         element = jqLite(element);
 13753 
 13996 
 13754         if (runSynchronously) {
       
 13755           // TODO(@caitp/@matsko): Remove undocumented `runSynchronously` parameter, and always
       
 13756           // perform DOM manipulation asynchronously or in postDigest.
       
 13757           self.$$addClassImmediately(element, add);
       
 13758           self.$$removeClassImmediately(element, remove);
       
 13759           return asyncPromise();
       
 13760         }
       
 13761 
       
 13762         var cache = element.data(STORAGE_KEY);
 13997         var cache = element.data(STORAGE_KEY);
 13763         if (!cache) {
 13998         if (!cache) {
 13764           cache = {
 13999           cache = {
 13765             classes: {}
 14000             classes: {},
       
 14001             options: options
 13766           };
 14002           };
 13767           createdCache = true;
 14003           createdCache = true;
       
 14004         } else if (options && cache.options) {
       
 14005           cache.options = angular.extend(cache.options || {}, options);
 13768         }
 14006         }
 13769 
 14007 
 13770         var classes = cache.classes;
 14008         var classes = cache.classes;
 13771 
 14009 
 13772         add = isArray(add) ? add : add.split(' ');
 14010         add = isArray(add) ? add : add.split(' ');
 13777         if (createdCache) {
 14015         if (createdCache) {
 13778           cache.promise = runAnimationPostDigest(function(done) {
 14016           cache.promise = runAnimationPostDigest(function(done) {
 13779             var cache = element.data(STORAGE_KEY);
 14017             var cache = element.data(STORAGE_KEY);
 13780             element.removeData(STORAGE_KEY);
 14018             element.removeData(STORAGE_KEY);
 13781 
 14019 
 13782             var classes = cache && resolveElementClasses(element, cache);
 14020             // in the event that the element is removed before postDigest
 13783 
 14021             // is run then the cache will be undefined and there will be
 13784             if (classes) {
 14022             // no need anymore to add or remove and of the element classes
 13785               if (classes[0]) self.$$addClassImmediately(element, classes[0]);
 14023             if (cache) {
 13786               if (classes[1]) self.$$removeClassImmediately(element, classes[1]);
 14024               var classes = resolveElementClasses(element, cache.classes);
       
 14025               if (classes) {
       
 14026                 self.$$setClassImmediately(element, classes[0], classes[1], cache.options);
       
 14027               }
 13787             }
 14028             }
 13788 
 14029 
 13789             done();
 14030             done();
 13790           });
 14031           });
 13791           element.data(STORAGE_KEY, cache);
 14032           element.data(STORAGE_KEY, cache);
 13792         }
 14033         }
 13793 
 14034 
 13794         return cache.promise;
 14035         return cache.promise;
 13795       },
 14036       },
 13796 
 14037 
 13797       enabled : noop,
 14038       $$setClassImmediately: function(element, add, remove, options) {
 13798       cancel : noop
 14039         add && this.$$addClassImmediately(element, add);
       
 14040         remove && this.$$removeClassImmediately(element, remove);
       
 14041         applyStyles(element, options);
       
 14042         return asyncPromise();
       
 14043       },
       
 14044 
       
 14045       enabled: noop,
       
 14046       cancel: noop
 13799     };
 14047     };
 13800   }];
 14048   }];
 13801 }];
 14049 }];
 13802 
 14050 
 13803 function $$AsyncCallbackProvider(){
 14051 function $$AsyncCallbackProvider() {
 13804   this.$get = ['$$rAF', '$timeout', function($$rAF, $timeout) {
 14052   this.$get = ['$$rAF', '$timeout', function($$rAF, $timeout) {
 13805     return $$rAF.supported
 14053     return $$rAF.supported
 13806       ? function(fn) { return $$rAF(fn); }
 14054       ? function(fn) { return $$rAF(fn); }
 13807       : function(fn) {
 14055       : function(fn) {
 13808         return $timeout(fn, 0, false);
 14056         return $timeout(fn, 0, false);
 13828  * the real browser apis.
 14076  * the real browser apis.
 13829  */
 14077  */
 13830 /**
 14078 /**
 13831  * @param {object} window The global window object.
 14079  * @param {object} window The global window object.
 13832  * @param {object} document jQuery wrapped document.
 14080  * @param {object} document jQuery wrapped document.
 13833  * @param {function()} XHR XMLHttpRequest constructor.
 14081  * @param {object} $log window.console or an object with the same interface.
 13834  * @param {object} $log console.log or an object with the same interface.
       
 13835  * @param {object} $sniffer $sniffer service
 14082  * @param {object} $sniffer $sniffer service
 13836  */
 14083  */
 13837 function Browser(window, document, $log, $sniffer) {
 14084 function Browser(window, document, $log, $sniffer) {
 13838   var self = this,
 14085   var self = this,
 13839       rawDocument = document[0],
 14086       rawDocument = document[0],
 13860     try {
 14107     try {
 13861       fn.apply(null, sliceArgs(arguments, 1));
 14108       fn.apply(null, sliceArgs(arguments, 1));
 13862     } finally {
 14109     } finally {
 13863       outstandingRequestCount--;
 14110       outstandingRequestCount--;
 13864       if (outstandingRequestCount === 0) {
 14111       if (outstandingRequestCount === 0) {
 13865         while(outstandingRequestCallbacks.length) {
 14112         while (outstandingRequestCallbacks.length) {
 13866           try {
 14113           try {
 13867             outstandingRequestCallbacks.pop()();
 14114             outstandingRequestCallbacks.pop()();
 13868           } catch (e) {
 14115           } catch (e) {
 13869             $log.error(e);
 14116             $log.error(e);
 13870           }
 14117           }
 13871         }
 14118         }
 13872       }
 14119       }
 13873     }
 14120     }
       
 14121   }
       
 14122 
       
 14123   function getHash(url) {
       
 14124     var index = url.indexOf('#');
       
 14125     return index === -1 ? '' : url.substr(index + 1);
 13874   }
 14126   }
 13875 
 14127 
 13876   /**
 14128   /**
 13877    * @private
 14129    * @private
 13878    * Note: this method is used only by scenario runner
 14130    * Note: this method is used only by scenario runner
 13881    */
 14133    */
 13882   self.notifyWhenNoOutstandingRequests = function(callback) {
 14134   self.notifyWhenNoOutstandingRequests = function(callback) {
 13883     // force browser to execute all pollFns - this is needed so that cookies and other pollers fire
 14135     // force browser to execute all pollFns - this is needed so that cookies and other pollers fire
 13884     // at some deterministic time in respect to the test runner's actions. Leaving things up to the
 14136     // at some deterministic time in respect to the test runner's actions. Leaving things up to the
 13885     // regular poller would result in flaky tests.
 14137     // regular poller would result in flaky tests.
 13886     forEach(pollFns, function(pollFn){ pollFn(); });
 14138     forEach(pollFns, function(pollFn) { pollFn(); });
 13887 
 14139 
 13888     if (outstandingRequestCount === 0) {
 14140     if (outstandingRequestCount === 0) {
 13889       callback();
 14141       callback();
 13890     } else {
 14142     } else {
 13891       outstandingRequestCallbacks.push(callback);
 14143       outstandingRequestCallbacks.push(callback);
 13923    * Configures the poller to run in the specified intervals, using the specified
 14175    * Configures the poller to run in the specified intervals, using the specified
 13924    * setTimeout fn and kicks it off.
 14176    * setTimeout fn and kicks it off.
 13925    */
 14177    */
 13926   function startPoller(interval, setTimeout) {
 14178   function startPoller(interval, setTimeout) {
 13927     (function check() {
 14179     (function check() {
 13928       forEach(pollFns, function(pollFn){ pollFn(); });
 14180       forEach(pollFns, function(pollFn) { pollFn(); });
 13929       pollTimeout = setTimeout(check, interval);
 14181       pollTimeout = setTimeout(check, interval);
 13930     })();
 14182     })();
 13931   }
 14183   }
 13932 
 14184 
 13933   //////////////////////////////////////////////////////////////
 14185   //////////////////////////////////////////////////////////////
 13934   // URL API
 14186   // URL API
 13935   //////////////////////////////////////////////////////////////
 14187   //////////////////////////////////////////////////////////////
 13936 
 14188 
 13937   var lastBrowserUrl = location.href,
 14189   var cachedState, lastHistoryState,
 13938       lastHistoryState = history.state,
 14190       lastBrowserUrl = location.href,
 13939       baseElement = document.find('base'),
 14191       baseElement = document.find('base'),
 13940       reloadLocation = null;
 14192       reloadLocation = null;
       
 14193 
       
 14194   cacheState();
       
 14195   lastHistoryState = cachedState;
 13941 
 14196 
 13942   /**
 14197   /**
 13943    * @name $browser#url
 14198    * @name $browser#url
 13944    *
 14199    *
 13945    * @description
 14200    * @description
 13971     if (location !== window.location) location = window.location;
 14226     if (location !== window.location) location = window.location;
 13972     if (history !== window.history) history = window.history;
 14227     if (history !== window.history) history = window.history;
 13973 
 14228 
 13974     // setter
 14229     // setter
 13975     if (url) {
 14230     if (url) {
       
 14231       var sameState = lastHistoryState === state;
       
 14232 
 13976       // Don't change anything if previous and current URLs and states match. This also prevents
 14233       // Don't change anything if previous and current URLs and states match. This also prevents
 13977       // IE<10 from getting into redirect loop when in LocationHashbangInHtml5Url mode.
 14234       // IE<10 from getting into redirect loop when in LocationHashbangInHtml5Url mode.
 13978       // See https://github.com/angular/angular.js/commit/ffb2701
 14235       // See https://github.com/angular/angular.js/commit/ffb2701
 13979       if (lastBrowserUrl === url && (!$sniffer.history || history.state === state)) {
 14236       if (lastBrowserUrl === url && (!$sniffer.history || sameState)) {
 13980         return;
 14237         return self;
 13981       }
 14238       }
 13982       var sameBase = lastBrowserUrl && stripHash(lastBrowserUrl) === stripHash(url);
 14239       var sameBase = lastBrowserUrl && stripHash(lastBrowserUrl) === stripHash(url);
 13983       lastBrowserUrl = url;
 14240       lastBrowserUrl = url;
       
 14241       lastHistoryState = state;
 13984       // Don't use history API if only the hash changed
 14242       // Don't use history API if only the hash changed
 13985       // due to a bug in IE10/IE11 which leads
 14243       // due to a bug in IE10/IE11 which leads
 13986       // to not firing a `hashchange` nor `popstate` event
 14244       // to not firing a `hashchange` nor `popstate` event
 13987       // in some cases (see #9143).
 14245       // in some cases (see #9143).
 13988       if ($sniffer.history && (!sameBase || history.state !== state)) {
 14246       if ($sniffer.history && (!sameBase || !sameState)) {
 13989         history[replace ? 'replaceState' : 'pushState'](state, '', url);
 14247         history[replace ? 'replaceState' : 'pushState'](state, '', url);
 13990         lastHistoryState = history.state;
 14248         cacheState();
       
 14249         // Do the assignment again so that those two variables are referentially identical.
       
 14250         lastHistoryState = cachedState;
 13991       } else {
 14251       } else {
 13992         if (!sameBase) {
 14252         if (!sameBase) {
 13993           reloadLocation = url;
 14253           reloadLocation = url;
 13994         }
 14254         }
 13995         if (replace) {
 14255         if (replace) {
 13996           location.replace(url);
 14256           location.replace(url);
       
 14257         } else if (!sameBase) {
       
 14258           location.href = url;
 13997         } else {
 14259         } else {
 13998           location.href = url;
 14260           location.hash = getHash(url);
 13999         }
 14261         }
 14000       }
 14262       }
 14001       return self;
 14263       return self;
 14002     // getter
 14264     // getter
 14003     } else {
 14265     } else {
 14017    * Return history.state or null if history.state is undefined.
 14279    * Return history.state or null if history.state is undefined.
 14018    *
 14280    *
 14019    * @returns {object} state
 14281    * @returns {object} state
 14020    */
 14282    */
 14021   self.state = function() {
 14283   self.state = function() {
 14022     return isUndefined(history.state) ? null : history.state;
 14284     return cachedState;
 14023   };
 14285   };
 14024 
 14286 
 14025   var urlChangeListeners = [],
 14287   var urlChangeListeners = [],
 14026       urlChangeInit = false;
 14288       urlChangeInit = false;
 14027 
 14289 
       
 14290   function cacheStateAndFireUrlChange() {
       
 14291     cacheState();
       
 14292     fireUrlChange();
       
 14293   }
       
 14294 
       
 14295   // This variable should be used *only* inside the cacheState function.
       
 14296   var lastCachedState = null;
       
 14297   function cacheState() {
       
 14298     // This should be the only place in $browser where `history.state` is read.
       
 14299     cachedState = window.history.state;
       
 14300     cachedState = isUndefined(cachedState) ? null : cachedState;
       
 14301 
       
 14302     // Prevent callbacks fo fire twice if both hashchange & popstate were fired.
       
 14303     if (equals(cachedState, lastCachedState)) {
       
 14304       cachedState = lastCachedState;
       
 14305     }
       
 14306     lastCachedState = cachedState;
       
 14307   }
       
 14308 
 14028   function fireUrlChange() {
 14309   function fireUrlChange() {
 14029     if (lastBrowserUrl === self.url() && lastHistoryState === history.state) {
 14310     if (lastBrowserUrl === self.url() && lastHistoryState === cachedState) {
 14030       return;
 14311       return;
 14031     }
 14312     }
 14032 
 14313 
 14033     lastBrowserUrl = self.url();
 14314     lastBrowserUrl = self.url();
       
 14315     lastHistoryState = cachedState;
 14034     forEach(urlChangeListeners, function(listener) {
 14316     forEach(urlChangeListeners, function(listener) {
 14035       listener(self.url(), history.state);
 14317       listener(self.url(), cachedState);
 14036     });
 14318     });
 14037   }
 14319   }
 14038 
 14320 
 14039   /**
 14321   /**
 14040    * @name $browser#onUrlChange
 14322    * @name $browser#onUrlChange
 14063       // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)
 14345       // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)
 14064       // don't fire popstate when user change the address bar and don't fire hashchange when url
 14346       // don't fire popstate when user change the address bar and don't fire hashchange when url
 14065       // changed by push/replaceState
 14347       // changed by push/replaceState
 14066 
 14348 
 14067       // html5 history api - popstate event
 14349       // html5 history api - popstate event
 14068       if ($sniffer.history) jqLite(window).on('popstate', fireUrlChange);
 14350       if ($sniffer.history) jqLite(window).on('popstate', cacheStateAndFireUrlChange);
 14069       // hashchange event
 14351       // hashchange event
 14070       jqLite(window).on('hashchange', fireUrlChange);
 14352       jqLite(window).on('hashchange', cacheStateAndFireUrlChange);
 14071 
 14353 
 14072       urlChangeInit = true;
 14354       urlChangeInit = true;
 14073     }
 14355     }
 14074 
 14356 
 14075     urlChangeListeners.push(callback);
 14357     urlChangeListeners.push(callback);
 14105   // Cookies API
 14387   // Cookies API
 14106   //////////////////////////////////////////////////////////////
 14388   //////////////////////////////////////////////////////////////
 14107   var lastCookies = {};
 14389   var lastCookies = {};
 14108   var lastCookieString = '';
 14390   var lastCookieString = '';
 14109   var cookiePath = self.baseHref();
 14391   var cookiePath = self.baseHref();
       
 14392 
       
 14393   function safeDecodeURIComponent(str) {
       
 14394     try {
       
 14395       return decodeURIComponent(str);
       
 14396     } catch (e) {
       
 14397       return str;
       
 14398     }
       
 14399   }
 14110 
 14400 
 14111   /**
 14401   /**
 14112    * @name $browser#cookies
 14402    * @name $browser#cookies
 14113    *
 14403    *
 14114    * @param {string=} name Cookie name
 14404    * @param {string=} name Cookie name
 14143           // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:
 14433           // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:
 14144           // - 300 cookies
 14434           // - 300 cookies
 14145           // - 20 cookies per unique domain
 14435           // - 20 cookies per unique domain
 14146           // - 4096 bytes per cookie
 14436           // - 4096 bytes per cookie
 14147           if (cookieLength > 4096) {
 14437           if (cookieLength > 4096) {
 14148             $log.warn("Cookie '"+ name +
 14438             $log.warn("Cookie '" + name +
 14149               "' possibly not set or overflowed because it was too large ("+
 14439               "' possibly not set or overflowed because it was too large (" +
 14150               cookieLength + " > 4096 bytes)!");
 14440               cookieLength + " > 4096 bytes)!");
 14151           }
 14441           }
 14152         }
 14442         }
 14153       }
 14443       }
 14154     } else {
 14444     } else {
 14159 
 14449 
 14160         for (i = 0; i < cookieArray.length; i++) {
 14450         for (i = 0; i < cookieArray.length; i++) {
 14161           cookie = cookieArray[i];
 14451           cookie = cookieArray[i];
 14162           index = cookie.indexOf('=');
 14452           index = cookie.indexOf('=');
 14163           if (index > 0) { //ignore nameless cookies
 14453           if (index > 0) { //ignore nameless cookies
 14164             name = decodeURIComponent(cookie.substring(0, index));
 14454             name = safeDecodeURIComponent(cookie.substring(0, index));
 14165             // the first value that is seen for a cookie is the most
 14455             // the first value that is seen for a cookie is the most
 14166             // specific one.  values for the same cookie name that
 14456             // specific one.  values for the same cookie name that
 14167             // follow are for less specific paths.
 14457             // follow are for less specific paths.
 14168             if (lastCookies[name] === undefined) {
 14458             if (lastCookies[name] === undefined) {
 14169               lastCookies[name] = decodeURIComponent(cookie.substring(index + 1));
 14459               lastCookies[name] = safeDecodeURIComponent(cookie.substring(index + 1));
 14170             }
 14460             }
 14171           }
 14461           }
 14172         }
 14462         }
 14173       }
 14463       }
 14174       return lastCookies;
 14464       return lastCookies;
 14222     return false;
 14512     return false;
 14223   };
 14513   };
 14224 
 14514 
 14225 }
 14515 }
 14226 
 14516 
 14227 function $BrowserProvider(){
 14517 function $BrowserProvider() {
 14228   this.$get = ['$window', '$log', '$sniffer', '$document',
 14518   this.$get = ['$window', '$log', '$sniffer', '$document',
 14229       function( $window,   $log,   $sniffer,   $document){
 14519       function($window, $log, $sniffer, $document) {
 14230         return new Browser($window, $document, $log, $sniffer);
 14520         return new Browser($window, $document, $log, $sniffer);
 14231       }];
 14521       }];
 14232 }
 14522 }
 14233 
 14523 
 14234 /**
 14524 /**
 14598  *     <p>This is the content of the template</p>
 14888  *     <p>This is the content of the template</p>
 14599  *   </script>
 14889  *   </script>
 14600  * ```
 14890  * ```
 14601  *
 14891  *
 14602  * **Note:** the `script` tag containing the template does not need to be included in the `head` of
 14892  * **Note:** the `script` tag containing the template does not need to be included in the `head` of
 14603  * the document, but it must be below the `ng-app` definition.
 14893  * the document, but it must be a descendent of the {@link ng.$rootElement $rootElement} (IE,
       
 14894  * element with ng-app attribute), otherwise the template will be ignored.
 14604  *
 14895  *
 14605  * Adding via the $templateCache service:
 14896  * Adding via the $templateCache service:
 14606  *
 14897  *
 14607  * ```js
 14898  * ```js
 14608  * var myApp = angular.module('myApp', []);
 14899  * var myApp = angular.module('myApp', []);
 14689  *       template: '<div></div>', // or // function(tElement, tAttrs) { ... },
 14980  *       template: '<div></div>', // or // function(tElement, tAttrs) { ... },
 14690  *       // or
 14981  *       // or
 14691  *       // templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... },
 14982  *       // templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... },
 14692  *       transclude: false,
 14983  *       transclude: false,
 14693  *       restrict: 'A',
 14984  *       restrict: 'A',
       
 14985  *       templateNamespace: 'html',
 14694  *       scope: false,
 14986  *       scope: false,
 14695  *       controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... },
 14987  *       controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... },
 14696  *       controllerAs: 'stringAlias',
 14988  *       controllerAs: 'stringAlias',
 14697  *       require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'],
 14989  *       require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'],
 14698  *       compile: function compile(tElement, tAttrs, transclude) {
 14990  *       compile: function compile(tElement, tAttrs, transclude) {
 14742  * compiler}. The attributes are:
 15034  * compiler}. The attributes are:
 14743  *
 15035  *
 14744  * #### `multiElement`
 15036  * #### `multiElement`
 14745  * When this property is set to true, the HTML compiler will collect DOM nodes between
 15037  * When this property is set to true, the HTML compiler will collect DOM nodes between
 14746  * nodes with the attributes `directive-name-start` and `directive-name-end`, and group them
 15038  * nodes with the attributes `directive-name-start` and `directive-name-end`, and group them
 14747  * together as the directive elements. It is recomended that this feature be used on directives
 15039  * together as the directive elements. It is recommended that this feature be used on directives
 14748  * which are not strictly behavioural (such as {@link api/ng.directive:ngClick ngClick}), and which
 15040  * which are not strictly behavioural (such as {@link ngClick}), and which
 14749  * do not manipulate or replace child nodes (such as {@link api/ng.directive:ngInclude ngInclude}).
 15041  * do not manipulate or replace child nodes (such as {@link ngInclude}).
 14750  *
 15042  *
 14751  * #### `priority`
 15043  * #### `priority`
 14752  * When there are multiple directives defined on a single DOM element, sometimes it
 15044  * When there are multiple directives defined on a single DOM element, sometimes it
 14753  * is necessary to specify the order in which the directives are applied. The `priority` is used
 15045  * is necessary to specify the order in which the directives are applied. The `priority` is used
 14754  * to sort the directives before their `compile` functions get called. Priority is defined as a
 15046  * to sort the directives before their `compile` functions get called. Priority is defined as a
 14757  * of directives with the same priority is undefined. The default priority is `0`.
 15049  * of directives with the same priority is undefined. The default priority is `0`.
 14758  *
 15050  *
 14759  * #### `terminal`
 15051  * #### `terminal`
 14760  * If set to true then the current `priority` will be the last set of directives
 15052  * If set to true then the current `priority` will be the last set of directives
 14761  * which will execute (any directives at the current priority will still execute
 15053  * which will execute (any directives at the current priority will still execute
 14762  * as the order of execution on same `priority` is undefined).
 15054  * as the order of execution on same `priority` is undefined). Note that expressions
       
 15055  * and other directives used in the directive's template will also be excluded from execution.
 14763  *
 15056  *
 14764  * #### `scope`
 15057  * #### `scope`
 14765  * **If set to `true`,** then a new scope will be created for this directive. If multiple directives on the
 15058  * **If set to `true`,** then a new scope will be created for this directive. If multiple directives on the
 14766  * same element request a new scope, only one new scope is created. The new scope rule does not
 15059  * same element request a new scope, only one new scope is created. The new scope rule does not
 14767  * apply for the root of the template since the root of the template always gets a new scope.
 15060  * apply for the root of the template since the root of the template always gets a new scope.
 14790  *   Given `<widget my-attr="parentModel">` and widget definition of
 15083  *   Given `<widget my-attr="parentModel">` and widget definition of
 14791  *   `scope: { localModel:'=myAttr' }`, then widget scope property `localModel` will reflect the
 15084  *   `scope: { localModel:'=myAttr' }`, then widget scope property `localModel` will reflect the
 14792  *   value of `parentModel` on the parent scope. Any changes to `parentModel` will be reflected
 15085  *   value of `parentModel` on the parent scope. Any changes to `parentModel` will be reflected
 14793  *   in `localModel` and any changes in `localModel` will reflect in `parentModel`. If the parent
 15086  *   in `localModel` and any changes in `localModel` will reflect in `parentModel`. If the parent
 14794  *   scope property doesn't exist, it will throw a NON_ASSIGNABLE_MODEL_EXPRESSION exception. You
 15087  *   scope property doesn't exist, it will throw a NON_ASSIGNABLE_MODEL_EXPRESSION exception. You
 14795  *   can avoid this behavior using `=?` or `=?attr` in order to flag the property as optional.
 15088  *   can avoid this behavior using `=?` or `=?attr` in order to flag the property as optional. If
       
 15089  *   you want to shallow watch for changes (i.e. $watchCollection instead of $watch) you can use
       
 15090  *   `=*` or `=*attr` (`=*?` or `=*?attr` if the property is optional).
 14796  *
 15091  *
 14797  * * `&` or `&attr` - provides a way to execute an expression in the context of the parent scope.
 15092  * * `&` or `&attr` - provides a way to execute an expression in the context of the parent scope.
 14798  *   If no `attr` name is specified then the attribute name is assumed to be the same as the
 15093  *   If no `attr` name is specified then the attribute name is assumed to be the same as the
 14799  *   local name. Given `<widget my-attr="count = count + value">` and widget definition of
 15094  *   local name. Given `<widget my-attr="count = count + value">` and widget definition of
 14800  *   `scope: { localFn:'&myAttr' }`, then isolate scope property `localFn` will point to
 15095  *   `scope: { localFn:'&myAttr' }`, then isolate scope property `localFn` will point to
 14804  *   For example, if the expression is `increment(amount)` then we can specify the amount value
 15099  *   For example, if the expression is `increment(amount)` then we can specify the amount value
 14805  *   by calling the `localFn` as `localFn({amount: 22})`.
 15100  *   by calling the `localFn` as `localFn({amount: 22})`.
 14806  *
 15101  *
 14807  *
 15102  *
 14808  * #### `bindToController`
 15103  * #### `bindToController`
 14809  * When an isolate scope is used for a component (see above), and `controllerAs` is used, `bindToController` will
 15104  * When an isolate scope is used for a component (see above), and `controllerAs` is used, `bindToController: true` will
 14810  * allow a component to have its properties bound to the controller, rather than to scope. When the controller
 15105  * allow a component to have its properties bound to the controller, rather than to scope. When the controller
 14811  * is instantiated, the initial values of the isolate scope bindings are already available.
 15106  * is instantiated, the initial values of the isolate scope bindings are already available.
 14812  *
 15107  *
 14813  * #### `controller`
 15108  * #### `controller`
 14814  * Controller constructor function. The controller is instantiated before the
 15109  * Controller constructor function. The controller is instantiated before the
 14904  * Template loading is asynchronous even if the template has been preloaded into the {@link $templateCache}
 15199  * Template loading is asynchronous even if the template has been preloaded into the {@link $templateCache}
 14905  *
 15200  *
 14906  * You can specify `templateUrl` as a string representing the URL or as a function which takes two
 15201  * You can specify `templateUrl` as a string representing the URL or as a function which takes two
 14907  * arguments `tElement` and `tAttrs` (described in the `compile` function api below) and returns
 15202  * arguments `tElement` and `tAttrs` (described in the `compile` function api below) and returns
 14908  * a string value representing the url.  In either case, the template URL is passed through {@link
 15203  * a string value representing the url.  In either case, the template URL is passed through {@link
 14909  * api/ng.$sce#getTrustedResourceUrl $sce.getTrustedResourceUrl}.
 15204  * $sce#getTrustedResourceUrl $sce.getTrustedResourceUrl}.
 14910  *
 15205  *
 14911  *
 15206  *
 14912  * #### `replace` ([*DEPRECATED*!], will be removed in next major release - i.e. v2.0)
 15207  * #### `replace` ([*DEPRECATED*!], will be removed in next major release - i.e. v2.0)
 14913  * specify what the template should replace. Defaults to `false`.
 15208  * specify what the template should replace. Defaults to `false`.
 14914  *
 15209  *
 14915  * * `true` - the template will replace the directive's element.
 15210  * * `true` - the template will replace the directive's element.
 14916  * * `false` - the template will replace the contents of the directive's element.
 15211  * * `false` - the template will replace the contents of the directive's element.
 14917  *
 15212  *
 14918  * The replacement process migrates all of the attributes / classes from the old element to the new
 15213  * The replacement process migrates all of the attributes / classes from the old element to the new
 14919  * one. See the {@link guide/directive#creating-custom-directives_creating-directives_template-expanding-directive
 15214  * one. See the {@link guide/directive#template-expanding-directive
 14920  * Directives Guide} for an example.
 15215  * Directives Guide} for an example.
 14921  *
 15216  *
 14922  * There are very few scenarios where element replacement is required for the application function,
 15217  * There are very few scenarios where element replacement is required for the application function,
 14923  * the main one being reusable custom components that are used within SVG contexts
 15218  * the main one being reusable custom components that are used within SVG contexts
 14924  * (because SVG doesn't work with custom elements in the DOM tree).
 15219  * (because SVG doesn't work with custom elements in the DOM tree).
 15069  *
 15364  *
 15070  * If you want to manually control the insertion and removal of the transcluded content in your directive
 15365  * If you want to manually control the insertion and removal of the transcluded content in your directive
 15071  * then you must use this transclude function. When you call a transclude function it returns a a jqLite/JQuery
 15366  * then you must use this transclude function. When you call a transclude function it returns a a jqLite/JQuery
 15072  * object that contains the compiled DOM, which is linked to the correct transclusion scope.
 15367  * object that contains the compiled DOM, which is linked to the correct transclusion scope.
 15073  *
 15368  *
 15074  * When you call a transclusion function you can pass in a **clone attach function**. This function is accepts
 15369  * When you call a transclusion function you can pass in a **clone attach function**. This function accepts
 15075  * two parameters, `function(clone, scope) { ... }`, where the `clone` is a fresh compiled copy of your transcluded
 15370  * two parameters, `function(clone, scope) { ... }`, where the `clone` is a fresh compiled copy of your transcluded
 15076  * content and the `scope` is the newly created transclusion scope, to which the clone is bound.
 15371  * content and the `scope` is the newly created transclusion scope, to which the clone is bound.
 15077  *
 15372  *
 15078  * <div class="alert alert-info">
 15373  * <div class="alert alert-info">
 15079  * **Best Practice**: Always provide a `cloneFn` (clone attach function) when you call a translude function
 15374  * **Best Practice**: Always provide a `cloneFn` (clone attach function) when you call a translude function
 15246  </example>
 15541  </example>
 15247 
 15542 
 15248  *
 15543  *
 15249  *
 15544  *
 15250  * @param {string|DOMElement} element Element or HTML string to compile into a template function.
 15545  * @param {string|DOMElement} element Element or HTML string to compile into a template function.
 15251  * @param {function(angular.Scope, cloneAttachFn=)} transclude function available to directives.
 15546  * @param {function(angular.Scope, cloneAttachFn=)} transclude function available to directives - DEPRECATED.
       
 15547  *
       
 15548  * <div class="alert alert-error">
       
 15549  * **Note:** Passing a `transclude` function to the $compile function is deprecated, as it
       
 15550  *   e.g. will not use the right outer scope. Please pass the transclude function as a
       
 15551  *   `parentBoundTranscludeFn` to the link function instead.
       
 15552  * </div>
       
 15553  *
 15252  * @param {number} maxPriority only apply directives lower than given priority (Only effects the
 15554  * @param {number} maxPriority only apply directives lower than given priority (Only effects the
 15253  *                 root element(s), not their children)
 15555  *                 root element(s), not their children)
 15254  * @returns {function(scope, cloneAttachFn=)} a link function which is used to bind template
 15556  * @returns {function(scope, cloneAttachFn=, options=)} a link function which is used to bind template
 15255  * (a DOM element/tree) to a scope. Where:
 15557  * (a DOM element/tree) to a scope. Where:
 15256  *
 15558  *
 15257  *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.
 15559  *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.
 15258  *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the
 15560  *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the
 15259  *  `template` and call the `cloneAttachFn` function allowing the caller to attach the
 15561  *  `template` and call the `cloneAttachFn` function allowing the caller to attach the
 15260  *  cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is
 15562  *  cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is
 15261  *  called as: <br> `cloneAttachFn(clonedElement, scope)` where:
 15563  *  called as: <br> `cloneAttachFn(clonedElement, scope)` where:
 15262  *
 15564  *
 15263  *      * `clonedElement` - is a clone of the original `element` passed into the compiler.
 15565  *      * `clonedElement` - is a clone of the original `element` passed into the compiler.
 15264  *      * `scope` - is the current scope with which the linking function is working with.
 15566  *      * `scope` - is the current scope with which the linking function is working with.
       
 15567  *
       
 15568  *  * `options` - An optional object hash with linking options. If `options` is provided, then the following
       
 15569  *  keys may be used to control linking behavior:
       
 15570  *
       
 15571  *      * `parentBoundTranscludeFn` - the transclude function made available to
       
 15572  *        directives; if given, it will be passed through to the link functions of
       
 15573  *        directives found in `element` during compilation.
       
 15574  *      * `transcludeControllers` - an object hash with keys that map controller names
       
 15575  *        to controller instances; if given, it will make the controllers
       
 15576  *        available to directives.
       
 15577  *      * `futureParentElement` - defines the parent to which the `cloneAttachFn` will add
       
 15578  *        the cloned elements; only needed for transcludes that are allowed to contain non html
       
 15579  *        elements (e.g. SVG elements). See also the directive.controller property.
 15265  *
 15580  *
 15266  * Calling the linking function returns the element of the template. It is either the original
 15581  * Calling the linking function returns the element of the template. It is either the original
 15267  * element passed in, or the clone of the element if the `cloneAttachFn` is provided.
 15582  * element passed in, or the clone of the element if the `cloneAttachFn` is provided.
 15268  *
 15583  *
 15269  * After linking the view is not updated until after a call to $digest which typically is done by
 15584  * After linking the view is not updated until after a call to $digest which typically is done by
 15306  */
 15621  */
 15307 $CompileProvider.$inject = ['$provide', '$$sanitizeUriProvider'];
 15622 $CompileProvider.$inject = ['$provide', '$$sanitizeUriProvider'];
 15308 function $CompileProvider($provide, $$sanitizeUriProvider) {
 15623 function $CompileProvider($provide, $$sanitizeUriProvider) {
 15309   var hasDirectives = {},
 15624   var hasDirectives = {},
 15310       Suffix = 'Directive',
 15625       Suffix = 'Directive',
 15311       COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\d\w_\-]+)\s+(.*)$/,
 15626       COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\w\-]+)\s+(.*)$/,
 15312       CLASS_DIRECTIVE_REGEXP = /(([\d\w_\-]+)(?:\:([^;]+))?;?)/,
 15627       CLASS_DIRECTIVE_REGEXP = /(([\w\-]+)(?:\:([^;]+))?;?)/,
 15313       ALL_OR_NOTHING_ATTRS = makeMap('ngSrc,ngSrcset,src,srcset'),
 15628       ALL_OR_NOTHING_ATTRS = makeMap('ngSrc,ngSrcset,src,srcset'),
 15314       REQUIRE_PREFIX_REGEXP = /^(?:(\^\^?)?(\?)?(\^\^?)?)?/;
 15629       REQUIRE_PREFIX_REGEXP = /^(?:(\^\^?)?(\?)?(\^\^?)?)?/;
 15315 
 15630 
 15316   // Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes
 15631   // Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes
 15317   // The assumption is that future DOM event attribute names will begin with
 15632   // The assumption is that future DOM event attribute names will begin with
 15318   // 'on' and be composed of only English letters.
 15633   // 'on' and be composed of only English letters.
 15319   var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/;
 15634   var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/;
 15320 
 15635 
 15321   function parseIsolateBindings(scope, directiveName) {
 15636   function parseIsolateBindings(scope, directiveName) {
 15322     var LOCAL_REGEXP = /^\s*([@=&])(\??)\s*(\w*)\s*$/;
 15637     var LOCAL_REGEXP = /^\s*([@&]|=(\*?))(\??)\s*(\w*)\s*$/;
 15323 
 15638 
 15324     var bindings = {};
 15639     var bindings = {};
 15325 
 15640 
 15326     forEach(scope, function(definition, scopeName) {
 15641     forEach(scope, function(definition, scopeName) {
 15327       var match = definition.match(LOCAL_REGEXP);
 15642       var match = definition.match(LOCAL_REGEXP);
 15332             " Definition: {... {1}: '{2}' ...}",
 15647             " Definition: {... {1}: '{2}' ...}",
 15333             directiveName, scopeName, definition);
 15648             directiveName, scopeName, definition);
 15334       }
 15649       }
 15335 
 15650 
 15336       bindings[scopeName] = {
 15651       bindings[scopeName] = {
 15337         attrName: match[3] || scopeName,
 15652         mode: match[1][0],
 15338         mode: match[1],
 15653         collection: match[2] === '*',
 15339         optional: match[2] === '?'
 15654         optional: match[3] === '?',
       
 15655         attrName: match[4] || scopeName
 15340       };
 15656       };
 15341     });
 15657     });
 15342 
 15658 
 15343     return bindings;
 15659     return bindings;
 15344   }
 15660   }
 15406    *
 15722    *
 15407    * @description
 15723    * @description
 15408    * Retrieves or overrides the default regular expression that is used for whitelisting of safe
 15724    * Retrieves or overrides the default regular expression that is used for whitelisting of safe
 15409    * urls during a[href] sanitization.
 15725    * urls during a[href] sanitization.
 15410    *
 15726    *
 15411    * The sanitization is a security measure aimed at prevent XSS attacks via html links.
 15727    * The sanitization is a security measure aimed at preventing XSS attacks via html links.
 15412    *
 15728    *
 15413    * Any url about to be assigned to a[href] via data-binding is first normalized and turned into
 15729    * Any url about to be assigned to a[href] via data-binding is first normalized and turned into
 15414    * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist`
 15730    * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist`
 15415    * regular expression. If a match is found, the original url is written into the dom. Otherwise,
 15731    * regular expression. If a match is found, the original url is written into the dom. Otherwise,
 15416    * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
 15732    * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
 15473    * binding information and a reference to the current scope on to DOM elements.
 15789    * binding information and a reference to the current scope on to DOM elements.
 15474    * If enabled, the compiler will add the following to DOM elements that have been bound to the scope
 15790    * If enabled, the compiler will add the following to DOM elements that have been bound to the scope
 15475    * * `ng-binding` CSS class
 15791    * * `ng-binding` CSS class
 15476    * * `$binding` data property containing an array of the binding expressions
 15792    * * `$binding` data property containing an array of the binding expressions
 15477    *
 15793    *
 15478    * You may want to use this in production for a significant performance boost. See
 15794    * You may want to disable this in production for a significant performance boost. See
 15479    * {@link guide/production#disabling-debug-data Disabling Debug Data} for more.
 15795    * {@link guide/production#disabling-debug-data Disabling Debug Data} for more.
 15480    *
 15796    *
 15481    * The default value is true.
 15797    * The default value is true.
 15482    */
 15798    */
 15483   var debugInfoEnabled = true;
 15799   var debugInfoEnabled = true;
 15484   this.debugInfoEnabled = function(enabled) {
 15800   this.debugInfoEnabled = function(enabled) {
 15485     if(isDefined(enabled)) {
 15801     if (isDefined(enabled)) {
 15486       debugInfoEnabled = enabled;
 15802       debugInfoEnabled = enabled;
 15487       return this;
 15803       return this;
 15488     }
 15804     }
 15489     return debugInfoEnabled;
 15805     return debugInfoEnabled;
 15490   };
 15806   };
 15510 
 15826 
 15511       this.$$element = element;
 15827       this.$$element = element;
 15512     };
 15828     };
 15513 
 15829 
 15514     Attributes.prototype = {
 15830     Attributes.prototype = {
       
 15831       /**
       
 15832        * @ngdoc method
       
 15833        * @name $compile.directive.Attributes#$normalize
       
 15834        * @kind function
       
 15835        *
       
 15836        * @description
       
 15837        * Converts an attribute name (e.g. dash/colon/underscore-delimited string, optionally prefixed with `x-` or
       
 15838        * `data-`) to its normalized, camelCase form.
       
 15839        *
       
 15840        * Also there is special case for Moz prefix starting with upper case letter.
       
 15841        *
       
 15842        * For further information check out the guide on {@link guide/directive#matching-directives Matching Directives}
       
 15843        *
       
 15844        * @param {string} name Name to normalize
       
 15845        */
 15515       $normalize: directiveNormalize,
 15846       $normalize: directiveNormalize,
 15516 
 15847 
 15517 
 15848 
 15518       /**
 15849       /**
 15519        * @ngdoc method
 15850        * @ngdoc method
 15524        * Adds the CSS class value specified by the classVal parameter to the element. If animations
 15855        * Adds the CSS class value specified by the classVal parameter to the element. If animations
 15525        * are enabled then an animation will be triggered for the class addition.
 15856        * are enabled then an animation will be triggered for the class addition.
 15526        *
 15857        *
 15527        * @param {string} classVal The className value that will be added to the element
 15858        * @param {string} classVal The className value that will be added to the element
 15528        */
 15859        */
 15529       $addClass : function(classVal) {
 15860       $addClass: function(classVal) {
 15530         if(classVal && classVal.length > 0) {
 15861         if (classVal && classVal.length > 0) {
 15531           $animate.addClass(this.$$element, classVal);
 15862           $animate.addClass(this.$$element, classVal);
 15532         }
 15863         }
 15533       },
 15864       },
 15534 
 15865 
 15535       /**
 15866       /**
 15541        * Removes the CSS class value specified by the classVal parameter from the element. If
 15872        * Removes the CSS class value specified by the classVal parameter from the element. If
 15542        * animations are enabled then an animation will be triggered for the class removal.
 15873        * animations are enabled then an animation will be triggered for the class removal.
 15543        *
 15874        *
 15544        * @param {string} classVal The className value that will be removed from the element
 15875        * @param {string} classVal The className value that will be removed from the element
 15545        */
 15876        */
 15546       $removeClass : function(classVal) {
 15877       $removeClass: function(classVal) {
 15547         if(classVal && classVal.length > 0) {
 15878         if (classVal && classVal.length > 0) {
 15548           $animate.removeClass(this.$$element, classVal);
 15879           $animate.removeClass(this.$$element, classVal);
 15549         }
 15880         }
 15550       },
 15881       },
 15551 
 15882 
 15552       /**
 15883       /**
 15559        * between the new and old CSS class values (specified as newClasses and oldClasses).
 15890        * between the new and old CSS class values (specified as newClasses and oldClasses).
 15560        *
 15891        *
 15561        * @param {string} newClasses The current CSS className value
 15892        * @param {string} newClasses The current CSS className value
 15562        * @param {string} oldClasses The former CSS className value
 15893        * @param {string} oldClasses The former CSS className value
 15563        */
 15894        */
 15564       $updateClass : function(newClasses, oldClasses) {
 15895       $updateClass: function(newClasses, oldClasses) {
 15565         var toAdd = tokenDifference(newClasses, oldClasses);
 15896         var toAdd = tokenDifference(newClasses, oldClasses);
 15566         if (toAdd && toAdd.length) {
 15897         if (toAdd && toAdd.length) {
 15567           $animate.addClass(this.$$element, toAdd);
 15898           $animate.addClass(this.$$element, toAdd);
 15568         }
 15899         }
 15569 
 15900 
 15589 
 15920 
 15590         var node = this.$$element[0],
 15921         var node = this.$$element[0],
 15591             booleanKey = getBooleanAttrName(node, key),
 15922             booleanKey = getBooleanAttrName(node, key),
 15592             aliasedKey = getAliasedAttrName(node, key),
 15923             aliasedKey = getAliasedAttrName(node, key),
 15593             observer = key,
 15924             observer = key,
 15594             normalizedVal,
       
 15595             nodeName;
 15925             nodeName;
 15596 
 15926 
 15597         if (booleanKey) {
 15927         if (booleanKey) {
 15598           this.$$element.prop(key, value);
 15928           this.$$element.prop(key, value);
 15599           attrName = booleanKey;
 15929           attrName = booleanKey;
 15600         } else if(aliasedKey) {
 15930         } else if (aliasedKey) {
 15601           this[aliasedKey] = value;
 15931           this[aliasedKey] = value;
 15602           observer = aliasedKey;
 15932           observer = aliasedKey;
 15603         }
 15933         }
 15604 
 15934 
 15605         this[key] = value;
 15935         this[key] = value;
 15633           // split srcset into tuple of uri and descriptor except for the last item
 15963           // split srcset into tuple of uri and descriptor except for the last item
 15634           var rawUris = trimmedSrcset.split(pattern);
 15964           var rawUris = trimmedSrcset.split(pattern);
 15635 
 15965 
 15636           // for each tuples
 15966           // for each tuples
 15637           var nbrUrisWith2parts = Math.floor(rawUris.length / 2);
 15967           var nbrUrisWith2parts = Math.floor(rawUris.length / 2);
 15638           for (var i=0; i<nbrUrisWith2parts; i++) {
 15968           for (var i = 0; i < nbrUrisWith2parts; i++) {
 15639             var innerIdx = i*2;
 15969             var innerIdx = i * 2;
 15640             // sanitize the uri
 15970             // sanitize the uri
 15641             result += $$sanitizeUri(trim( rawUris[innerIdx]), true);
 15971             result += $$sanitizeUri(trim(rawUris[innerIdx]), true);
 15642             // add the descriptor
 15972             // add the descriptor
 15643             result += ( " " + trim(rawUris[innerIdx+1]));
 15973             result += (" " + trim(rawUris[innerIdx + 1]));
 15644           }
 15974           }
 15645 
 15975 
 15646           // split the last item into uri and descriptor
 15976           // split the last item into uri and descriptor
 15647           var lastTuple = trim(rawUris[i*2]).split(/\s/);
 15977           var lastTuple = trim(rawUris[i * 2]).split(/\s/);
 15648 
 15978 
 15649           // sanitize the last uri
 15979           // sanitize the last uri
 15650           result += $$sanitizeUri(trim(lastTuple[0]), true);
 15980           result += $$sanitizeUri(trim(lastTuple[0]), true);
 15651 
 15981 
 15652           // and add the last descriptor if any
 15982           // and add the last descriptor if any
 15653           if( lastTuple.length === 2) {
 15983           if (lastTuple.length === 2) {
 15654             result += (" " + trim(lastTuple[1]));
 15984             result += (" " + trim(lastTuple[1]));
 15655           }
 15985           }
 15656           this[key] = value = result;
 15986           this[key] = value = result;
 15657         }
 15987         }
 15658 
 15988 
 15689        * changes.
 16019        * changes.
 15690        *
 16020        *
 15691        * @param {string} key Normalized key. (ie ngAttribute) .
 16021        * @param {string} key Normalized key. (ie ngAttribute) .
 15692        * @param {function(interpolatedValue)} fn Function that will be called whenever
 16022        * @param {function(interpolatedValue)} fn Function that will be called whenever
 15693                 the interpolated value of the attribute changes.
 16023                 the interpolated value of the attribute changes.
 15694        *        See {@link ng.$compile#attributes $compile} for more info.
 16024        *        See the {@link guide/directive#text-and-attribute-bindings Directives} guide for more info.
 15695        * @returns {function()} Returns a deregistration function for this observer.
 16025        * @returns {function()} Returns a deregistration function for this observer.
 15696        */
 16026        */
 15697       $observe: function(key, fn) {
 16027       $observe: function(key, fn) {
 15698         var attrs = this,
 16028         var attrs = this,
 15699             $$observers = (attrs.$$observers || (attrs.$$observers = Object.create(null))),
 16029             $$observers = (attrs.$$observers || (attrs.$$observers = createMap())),
 15700             listeners = ($$observers[key] || ($$observers[key] = []));
 16030             listeners = ($$observers[key] || ($$observers[key] = []));
 15701 
 16031 
 15702         listeners.push(fn);
 16032         listeners.push(fn);
 15703         $rootScope.$evalAsync(function() {
 16033         $rootScope.$evalAsync(function() {
 15704           if (!listeners.$$inter) {
 16034           if (!listeners.$$inter && attrs.hasOwnProperty(key)) {
 15705             // no one registered attribute interpolation function, so lets call it manually
 16035             // no one registered attribute interpolation function, so lets call it manually
 15706             fn(attrs[key]);
 16036             fn(attrs[key]);
 15707           }
 16037           }
 15708         });
 16038         });
 15709 
 16039 
 15715 
 16045 
 15716 
 16046 
 15717     function safeAddClass($element, className) {
 16047     function safeAddClass($element, className) {
 15718       try {
 16048       try {
 15719         $element.addClass(className);
 16049         $element.addClass(className);
 15720       } catch(e) {
 16050       } catch (e) {
 15721         // ignore, since it means that we are trying to set class on
 16051         // ignore, since it means that we are trying to set class on
 15722         // SVG element, where class name is read-only.
 16052         // SVG element, where class name is read-only.
 15723       }
 16053       }
 15724     }
 16054     }
 15725 
 16055 
 15769         // modify it.
 16099         // modify it.
 15770         $compileNodes = jqLite($compileNodes);
 16100         $compileNodes = jqLite($compileNodes);
 15771       }
 16101       }
 15772       // We can not compile top level text elements since text nodes can be merged and we will
 16102       // We can not compile top level text elements since text nodes can be merged and we will
 15773       // not be able to attach scope data to them, so we will wrap them in <span>
 16103       // not be able to attach scope data to them, so we will wrap them in <span>
 15774       forEach($compileNodes, function(node, index){
 16104       forEach($compileNodes, function(node, index) {
 15775         if (node.nodeType == NODE_TYPE_TEXT && node.nodeValue.match(/\S+/) /* non-empty */ ) {
 16105         if (node.nodeType == NODE_TYPE_TEXT && node.nodeValue.match(/\S+/) /* non-empty */ ) {
 15776           $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];
 16106           $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];
 15777         }
 16107         }
 15778       });
 16108       });
 15779       var compositeLinkFn =
 16109       var compositeLinkFn =
 15780               compileNodes($compileNodes, transcludeFn, $compileNodes,
 16110               compileNodes($compileNodes, transcludeFn, $compileNodes,
 15781                            maxPriority, ignoreDirective, previousCompileContext);
 16111                            maxPriority, ignoreDirective, previousCompileContext);
 15782       compile.$$addScopeClass($compileNodes);
 16112       compile.$$addScopeClass($compileNodes);
 15783       var namespace = null;
 16113       var namespace = null;
 15784       return function publicLinkFn(scope, cloneConnectFn, transcludeControllers, parentBoundTranscludeFn, futureParentElement){
 16114       return function publicLinkFn(scope, cloneConnectFn, options) {
 15785         assertArg(scope, 'scope');
 16115         assertArg(scope, 'scope');
       
 16116 
       
 16117         options = options || {};
       
 16118         var parentBoundTranscludeFn = options.parentBoundTranscludeFn,
       
 16119           transcludeControllers = options.transcludeControllers,
       
 16120           futureParentElement = options.futureParentElement;
       
 16121 
       
 16122         // When `parentBoundTranscludeFn` is passed, it is a
       
 16123         // `controllersBoundTransclude` function (it was previously passed
       
 16124         // as `transclude` to directive.link) so we must unwrap it to get
       
 16125         // its `boundTranscludeFn`
       
 16126         if (parentBoundTranscludeFn && parentBoundTranscludeFn.$$boundTransclude) {
       
 16127           parentBoundTranscludeFn = parentBoundTranscludeFn.$$boundTransclude;
       
 16128         }
       
 16129 
 15786         if (!namespace) {
 16130         if (!namespace) {
 15787           namespace = detectNamespaceForChildElements(futureParentElement);
 16131           namespace = detectNamespaceForChildElements(futureParentElement);
 15788         }
 16132         }
 15789         var $linkNode;
 16133         var $linkNode;
 15790         if (namespace !== 'html') {
 16134         if (namespace !== 'html') {
 15822       // TODO: Make this detect MathML as well...
 16166       // TODO: Make this detect MathML as well...
 15823       var node = parentElement && parentElement[0];
 16167       var node = parentElement && parentElement[0];
 15824       if (!node) {
 16168       if (!node) {
 15825         return 'html';
 16169         return 'html';
 15826       } else {
 16170       } else {
 15827         return nodeName_(node) !== 'foreignobject' && node.toString().match(/SVG/) ? 'svg': 'html';
 16171         return nodeName_(node) !== 'foreignobject' && node.toString().match(/SVG/) ? 'svg' : 'html';
 15828       }
 16172       }
 15829     }
 16173     }
 15830 
 16174 
 15831     /**
 16175     /**
 15832      * Compile function matches each node in nodeList against the directives. Once all directives
 16176      * Compile function matches each node in nodeList against the directives. Once all directives
 15904           }
 16248           }
 15905         } else {
 16249         } else {
 15906           stableNodeList = nodeList;
 16250           stableNodeList = nodeList;
 15907         }
 16251         }
 15908 
 16252 
 15909         for(i = 0, ii = linkFns.length; i < ii;) {
 16253         for (i = 0, ii = linkFns.length; i < ii;) {
 15910           node = stableNodeList[linkFns[i++]];
 16254           node = stableNodeList[linkFns[i++]];
 15911           nodeLinkFn = linkFns[i++];
 16255           nodeLinkFn = linkFns[i++];
 15912           childLinkFn = linkFns[i++];
 16256           childLinkFn = linkFns[i++];
 15913 
 16257 
 15914           if (nodeLinkFn) {
 16258           if (nodeLinkFn) {
 15917               compile.$$addScopeInfo(jqLite(node), childScope);
 16261               compile.$$addScopeInfo(jqLite(node), childScope);
 15918             } else {
 16262             } else {
 15919               childScope = scope;
 16263               childScope = scope;
 15920             }
 16264             }
 15921 
 16265 
 15922             if ( nodeLinkFn.transcludeOnThisElement ) {
 16266             if (nodeLinkFn.transcludeOnThisElement) {
 15923               childBoundTranscludeFn = createBoundTranscludeFn(
 16267               childBoundTranscludeFn = createBoundTranscludeFn(
 15924                   scope, nodeLinkFn.transclude, parentBoundTranscludeFn,
 16268                   scope, nodeLinkFn.transclude, parentBoundTranscludeFn,
 15925                   nodeLinkFn.elementTranscludeOnThisElement);
 16269                   nodeLinkFn.elementTranscludeOnThisElement);
 15926 
 16270 
 15927             } else if (!nodeLinkFn.templateOnThisElement && parentBoundTranscludeFn) {
 16271             } else if (!nodeLinkFn.templateOnThisElement && parentBoundTranscludeFn) {
 15950         if (!transcludedScope) {
 16294         if (!transcludedScope) {
 15951           transcludedScope = scope.$new(false, containingScope);
 16295           transcludedScope = scope.$new(false, containingScope);
 15952           transcludedScope.$$transcluded = true;
 16296           transcludedScope.$$transcluded = true;
 15953         }
 16297         }
 15954 
 16298 
 15955         return transcludeFn(transcludedScope, cloneFn, controllers, previousBoundTranscludeFn, futureParentElement);
 16299         return transcludeFn(transcludedScope, cloneFn, {
       
 16300           parentBoundTranscludeFn: previousBoundTranscludeFn,
       
 16301           transcludeControllers: controllers,
       
 16302           futureParentElement: futureParentElement
       
 16303         });
 15956       };
 16304       };
 15957 
 16305 
 15958       return boundTranscludeFn;
 16306       return boundTranscludeFn;
 15959     }
 16307     }
 15960 
 16308 
 15972       var nodeType = node.nodeType,
 16320       var nodeType = node.nodeType,
 15973           attrsMap = attrs.$attr,
 16321           attrsMap = attrs.$attr,
 15974           match,
 16322           match,
 15975           className;
 16323           className;
 15976 
 16324 
 15977       switch(nodeType) {
 16325       switch (nodeType) {
 15978         case NODE_TYPE_ELEMENT: /* Element */
 16326         case NODE_TYPE_ELEMENT: /* Element */
 15979           // use the node name: <directive>
 16327           // use the node name: <directive>
 15980           addDirective(directives,
 16328           addDirective(directives,
 15981               directiveNormalize(nodeName_(node)), 'E', maxPriority, ignoreDirective);
 16329               directiveNormalize(nodeName_(node)), 'E', maxPriority, ignoreDirective);
 15982 
 16330 
 15991             value = trim(attr.value);
 16339             value = trim(attr.value);
 15992 
 16340 
 15993             // support ngAttr attribute binding
 16341             // support ngAttr attribute binding
 15994             ngAttrName = directiveNormalize(name);
 16342             ngAttrName = directiveNormalize(name);
 15995             if (isNgAttr = NG_ATTR_BINDING.test(ngAttrName)) {
 16343             if (isNgAttr = NG_ATTR_BINDING.test(ngAttrName)) {
 15996               name = snake_case(ngAttrName.substr(6), '-');
 16344               name = name.replace(PREFIX_REGEXP, '')
       
 16345                 .substr(8).replace(/_(.)/g, function(match, letter) {
       
 16346                   return letter.toUpperCase();
       
 16347                 });
 15997             }
 16348             }
 15998 
 16349 
 15999             var directiveNName = ngAttrName.replace(/(Start|End)$/, '');
 16350             var directiveNName = ngAttrName.replace(/(Start|End)$/, '');
 16000             if (directiveIsMultiElement(directiveNName)) {
 16351             if (directiveIsMultiElement(directiveNName)) {
 16001               if (ngAttrName === directiveNName + 'Start') {
 16352               if (ngAttrName === directiveNName + 'Start') {
 16064      */
 16415      */
 16065     function groupScan(node, attrStart, attrEnd) {
 16416     function groupScan(node, attrStart, attrEnd) {
 16066       var nodes = [];
 16417       var nodes = [];
 16067       var depth = 0;
 16418       var depth = 0;
 16068       if (attrStart && node.hasAttribute && node.hasAttribute(attrStart)) {
 16419       if (attrStart && node.hasAttribute && node.hasAttribute(attrStart)) {
 16069         var startNode = node;
       
 16070         do {
 16420         do {
 16071           if (!node) {
 16421           if (!node) {
 16072             throw $compileMinErr('uterdir',
 16422             throw $compileMinErr('uterdir',
 16073                       "Unterminated attribute, found '{0}' but no matching '{1}' found.",
 16423                       "Unterminated attribute, found '{0}' but no matching '{1}' found.",
 16074                       attrStart, attrEnd);
 16424                       attrStart, attrEnd);
 16148           childTranscludeFn = transcludeFn,
 16498           childTranscludeFn = transcludeFn,
 16149           linkFn,
 16499           linkFn,
 16150           directiveValue;
 16500           directiveValue;
 16151 
 16501 
 16152       // executes all directives on the current element
 16502       // executes all directives on the current element
 16153       for(var i = 0, ii = directives.length; i < ii; i++) {
 16503       for (var i = 0, ii = directives.length; i < ii; i++) {
 16154         directive = directives[i];
 16504         directive = directives[i];
 16155         var attrStart = directive.$$start;
 16505         var attrStart = directive.$$start;
 16156         var attrEnd = directive.$$end;
 16506         var attrEnd = directive.$$end;
 16157 
 16507 
 16158         // collect multiblock sections
 16508         // collect multiblock sections
 16392           if (!value && !optional) {
 16742           if (!value && !optional) {
 16393             throw $compileMinErr('ctreq',
 16743             throw $compileMinErr('ctreq',
 16394                 "Controller '{0}', required by directive '{1}', can't be found!",
 16744                 "Controller '{0}', required by directive '{1}', can't be found!",
 16395                 require, directiveName);
 16745                 require, directiveName);
 16396           }
 16746           }
 16397           return value;
 16747           return value || null;
 16398         } else if (isArray(require)) {
 16748         } else if (isArray(require)) {
 16399           value = [];
 16749           value = [];
 16400           forEach(require, function(require) {
 16750           forEach(require, function(require) {
 16401             value.push(getControllers(directiveName, require, $element, elementControllers));
 16751             value.push(getControllers(directiveName, require, $element, elementControllers));
 16402           });
 16752           });
 16419 
 16769 
 16420         if (newIsolateScopeDirective) {
 16770         if (newIsolateScopeDirective) {
 16421           isolateScope = scope.$new(true);
 16771           isolateScope = scope.$new(true);
 16422         }
 16772         }
 16423 
 16773 
 16424         transcludeFn = boundTranscludeFn && controllersBoundTransclude;
 16774         if (boundTranscludeFn) {
       
 16775           // track `boundTranscludeFn` so it can be unwrapped if `transcludeFn`
       
 16776           // is later passed as `parentBoundTranscludeFn` to `publicLinkFn`
       
 16777           transcludeFn = controllersBoundTransclude;
       
 16778           transcludeFn.$$boundTransclude = boundTranscludeFn;
       
 16779         }
       
 16780 
 16425         if (controllerDirectives) {
 16781         if (controllerDirectives) {
 16426           // TODO: merge `controllers` and `elementControllers` into single object.
 16782           // TODO: merge `controllers` and `elementControllers` into single object.
 16427           controllers = {};
 16783           controllers = {};
 16428           elementControllers = {};
 16784           elementControllers = {};
 16429           forEach(controllerDirectives, function(directive) {
 16785           forEach(controllerDirectives, function(directive) {
 16454             controllers[directive.name] = controllerInstance;
 16810             controllers[directive.name] = controllerInstance;
 16455           });
 16811           });
 16456         }
 16812         }
 16457 
 16813 
 16458         if (newIsolateScopeDirective) {
 16814         if (newIsolateScopeDirective) {
 16459           var LOCAL_REGEXP = /^\s*([@=&])(\??)\s*(\w*)\s*$/;
       
 16460 
       
 16461           compile.$$addScopeInfo($element, isolateScope, true, !(templateDirective && (templateDirective === newIsolateScopeDirective ||
 16815           compile.$$addScopeInfo($element, isolateScope, true, !(templateDirective && (templateDirective === newIsolateScopeDirective ||
 16462               templateDirective === newIsolateScopeDirective.$$originalDirective)));
 16816               templateDirective === newIsolateScopeDirective.$$originalDirective)));
 16463           compile.$$addScopeClass($element, true);
 16817           compile.$$addScopeClass($element, true);
 16464 
 16818 
 16465           var isolateScopeController = controllers && controllers[newIsolateScopeDirective.name];
 16819           var isolateScopeController = controllers && controllers[newIsolateScopeDirective.name];
 16481               case '@':
 16835               case '@':
 16482                 attrs.$observe(attrName, function(value) {
 16836                 attrs.$observe(attrName, function(value) {
 16483                   isolateBindingContext[scopeName] = value;
 16837                   isolateBindingContext[scopeName] = value;
 16484                 });
 16838                 });
 16485                 attrs.$$observers[attrName].$$scope = scope;
 16839                 attrs.$$observers[attrName].$$scope = scope;
 16486                 if( attrs[attrName] ) {
 16840                 if (attrs[attrName]) {
 16487                   // If the attribute has been provided then we trigger an interpolation to ensure
 16841                   // If the attribute has been provided then we trigger an interpolation to ensure
 16488                   // the value is there for use in the link fn
 16842                   // the value is there for use in the link fn
 16489                   isolateBindingContext[scopeName] = $interpolate(attrs[attrName])(scope);
 16843                   isolateBindingContext[scopeName] = $interpolate(attrs[attrName])(scope);
 16490                 }
 16844                 }
 16491                 break;
 16845                 break;
 16496                 }
 16850                 }
 16497                 parentGet = $parse(attrs[attrName]);
 16851                 parentGet = $parse(attrs[attrName]);
 16498                 if (parentGet.literal) {
 16852                 if (parentGet.literal) {
 16499                   compare = equals;
 16853                   compare = equals;
 16500                 } else {
 16854                 } else {
 16501                   compare = function(a,b) { return a === b || (a !== a && b !== b); };
 16855                   compare = function(a, b) { return a === b || (a !== a && b !== b); };
 16502                 }
 16856                 }
 16503                 parentSet = parentGet.assign || function() {
 16857                 parentSet = parentGet.assign || function() {
 16504                   // reset the change, or we will throw this exception on every $digest
 16858                   // reset the change, or we will throw this exception on every $digest
 16505                   lastValue = isolateBindingContext[scopeName] = parentGet(scope);
 16859                   lastValue = isolateBindingContext[scopeName] = parentGet(scope);
 16506                   throw $compileMinErr('nonassign',
 16860                   throw $compileMinErr('nonassign',
 16520                     }
 16874                     }
 16521                   }
 16875                   }
 16522                   return lastValue = parentValue;
 16876                   return lastValue = parentValue;
 16523                 };
 16877                 };
 16524                 parentValueWatch.$stateful = true;
 16878                 parentValueWatch.$stateful = true;
 16525                 var unwatch = scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal);
 16879                 var unwatch;
       
 16880                 if (definition.collection) {
       
 16881                   unwatch = scope.$watchCollection(attrs[attrName], parentValueWatch);
       
 16882                 } else {
       
 16883                   unwatch = scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal);
       
 16884                 }
 16526                 isolateScope.$on('$destroy', unwatch);
 16885                 isolateScope.$on('$destroy', unwatch);
 16527                 break;
 16886                 break;
 16528 
 16887 
 16529               case '&':
 16888               case '&':
 16530                 parentGet = $parse(attrs[attrName]);
 16889                 parentGet = $parse(attrs[attrName]);
 16541           });
 16900           });
 16542           controllers = null;
 16901           controllers = null;
 16543         }
 16902         }
 16544 
 16903 
 16545         // PRELINKING
 16904         // PRELINKING
 16546         for(i = 0, ii = preLinkFns.length; i < ii; i++) {
 16905         for (i = 0, ii = preLinkFns.length; i < ii; i++) {
 16547           linkFn = preLinkFns[i];
 16906           linkFn = preLinkFns[i];
 16548           invokeLinkFn(linkFn,
 16907           invokeLinkFn(linkFn,
 16549               linkFn.isolateScope ? isolateScope : scope,
 16908               linkFn.isolateScope ? isolateScope : scope,
 16550               $element,
 16909               $element,
 16551               attrs,
 16910               attrs,
 16562           scopeToChild = isolateScope;
 16921           scopeToChild = isolateScope;
 16563         }
 16922         }
 16564         childLinkFn && childLinkFn(scopeToChild, linkNode.childNodes, undefined, boundTranscludeFn);
 16923         childLinkFn && childLinkFn(scopeToChild, linkNode.childNodes, undefined, boundTranscludeFn);
 16565 
 16924 
 16566         // POSTLINKING
 16925         // POSTLINKING
 16567         for(i = postLinkFns.length - 1; i >= 0; i--) {
 16926         for (i = postLinkFns.length - 1; i >= 0; i--) {
 16568           linkFn = postLinkFns[i];
 16927           linkFn = postLinkFns[i];
 16569           invokeLinkFn(linkFn,
 16928           invokeLinkFn(linkFn,
 16570               linkFn.isolateScope ? isolateScope : scope,
 16929               linkFn.isolateScope ? isolateScope : scope,
 16571               $element,
 16930               $element,
 16572               attrs,
 16931               attrs,
 16622     function addDirective(tDirectives, name, location, maxPriority, ignoreDirective, startAttrName,
 16981     function addDirective(tDirectives, name, location, maxPriority, ignoreDirective, startAttrName,
 16623                           endAttrName) {
 16982                           endAttrName) {
 16624       if (name === ignoreDirective) return null;
 16983       if (name === ignoreDirective) return null;
 16625       var match = null;
 16984       var match = null;
 16626       if (hasDirectives.hasOwnProperty(name)) {
 16985       if (hasDirectives.hasOwnProperty(name)) {
 16627         for(var directive, directives = $injector.get(name + Suffix),
 16986         for (var directive, directives = $injector.get(name + Suffix),
 16628             i = 0, ii = directives.length; i<ii; i++) {
 16987             i = 0, ii = directives.length; i < ii; i++) {
 16629           try {
 16988           try {
 16630             directive = directives[i];
 16989             directive = directives[i];
 16631             if ( (maxPriority === undefined || maxPriority > directive.priority) &&
 16990             if ((maxPriority === undefined || maxPriority > directive.priority) &&
 16632                  directive.restrict.indexOf(location) != -1) {
 16991                  directive.restrict.indexOf(location) != -1) {
 16633               if (startAttrName) {
 16992               if (startAttrName) {
 16634                 directive = inherit(directive, {$$start: startAttrName, $$end: endAttrName});
 16993                 directive = inherit(directive, {$$start: startAttrName, $$end: endAttrName});
 16635               }
 16994               }
 16636               tDirectives.push(directive);
 16995               tDirectives.push(directive);
 16637               match = directive;
 16996               match = directive;
 16638             }
 16997             }
 16639           } catch(e) { $exceptionHandler(e); }
 16998           } catch (e) { $exceptionHandler(e); }
 16640         }
 16999         }
 16641       }
 17000       }
 16642       return match;
 17001       return match;
 16643     }
 17002     }
 16644 
 17003 
 16651      * @param {string} name name of the directive to look up.
 17010      * @param {string} name name of the directive to look up.
 16652      * @returns true if directive was registered as multi-element.
 17011      * @returns true if directive was registered as multi-element.
 16653      */
 17012      */
 16654     function directiveIsMultiElement(name) {
 17013     function directiveIsMultiElement(name) {
 16655       if (hasDirectives.hasOwnProperty(name)) {
 17014       if (hasDirectives.hasOwnProperty(name)) {
 16656         for(var directive, directives = $injector.get(name + Suffix),
 17015         for (var directive, directives = $injector.get(name + Suffix),
 16657             i = 0, ii = directives.length; i<ii; i++) {
 17016             i = 0, ii = directives.length; i < ii; i++) {
 16658           directive = directives[i];
 17017           directive = directives[i];
 16659           if (directive.multiElement) {
 17018           if (directive.multiElement) {
 16660             return true;
 17019             return true;
 16661           }
 17020           }
 16662         }
 17021         }
 16768               $rootElement[i] = $compileNode[0];
 17127               $rootElement[i] = $compileNode[0];
 16769             }
 17128             }
 16770           });
 17129           });
 16771           afterTemplateChildLinkFn = compileNodes($compileNode[0].childNodes, childTranscludeFn);
 17130           afterTemplateChildLinkFn = compileNodes($compileNode[0].childNodes, childTranscludeFn);
 16772 
 17131 
 16773           while(linkQueue.length) {
 17132           while (linkQueue.length) {
 16774             var scope = linkQueue.shift(),
 17133             var scope = linkQueue.shift(),
 16775                 beforeTemplateLinkNode = linkQueue.shift(),
 17134                 beforeTemplateLinkNode = linkQueue.shift(),
 16776                 linkRootElement = linkQueue.shift(),
 17135                 linkRootElement = linkQueue.shift(),
 16777                 boundTranscludeFn = linkQueue.shift(),
 17136                 boundTranscludeFn = linkQueue.shift(),
 16778                 linkNode = $compileNode[0];
 17137                 linkNode = $compileNode[0];
 16805 
 17164 
 16806       return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, boundTranscludeFn) {
 17165       return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, boundTranscludeFn) {
 16807         var childBoundTranscludeFn = boundTranscludeFn;
 17166         var childBoundTranscludeFn = boundTranscludeFn;
 16808         if (scope.$$destroyed) return;
 17167         if (scope.$$destroyed) return;
 16809         if (linkQueue) {
 17168         if (linkQueue) {
 16810           linkQueue.push(scope);
 17169           linkQueue.push(scope,
 16811           linkQueue.push(node);
 17170                          node,
 16812           linkQueue.push(rootElement);
 17171                          rootElement,
 16813           linkQueue.push(childBoundTranscludeFn);
 17172                          childBoundTranscludeFn);
 16814         } else {
 17173         } else {
 16815           if (afterTemplateNodeLinkFn.transcludeOnThisElement) {
 17174           if (afterTemplateNodeLinkFn.transcludeOnThisElement) {
 16816             childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);
 17175             childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);
 16817           }
 17176           }
 16818           afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, childBoundTranscludeFn);
 17177           afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, childBoundTranscludeFn);
 16867     }
 17226     }
 16868 
 17227 
 16869 
 17228 
 16870     function wrapTemplate(type, template) {
 17229     function wrapTemplate(type, template) {
 16871       type = lowercase(type || 'html');
 17230       type = lowercase(type || 'html');
 16872       switch(type) {
 17231       switch (type) {
 16873       case 'svg':
 17232       case 'svg':
 16874       case 'math':
 17233       case 'math':
 16875         var wrapper = document.createElement('div');
 17234         var wrapper = document.createElement('div');
 16876         wrapper.innerHTML = '<'+type+'>'+template+'</'+type+'>';
 17235         wrapper.innerHTML = '<' + type + '>' + template + '</' + type + '>';
 16877         return wrapper.childNodes[0].childNodes;
 17236         return wrapper.childNodes[0].childNodes;
 16878       default:
 17237       default:
 16879         return template;
 17238         return template;
 16880       }
 17239       }
 16881     }
 17240     }
 16895       }
 17254       }
 16896     }
 17255     }
 16897 
 17256 
 16898 
 17257 
 16899     function addAttrInterpolateDirective(node, directives, value, name, allOrNothing) {
 17258     function addAttrInterpolateDirective(node, directives, value, name, allOrNothing) {
 16900       var interpolateFn = $interpolate(value, true);
 17259       var trustedContext = getTrustedContext(node, name);
       
 17260       allOrNothing = ALL_OR_NOTHING_ATTRS[name] || allOrNothing;
       
 17261 
       
 17262       var interpolateFn = $interpolate(value, true, trustedContext, allOrNothing);
 16901 
 17263 
 16902       // no interpolation found -> ignore
 17264       // no interpolation found -> ignore
 16903       if (!interpolateFn) return;
 17265       if (!interpolateFn) return;
 16904 
 17266 
 16905 
 17267 
 16920                   throw $compileMinErr('nodomevents',
 17282                   throw $compileMinErr('nodomevents',
 16921                       "Interpolations for HTML DOM event attributes are disallowed.  Please use the " +
 17283                       "Interpolations for HTML DOM event attributes are disallowed.  Please use the " +
 16922                           "ng- versions (such as ng-click instead of onclick) instead.");
 17284                           "ng- versions (such as ng-click instead of onclick) instead.");
 16923                 }
 17285                 }
 16924 
 17286 
 16925                 // If the attribute was removed, then we are done
 17287                 // If the attribute has changed since last $interpolate()ed
 16926                 if (!attr[name]) {
 17288                 var newValue = attr[name];
 16927                   return;
 17289                 if (newValue !== value) {
       
 17290                   // we need to interpolate again since the attribute value has been updated
       
 17291                   // (e.g. by another directive's compile function)
       
 17292                   // ensure unset/empty values make interpolateFn falsy
       
 17293                   interpolateFn = newValue && $interpolate(newValue, true, trustedContext, allOrNothing);
       
 17294                   value = newValue;
 16928                 }
 17295                 }
 16929 
       
 16930                 // we need to interpolate again, in case the attribute value has been updated
       
 16931                 // (e.g. by another directive's compile function)
       
 16932                 interpolateFn = $interpolate(attr[name], true, getTrustedContext(node, name),
       
 16933                     ALL_OR_NOTHING_ATTRS[name] || allOrNothing);
       
 16934 
 17296 
 16935                 // if attribute was updated so that there is no interpolation going on we don't want to
 17297                 // if attribute was updated so that there is no interpolation going on we don't want to
 16936                 // register any observers
 17298                 // register any observers
 16937                 if (!interpolateFn) return;
 17299                 if (!interpolateFn) return;
 16938 
 17300 
 16948                     //so that class changes can tap into the animation
 17310                     //so that class changes can tap into the animation
 16949                     //hooks provided by the $animate service. Be sure to
 17311                     //hooks provided by the $animate service. Be sure to
 16950                     //skip animations when the first digest occurs (when
 17312                     //skip animations when the first digest occurs (when
 16951                     //both the new and the old values are the same) since
 17313                     //both the new and the old values are the same) since
 16952                     //the CSS classes are the non-interpolated values
 17314                     //the CSS classes are the non-interpolated values
 16953                     if(name === 'class' && newValue != oldValue) {
 17315                     if (name === 'class' && newValue != oldValue) {
 16954                       attr.$updateClass(newValue, oldValue);
 17316                       attr.$updateClass(newValue, oldValue);
 16955                     } else {
 17317                     } else {
 16956                       attr.$set(name, newValue);
 17318                       attr.$set(name, newValue);
 16957                     }
 17319                     }
 16958                   });
 17320                   });
 16978           removeCount = elementsToRemove.length,
 17340           removeCount = elementsToRemove.length,
 16979           parent = firstElementToRemove.parentNode,
 17341           parent = firstElementToRemove.parentNode,
 16980           i, ii;
 17342           i, ii;
 16981 
 17343 
 16982       if ($rootElement) {
 17344       if ($rootElement) {
 16983         for(i = 0, ii = $rootElement.length; i < ii; i++) {
 17345         for (i = 0, ii = $rootElement.length; i < ii; i++) {
 16984           if ($rootElement[i] == firstElementToRemove) {
 17346           if ($rootElement[i] == firstElementToRemove) {
 16985             $rootElement[i++] = newNode;
 17347             $rootElement[i++] = newNode;
 16986             for (var j = i, j2 = j + removeCount - 1,
 17348             for (var j = i, j2 = j + removeCount - 1,
 16987                      jj = $rootElement.length;
 17349                      jj = $rootElement.length;
 16988                  j < jj; j++, j2++) {
 17350                  j < jj; j++, j2++) {
 17053 
 17415 
 17054 
 17416 
 17055     function invokeLinkFn(linkFn, scope, $element, attrs, controllers, transcludeFn) {
 17417     function invokeLinkFn(linkFn, scope, $element, attrs, controllers, transcludeFn) {
 17056       try {
 17418       try {
 17057         linkFn(scope, $element, attrs, controllers, transcludeFn);
 17419         linkFn(scope, $element, attrs, controllers, transcludeFn);
 17058       } catch(e) {
 17420       } catch (e) {
 17059         $exceptionHandler(e, startingTag($element));
 17421         $exceptionHandler(e, startingTag($element));
 17060       }
 17422       }
 17061     }
 17423     }
 17062   }];
 17424   }];
 17063 }
 17425 }
 17064 
 17426 
 17065 var PREFIX_REGEXP = /^(x[\:\-_]|data[\:\-_])/i;
 17427 var PREFIX_REGEXP = /^((?:x|data)[\:\-_])/i;
 17066 /**
 17428 /**
 17067  * Converts all accepted directives format into proper directive name.
 17429  * Converts all accepted directives format into proper directive name.
 17068  * All of these will become 'myDirective':
       
 17069  *   my:Directive
       
 17070  *   my-directive
       
 17071  *   x-my-directive
       
 17072  *   data-my:directive
       
 17073  *
       
 17074  * Also there is special case for Moz prefix starting with upper case letter.
       
 17075  * @param name Name to normalize
 17430  * @param name Name to normalize
 17076  */
 17431  */
 17077 function directiveNormalize(name) {
 17432 function directiveNormalize(name) {
 17078   return camelCase(name.replace(PREFIX_REGEXP, ''));
 17433   return camelCase(name.replace(PREFIX_REGEXP, ''));
 17079 }
 17434 }
 17126 function nodesetLinkingFn(
 17481 function nodesetLinkingFn(
 17127   /* angular.Scope */ scope,
 17482   /* angular.Scope */ scope,
 17128   /* NodeList */ nodeList,
 17483   /* NodeList */ nodeList,
 17129   /* Element */ rootElement,
 17484   /* Element */ rootElement,
 17130   /* function(Function) */ boundTranscludeFn
 17485   /* function(Function) */ boundTranscludeFn
 17131 ){}
 17486 ) {}
 17132 
 17487 
 17133 function directiveLinkingFn(
 17488 function directiveLinkingFn(
 17134   /* nodesetLinkingFn */ nodesetLinkingFn,
 17489   /* nodesetLinkingFn */ nodesetLinkingFn,
 17135   /* angular.Scope */ scope,
 17490   /* angular.Scope */ scope,
 17136   /* Node */ node,
 17491   /* Node */ node,
 17137   /* Element */ rootElement,
 17492   /* Element */ rootElement,
 17138   /* function(Function) */ boundTranscludeFn
 17493   /* function(Function) */ boundTranscludeFn
 17139 ){}
 17494 ) {}
 17140 
 17495 
 17141 function tokenDifference(str1, str2) {
 17496 function tokenDifference(str1, str2) {
 17142   var values = '',
 17497   var values = '',
 17143       tokens1 = str1.split(/\s+/),
 17498       tokens1 = str1.split(/\s+/),
 17144       tokens2 = str2.split(/\s+/);
 17499       tokens2 = str2.split(/\s+/);
 17145 
 17500 
 17146   outer:
 17501   outer:
 17147   for(var i = 0; i < tokens1.length; i++) {
 17502   for (var i = 0; i < tokens1.length; i++) {
 17148     var token = tokens1[i];
 17503     var token = tokens1[i];
 17149     for(var j = 0; j < tokens2.length; j++) {
 17504     for (var j = 0; j < tokens2.length; j++) {
 17150       if(token == tokens2[j]) continue outer;
 17505       if (token == tokens2[j]) continue outer;
 17151     }
 17506     }
 17152     values += (values.length > 0 ? ' ' : '') + token;
 17507     values += (values.length > 0 ? ' ' : '') + token;
 17153   }
 17508   }
 17154   return values;
 17509   return values;
 17155 }
 17510 }
 17227      *
 17582      *
 17228      *    * check if a controller with given name is registered via `$controllerProvider`
 17583      *    * check if a controller with given name is registered via `$controllerProvider`
 17229      *    * check if evaluating the string on the current scope returns a constructor
 17584      *    * check if evaluating the string on the current scope returns a constructor
 17230      *    * if $controllerProvider#allowGlobals, check `window[constructor]` on the global
 17585      *    * if $controllerProvider#allowGlobals, check `window[constructor]` on the global
 17231      *      `window` object (not recommended)
 17586      *      `window` object (not recommended)
       
 17587      *
       
 17588      *    The string can use the `controller as property` syntax, where the controller instance is published
       
 17589      *    as the specified property on the `scope`; the `scope` must be injected into `locals` param for this
       
 17590      *    to work correctly.
 17232      *
 17591      *
 17233      * @param {Object} locals Injection locals for Controller.
 17592      * @param {Object} locals Injection locals for Controller.
 17234      * @return {Object} Instance of given controller.
 17593      * @return {Object} Instance of given controller.
 17235      *
 17594      *
 17236      * @description
 17595      * @description
 17251       later = later === true;
 17610       later = later === true;
 17252       if (ident && isString(ident)) {
 17611       if (ident && isString(ident)) {
 17253         identifier = ident;
 17612         identifier = ident;
 17254       }
 17613       }
 17255 
 17614 
 17256       if(isString(expression)) {
 17615       if (isString(expression)) {
 17257         match = expression.match(CNTRL_REG),
 17616         match = expression.match(CNTRL_REG),
 17258         constructor = match[1],
 17617         constructor = match[1],
 17259         identifier = identifier || match[3];
 17618         identifier = identifier || match[3];
 17260         expression = controllers.hasOwnProperty(constructor)
 17619         expression = controllers.hasOwnProperty(constructor)
 17261             ? controllers[constructor]
 17620             ? controllers[constructor]
 17273         // This allows properties to be added to the controller before the constructor is
 17632         // This allows properties to be added to the controller before the constructor is
 17274         // invoked. Primarily, this is used for isolate scope bindings in $compile.
 17633         // invoked. Primarily, this is used for isolate scope bindings in $compile.
 17275         //
 17634         //
 17276         // This feature is not intended for use by applications, and is thus not documented
 17635         // This feature is not intended for use by applications, and is thus not documented
 17277         // publicly.
 17636         // publicly.
 17278         var Constructor = function() {};
 17637         // Object creation: http://jsperf.com/create-constructor/2
 17279         Constructor.prototype = (isArray(expression) ?
 17638         var controllerPrototype = (isArray(expression) ?
 17280           expression[expression.length - 1] : expression).prototype;
 17639           expression[expression.length - 1] : expression).prototype;
 17281         instance = new Constructor();
 17640         instance = Object.create(controllerPrototype);
 17282 
 17641 
 17283         if (identifier) {
 17642         if (identifier) {
 17284           addIdentifier(locals, identifier, instance, constructor || expression.name);
 17643           addIdentifier(locals, identifier, instance, constructor || expression.name);
 17285         }
 17644         }
 17286 
 17645 
 17337            $scope.windowTitle = angular.element(window.document)[0].title;
 17696            $scope.windowTitle = angular.element(window.document)[0].title;
 17338          }]);
 17697          }]);
 17339      </file>
 17698      </file>
 17340    </example>
 17699    </example>
 17341  */
 17700  */
 17342 function $DocumentProvider(){
 17701 function $DocumentProvider() {
 17343   this.$get = ['$window', function(window){
 17702   this.$get = ['$window', function(window) {
 17344     return jqLite(window.document);
 17703     return jqLite(window.document);
 17345   }];
 17704   }];
 17346 }
 17705 }
 17347 
 17706 
 17348 /**
 17707 /**
 17359  * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.
 17718  * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.
 17360  *
 17719  *
 17361  * ## Example:
 17720  * ## Example:
 17362  *
 17721  *
 17363  * ```js
 17722  * ```js
 17364  *   angular.module('exceptionOverride', []).factory('$exceptionHandler', function () {
 17723  *   angular.module('exceptionOverride', []).factory('$exceptionHandler', function() {
 17365  *     return function (exception, cause) {
 17724  *     return function(exception, cause) {
 17366  *       exception.message += ' (caused by "' + cause + '")';
 17725  *       exception.message += ' (caused by "' + cause + '")';
 17367  *       throw exception;
 17726  *       throw exception;
 17368  *     };
 17727  *     };
 17369  *   });
 17728  *   });
 17370  * ```
 17729  * ```
 17371  *
 17730  *
 17372  * This example will override the normal action of `$exceptionHandler`, to make angular
 17731  * This example will override the normal action of `$exceptionHandler`, to make angular
 17373  * exceptions fail hard when they happen, instead of just logging to the console.
 17732  * exceptions fail hard when they happen, instead of just logging to the console.
       
 17733  *
       
 17734  * <hr />
       
 17735  * Note, that code executed in event-listeners (even those registered using jqLite's `on`/`bind`
       
 17736  * methods) does not delegate exceptions to the {@link ng.$exceptionHandler $exceptionHandler}
       
 17737  * (unless executed during a digest).
       
 17738  *
       
 17739  * If you wish, you can manually delegate exceptions, e.g.
       
 17740  * `try { ... } catch(e) { $exceptionHandler(e); }`
 17374  *
 17741  *
 17375  * @param {Error} exception Exception associated with the error.
 17742  * @param {Error} exception Exception associated with the error.
 17376  * @param {string=} cause optional information about the context in which
 17743  * @param {string=} cause optional information about the context in which
 17377  *       the error was thrown.
 17744  *       the error was thrown.
 17378  *
 17745  *
 17383       $log.error.apply($log, arguments);
 17750       $log.error.apply($log, arguments);
 17384     };
 17751     };
 17385   }];
 17752   }];
 17386 }
 17753 }
 17387 
 17754 
       
 17755 var APPLICATION_JSON = 'application/json';
       
 17756 var CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': APPLICATION_JSON + ';charset=utf-8'};
       
 17757 var JSON_START = /^\[|^\{(?!\{)/;
       
 17758 var JSON_ENDS = {
       
 17759   '[': /]$/,
       
 17760   '{': /}$/
       
 17761 };
       
 17762 var JSON_PROTECTION_PREFIX = /^\)\]\}',?\n/;
       
 17763 
       
 17764 function defaultHttpResponseTransform(data, headers) {
       
 17765   if (isString(data)) {
       
 17766     // Strip json vulnerability protection prefix and trim whitespace
       
 17767     var tempData = data.replace(JSON_PROTECTION_PREFIX, '').trim();
       
 17768 
       
 17769     if (tempData) {
       
 17770       var contentType = headers('Content-Type');
       
 17771       if ((contentType && (contentType.indexOf(APPLICATION_JSON) === 0)) || isJsonLike(tempData)) {
       
 17772         data = fromJson(tempData);
       
 17773       }
       
 17774     }
       
 17775   }
       
 17776 
       
 17777   return data;
       
 17778 }
       
 17779 
       
 17780 function isJsonLike(str) {
       
 17781     var jsonStart = str.match(JSON_START);
       
 17782     return jsonStart && JSON_ENDS[jsonStart[0]].test(str);
       
 17783 }
       
 17784 
 17388 /**
 17785 /**
 17389  * Parse headers into key value object
 17786  * Parse headers into key value object
 17390  *
 17787  *
 17391  * @param {string} headers Raw headers as a string
 17788  * @param {string} headers Raw headers as a string
 17392  * @returns {Object} Parsed headers as key value object
 17789  * @returns {Object} Parsed headers as key value object
 17393  */
 17790  */
 17394 function parseHeaders(headers) {
 17791 function parseHeaders(headers) {
 17395   var parsed = {}, key, val, i;
 17792   var parsed = createMap(), key, val, i;
 17396 
 17793 
 17397   if (!headers) return parsed;
 17794   if (!headers) return parsed;
 17398 
 17795 
 17399   forEach(headers.split('\n'), function(line) {
 17796   forEach(headers.split('\n'), function(line) {
 17400     i = line.indexOf(':');
 17797     i = line.indexOf(':');
 17427 
 17824 
 17428   return function(name) {
 17825   return function(name) {
 17429     if (!headersObj) headersObj =  parseHeaders(headers);
 17826     if (!headersObj) headersObj =  parseHeaders(headers);
 17430 
 17827 
 17431     if (name) {
 17828     if (name) {
 17432       return headersObj[lowercase(name)] || null;
 17829       var value = headersObj[lowercase(name)];
       
 17830       if (value === void 0) {
       
 17831         value = null;
       
 17832       }
       
 17833       return value;
 17433     }
 17834     }
 17434 
 17835 
 17435     return headersObj;
 17836     return headersObj;
 17436   };
 17837   };
 17437 }
 17838 }
 17441  * Chain all given functions
 17842  * Chain all given functions
 17442  *
 17843  *
 17443  * This function is used for both request and response transforming
 17844  * This function is used for both request and response transforming
 17444  *
 17845  *
 17445  * @param {*} data Data to transform.
 17846  * @param {*} data Data to transform.
 17446  * @param {function(string=)} headers Http headers getter fn.
 17847  * @param {function(string=)} headers HTTP headers getter fn.
       
 17848  * @param {number} status HTTP status code of the response.
 17447  * @param {(Function|Array.<Function>)} fns Function or an array of functions.
 17849  * @param {(Function|Array.<Function>)} fns Function or an array of functions.
 17448  * @returns {*} Transformed data.
 17850  * @returns {*} Transformed data.
 17449  */
 17851  */
 17450 function transformData(data, headers, fns) {
 17852 function transformData(data, headers, status, fns) {
 17451   if (isFunction(fns))
 17853   if (isFunction(fns))
 17452     return fns(data, headers);
 17854     return fns(data, headers, status);
 17453 
 17855 
 17454   forEach(fns, function(fn) {
 17856   forEach(fns, function(fn) {
 17455     data = fn(data, headers);
 17857     data = fn(data, headers, status);
 17456   });
 17858   });
 17457 
 17859 
 17458   return data;
 17860   return data;
 17459 }
 17861 }
 17460 
 17862 
 17469  * @name $httpProvider
 17871  * @name $httpProvider
 17470  * @description
 17872  * @description
 17471  * Use `$httpProvider` to change the default behavior of the {@link ng.$http $http} service.
 17873  * Use `$httpProvider` to change the default behavior of the {@link ng.$http $http} service.
 17472  * */
 17874  * */
 17473 function $HttpProvider() {
 17875 function $HttpProvider() {
 17474   var JSON_START = /^\s*(\[|\{[^\{])/,
       
 17475       JSON_END = /[\}\]]\s*$/,
       
 17476       PROTECTION_PREFIX = /^\)\]\}',?\n/,
       
 17477       APPLICATION_JSON = 'application/json',
       
 17478       CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': APPLICATION_JSON + ';charset=utf-8'};
       
 17479 
       
 17480   /**
 17876   /**
 17481    * @ngdoc property
 17877    * @ngdoc property
 17482    * @name $httpProvider#defaults
 17878    * @name $httpProvider#defaults
 17483    * @description
 17879    * @description
 17484    *
 17880    *
 17485    * Object containing default values for all {@link ng.$http $http} requests.
 17881    * Object containing default values for all {@link ng.$http $http} requests.
       
 17882    *
       
 17883    * - **`defaults.cache`** - {Object} - an object built with {@link ng.$cacheFactory `$cacheFactory`}
       
 17884    * that will provide the cache for all requests who set their `cache` property to `true`.
       
 17885    * If you set the `default.cache = false` then only requests that specify their own custom
       
 17886    * cache object will be cached. See {@link $http#caching $http Caching} for more information.
 17486    *
 17887    *
 17487    * - **`defaults.xsrfCookieName`** - {string} - Name of cookie containing the XSRF token.
 17888    * - **`defaults.xsrfCookieName`** - {string} - Name of cookie containing the XSRF token.
 17488    * Defaults value is `'XSRF-TOKEN'`.
 17889    * Defaults value is `'XSRF-TOKEN'`.
 17489    *
 17890    *
 17490    * - **`defaults.xsrfHeaderName`** - {string} - Name of HTTP header to populate with the
 17891    * - **`defaults.xsrfHeaderName`** - {string} - Name of HTTP header to populate with the
 17495    * setting default headers.
 17896    * setting default headers.
 17496    *     - **`defaults.headers.common`**
 17897    *     - **`defaults.headers.common`**
 17497    *     - **`defaults.headers.post`**
 17898    *     - **`defaults.headers.post`**
 17498    *     - **`defaults.headers.put`**
 17899    *     - **`defaults.headers.put`**
 17499    *     - **`defaults.headers.patch`**
 17900    *     - **`defaults.headers.patch`**
       
 17901    *
 17500    **/
 17902    **/
 17501   var defaults = this.defaults = {
 17903   var defaults = this.defaults = {
 17502     // transform incoming response data
 17904     // transform incoming response data
 17503     transformResponse: [function defaultHttpResponseTransform(data, headers) {
 17905     transformResponse: [defaultHttpResponseTransform],
 17504       if (isString(data)) {
       
 17505         // strip json vulnerability protection prefix
       
 17506         data = data.replace(PROTECTION_PREFIX, '');
       
 17507         var contentType = headers('Content-Type');
       
 17508         if ((contentType && contentType.indexOf(APPLICATION_JSON) === 0) ||
       
 17509             (JSON_START.test(data) && JSON_END.test(data))) {
       
 17510           data = fromJson(data);
       
 17511         }
       
 17512       }
       
 17513       return data;
       
 17514     }],
       
 17515 
 17906 
 17516     // transform outgoing request data
 17907     // transform outgoing request data
 17517     transformRequest: [function(d) {
 17908     transformRequest: [function(d) {
 17518       return isObject(d) && !isFile(d) && !isBlob(d) ? toJson(d) : d;
 17909       return isObject(d) && !isFile(d) && !isBlob(d) && !isFormData(d) ? toJson(d) : d;
 17519     }],
 17910     }],
 17520 
 17911 
 17521     // default headers
 17912     // default headers
 17522     headers: {
 17913     headers: {
 17523       common: {
 17914       common: {
 17537    * @ngdoc method
 17928    * @ngdoc method
 17538    * @name $httpProvider#useApplyAsync
 17929    * @name $httpProvider#useApplyAsync
 17539    * @description
 17930    * @description
 17540    *
 17931    *
 17541    * Configure $http service to combine processing of multiple http responses received at around
 17932    * Configure $http service to combine processing of multiple http responses received at around
 17542    * the same time via {@link ng.$rootScope#applyAsync $rootScope.$applyAsync}. This can result in
 17933    * the same time via {@link ng.$rootScope.Scope#$applyAsync $rootScope.$applyAsync}. This can result in
 17543    * significant performance improvement for bigger applications that make many HTTP requests
 17934    * significant performance improvement for bigger applications that make many HTTP requests
 17544    * concurrently (common during application bootstrap).
 17935    * concurrently (common during application bootstrap).
 17545    *
 17936    *
 17546    * Defaults to false. If no value is specifed, returns the current configured value.
 17937    * Defaults to false. If no value is specifed, returns the current configured value.
 17547    *
 17938    *
 17559     }
 17950     }
 17560     return useApplyAsync;
 17951     return useApplyAsync;
 17561   };
 17952   };
 17562 
 17953 
 17563   /**
 17954   /**
 17564    * Are ordered by request, i.e. they are applied in the same order as the
 17955    * @ngdoc property
       
 17956    * @name $httpProvider#interceptors
       
 17957    * @description
       
 17958    *
       
 17959    * Array containing service factories for all synchronous or asynchronous {@link ng.$http $http}
       
 17960    * pre-processing of request or postprocessing of responses.
       
 17961    *
       
 17962    * These service factories are ordered by request, i.e. they are applied in the same order as the
 17565    * array, on request, but reverse order, on response.
 17963    * array, on request, but reverse order, on response.
 17566    */
 17964    *
       
 17965    * {@link ng.$http#interceptors Interceptors detailed info}
       
 17966    **/
 17567   var interceptorFactories = this.interceptors = [];
 17967   var interceptorFactories = this.interceptors = [];
 17568 
 17968 
 17569   this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',
 17969   this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',
 17570       function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {
 17970       function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {
 17571 
 17971 
 17613      * The `$http` service is a function which takes a single argument — a configuration object —
 18013      * The `$http` service is a function which takes a single argument — a configuration object —
 17614      * that is used to generate an HTTP request and returns  a {@link ng.$q promise}
 18014      * that is used to generate an HTTP request and returns  a {@link ng.$q promise}
 17615      * with two $http specific methods: `success` and `error`.
 18015      * with two $http specific methods: `success` and `error`.
 17616      *
 18016      *
 17617      * ```js
 18017      * ```js
 17618      *   $http({method: 'GET', url: '/someUrl'}).
 18018      *   // Simple GET request example :
       
 18019      *   $http.get('/someUrl').
 17619      *     success(function(data, status, headers, config) {
 18020      *     success(function(data, status, headers, config) {
 17620      *       // this callback will be called asynchronously
 18021      *       // this callback will be called asynchronously
 17621      *       // when the response is available
 18022      *       // when the response is available
 17622      *     }).
 18023      *     }).
 17623      *     error(function(data, status, headers, config) {
 18024      *     error(function(data, status, headers, config) {
 17624      *       // called asynchronously if an error occurs
 18025      *       // called asynchronously if an error occurs
 17625      *       // or server returns response with an error status.
 18026      *       // or server returns response with an error status.
 17626      *     });
 18027      *     });
 17627      * ```
 18028      * ```
       
 18029      *
       
 18030      * ```js
       
 18031      *   // Simple POST request example (passing data) :
       
 18032      *   $http.post('/someUrl', {msg:'hello word!'}).
       
 18033      *     success(function(data, status, headers, config) {
       
 18034      *       // this callback will be called asynchronously
       
 18035      *       // when the response is available
       
 18036      *     }).
       
 18037      *     error(function(data, status, headers, config) {
       
 18038      *       // called asynchronously if an error occurs
       
 18039      *       // or server returns response with an error status.
       
 18040      *     });
       
 18041      * ```
       
 18042      *
 17628      *
 18043      *
 17629      * Since the returned value of calling the $http function is a `promise`, you can also use
 18044      * Since the returned value of calling the $http function is a `promise`, you can also use
 17630      * the `then` method to register callbacks, and these callbacks will receive a single argument –
 18045      * the `then` method to register callbacks, and these callbacks will receive a single argument –
 17631      * an object representing the response. See the API signature and type info below for more
 18046      * an object representing the response. See the API signature and type info below for more
 17632      * details.
 18047      * details.
 17696      * ```
 18111      * ```
 17697      *
 18112      *
 17698      * In addition, you can supply a `headers` property in the config object passed when
 18113      * In addition, you can supply a `headers` property in the config object passed when
 17699      * calling `$http(config)`, which overrides the defaults without changing them globally.
 18114      * calling `$http(config)`, which overrides the defaults without changing them globally.
 17700      *
 18115      *
       
 18116      * To explicitly remove a header automatically added via $httpProvider.defaults.headers on a per request basis,
       
 18117      * Use the `headers` property, setting the desired header to `undefined`. For example:
       
 18118      *
       
 18119      * ```js
       
 18120      * var req = {
       
 18121      *  method: 'POST',
       
 18122      *  url: 'http://example.com',
       
 18123      *  headers: {
       
 18124      *    'Content-Type': undefined
       
 18125      *  },
       
 18126      *  data: { test: 'test' },
       
 18127      * }
       
 18128      *
       
 18129      * $http(req).success(function(){...}).error(function(){...});
       
 18130      * ```
 17701      *
 18131      *
 17702      * ## Transforming Requests and Responses
 18132      * ## Transforming Requests and Responses
 17703      *
 18133      *
 17704      * Both requests and responses can be transformed using transformation functions: `transformRequest`
 18134      * Both requests and responses can be transformed using transformation functions: `transformRequest`
 17705      * and `transformResponse`. These properties can be a single function that returns
 18135      * and `transformResponse`. These properties can be a single function that returns
 17706      * the transformed value (`{function(data, headersGetter)`) or an array of such transformation functions,
 18136      * the transformed value (`{function(data, headersGetter, status)`) or an array of such transformation functions,
 17707      * which allows you to `push` or `unshift` a new transformation function into the transformation chain.
 18137      * which allows you to `push` or `unshift` a new transformation function into the transformation chain.
 17708      *
 18138      *
 17709      * ### Default Transformations
 18139      * ### Default Transformations
 17710      *
 18140      *
 17711      * The `$httpProvider` provider and `$http` service expose `defaults.transformRequest` and
 18141      * The `$httpProvider` provider and `$http` service expose `defaults.transformRequest` and
 17776      * cache, but the cache is not populated yet, only one request to the server will be made and
 18206      * cache, but the cache is not populated yet, only one request to the server will be made and
 17777      * the remaining requests will be fulfilled using the response from the first request.
 18207      * the remaining requests will be fulfilled using the response from the first request.
 17778      *
 18208      *
 17779      * You can change the default cache to a new object (built with
 18209      * You can change the default cache to a new object (built with
 17780      * {@link ng.$cacheFactory `$cacheFactory`}) by updating the
 18210      * {@link ng.$cacheFactory `$cacheFactory`}) by updating the
 17781      * {@link ng.$http#properties_defaults `$http.defaults.cache`} property. All requests who set
 18211      * {@link ng.$http#defaults `$http.defaults.cache`} property. All requests who set
 17782      * their `cache` property to `true` will now use this cache object.
 18212      * their `cache` property to `true` will now use this cache object.
 17783      *
 18213      *
 17784      * If you set the default cache to `false` then only requests that specify their own custom
 18214      * If you set the default cache to `false` then only requests that specify their own custom
 17785      * cache object will be cached.
 18215      * cache object will be cached.
 17786      *
 18216      *
 17942      *    - **xsrfCookieName** – `{string}` – Name of cookie containing the XSRF token.
 18372      *    - **xsrfCookieName** – `{string}` – Name of cookie containing the XSRF token.
 17943      *    - **transformRequest** –
 18373      *    - **transformRequest** –
 17944      *      `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
 18374      *      `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
 17945      *      transform function or an array of such functions. The transform function takes the http
 18375      *      transform function or an array of such functions. The transform function takes the http
 17946      *      request body and headers and returns its transformed (typically serialized) version.
 18376      *      request body and headers and returns its transformed (typically serialized) version.
 17947      *      See {@link #overriding-the-default-transformations-per-request Overriding the Default Transformations}
 18377      *      See {@link ng.$http#overriding-the-default-transformations-per-request
       
 18378      *      Overriding the Default Transformations}
 17948      *    - **transformResponse** –
 18379      *    - **transformResponse** –
 17949      *      `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
 18380      *      `{function(data, headersGetter, status)|Array.<function(data, headersGetter, status)>}` –
 17950      *      transform function or an array of such functions. The transform function takes the http
 18381      *      transform function or an array of such functions. The transform function takes the http
 17951      *      response body and headers and returns its transformed (typically deserialized) version.
 18382      *      response body, headers and status and returns its transformed (typically deserialized) version.
 17952      *      See {@link #overriding-the-default-transformations-per-request Overriding the Default Transformations}
 18383      *      See {@link ng.$http#overriding-the-default-transformations-per-request
       
 18384      *      Overriding the Default Transformations}
 17953      *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the
 18385      *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the
 17954      *      GET request, otherwise if a cache instance built with
 18386      *      GET request, otherwise if a cache instance built with
 17955      *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for
 18387      *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for
 17956      *      caching.
 18388      *      caching.
 17957      *    - **timeout** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise}
 18389      *    - **timeout** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise}
 18068   });
 18500   });
 18069 </file>
 18501 </file>
 18070 </example>
 18502 </example>
 18071      */
 18503      */
 18072     function $http(requestConfig) {
 18504     function $http(requestConfig) {
 18073       var config = {
 18505 
       
 18506       if (!angular.isObject(requestConfig)) {
       
 18507         throw minErr('$http')('badreq', 'Http request configuration must be an object.  Received: {0}', requestConfig);
       
 18508       }
       
 18509 
       
 18510       var config = extend({
 18074         method: 'get',
 18511         method: 'get',
 18075         transformRequest: defaults.transformRequest,
 18512         transformRequest: defaults.transformRequest,
 18076         transformResponse: defaults.transformResponse
 18513         transformResponse: defaults.transformResponse
 18077       };
 18514       }, requestConfig);
 18078       var headers = mergeHeaders(requestConfig);
 18515 
 18079 
 18516       config.headers = mergeHeaders(requestConfig);
 18080       extend(config, requestConfig);
       
 18081       config.headers = headers;
       
 18082       config.method = uppercase(config.method);
 18517       config.method = uppercase(config.method);
 18083 
 18518 
 18084       var serverRequest = function(config) {
 18519       var serverRequest = function(config) {
 18085         headers = config.headers;
 18520         var headers = config.headers;
 18086         var reqData = transformData(config.data, headersGetter(headers), config.transformRequest);
 18521         var reqData = transformData(config.data, headersGetter(headers), undefined, config.transformRequest);
 18087 
 18522 
 18088         // strip content-type if data is undefined
 18523         // strip content-type if data is undefined
 18089         if (isUndefined(reqData)) {
 18524         if (isUndefined(reqData)) {
 18090           forEach(headers, function(value, header) {
 18525           forEach(headers, function(value, header) {
 18091             if (lowercase(header) === 'content-type') {
 18526             if (lowercase(header) === 'content-type') {
 18097         if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) {
 18532         if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) {
 18098           config.withCredentials = defaults.withCredentials;
 18533           config.withCredentials = defaults.withCredentials;
 18099         }
 18534         }
 18100 
 18535 
 18101         // send request
 18536         // send request
 18102         return sendReq(config, reqData, headers).then(transformResponse, transformResponse);
 18537         return sendReq(config, reqData).then(transformResponse, transformResponse);
 18103       };
 18538       };
 18104 
 18539 
 18105       var chain = [serverRequest, undefined];
 18540       var chain = [serverRequest, undefined];
 18106       var promise = $q.when(config);
 18541       var promise = $q.when(config);
 18107 
 18542 
 18113         if (interceptor.response || interceptor.responseError) {
 18548         if (interceptor.response || interceptor.responseError) {
 18114           chain.push(interceptor.response, interceptor.responseError);
 18549           chain.push(interceptor.response, interceptor.responseError);
 18115         }
 18550         }
 18116       });
 18551       });
 18117 
 18552 
 18118       while(chain.length) {
 18553       while (chain.length) {
 18119         var thenFn = chain.shift();
 18554         var thenFn = chain.shift();
 18120         var rejectFn = chain.shift();
 18555         var rejectFn = chain.shift();
 18121 
 18556 
 18122         promise = promise.then(thenFn, rejectFn);
 18557         promise = promise.then(thenFn, rejectFn);
 18123       }
 18558       }
 18138 
 18573 
 18139       return promise;
 18574       return promise;
 18140 
 18575 
 18141       function transformResponse(response) {
 18576       function transformResponse(response) {
 18142         // make a copy since the response must be cacheable
 18577         // make a copy since the response must be cacheable
 18143         var resp = extend({}, response, {
 18578         var resp = extend({}, response);
 18144           data: transformData(response.data, response.headers, config.transformResponse)
 18579         if (!response.data) {
 18145         });
 18580           resp.data = response.data;
       
 18581         } else {
       
 18582           resp.data = transformData(response.data, response.headers, response.status, config.transformResponse);
       
 18583         }
 18146         return (isSuccess(response.status))
 18584         return (isSuccess(response.status))
 18147           ? resp
 18585           ? resp
 18148           : $q.reject(resp);
 18586           : $q.reject(resp);
       
 18587       }
       
 18588 
       
 18589       function executeHeaderFns(headers) {
       
 18590         var headerContent, processedHeaders = {};
       
 18591 
       
 18592         forEach(headers, function(headerFn, header) {
       
 18593           if (isFunction(headerFn)) {
       
 18594             headerContent = headerFn();
       
 18595             if (headerContent != null) {
       
 18596               processedHeaders[header] = headerContent;
       
 18597             }
       
 18598           } else {
       
 18599             processedHeaders[header] = headerFn;
       
 18600           }
       
 18601         });
       
 18602 
       
 18603         return processedHeaders;
 18149       }
 18604       }
 18150 
 18605 
 18151       function mergeHeaders(config) {
 18606       function mergeHeaders(config) {
 18152         var defHeaders = defaults.headers,
 18607         var defHeaders = defaults.headers,
 18153             reqHeaders = extend({}, config.headers),
 18608             reqHeaders = extend({}, config.headers),
 18168 
 18623 
 18169           reqHeaders[defHeaderName] = defHeaders[defHeaderName];
 18624           reqHeaders[defHeaderName] = defHeaders[defHeaderName];
 18170         }
 18625         }
 18171 
 18626 
 18172         // execute if header value is a function for merged headers
 18627         // execute if header value is a function for merged headers
 18173         execHeaders(reqHeaders);
 18628         return executeHeaderFns(reqHeaders);
 18174         return reqHeaders;
       
 18175 
       
 18176         function execHeaders(headers) {
       
 18177           var headerContent;
       
 18178 
       
 18179           forEach(headers, function(headerFn, header) {
       
 18180             if (isFunction(headerFn)) {
       
 18181               headerContent = headerFn();
       
 18182               if (headerContent != null) {
       
 18183                 headers[header] = headerContent;
       
 18184               } else {
       
 18185                 delete headers[header];
       
 18186               }
       
 18187             }
       
 18188           });
       
 18189         }
       
 18190       }
 18629       }
 18191     }
 18630     }
 18192 
 18631 
 18193     $http.pendingRequests = [];
 18632     $http.pendingRequests = [];
 18194 
 18633 
 18327      * Makes the request.
 18766      * Makes the request.
 18328      *
 18767      *
 18329      * !!! ACCESSES CLOSURE VARS:
 18768      * !!! ACCESSES CLOSURE VARS:
 18330      * $httpBackend, defaults, $log, $rootScope, defaultCache, $http.pendingRequests
 18769      * $httpBackend, defaults, $log, $rootScope, defaultCache, $http.pendingRequests
 18331      */
 18770      */
 18332     function sendReq(config, reqData, reqHeaders) {
 18771     function sendReq(config, reqData) {
 18333       var deferred = $q.defer(),
 18772       var deferred = $q.defer(),
 18334           promise = deferred.promise,
 18773           promise = deferred.promise,
 18335           cache,
 18774           cache,
 18336           cachedResp,
 18775           cachedResp,
       
 18776           reqHeaders = config.headers,
 18337           url = buildUrl(config.url, config.params);
 18777           url = buildUrl(config.url, config.params);
 18338 
 18778 
 18339       $http.pendingRequests.push(config);
 18779       $http.pendingRequests.push(config);
 18340       promise.then(removePendingReq, removePendingReq);
 18780       promise.then(removePendingReq, removePendingReq);
 18341 
 18781 
 18350       if (cache) {
 18790       if (cache) {
 18351         cachedResp = cache.get(url);
 18791         cachedResp = cache.get(url);
 18352         if (isDefined(cachedResp)) {
 18792         if (isDefined(cachedResp)) {
 18353           if (isPromiseLike(cachedResp)) {
 18793           if (isPromiseLike(cachedResp)) {
 18354             // cached request has already been sent, but there is no response yet
 18794             // cached request has already been sent, but there is no response yet
 18355             cachedResp.then(removePendingReq, removePendingReq);
 18795             cachedResp.then(resolvePromiseWithResult, resolvePromiseWithResult);
 18356             return cachedResp;
       
 18357           } else {
 18796           } else {
 18358             // serving from cache
 18797             // serving from cache
 18359             if (isArray(cachedResp)) {
 18798             if (isArray(cachedResp)) {
 18360               resolvePromise(cachedResp[1], cachedResp[0], shallowCopy(cachedResp[2]), cachedResp[3]);
 18799               resolvePromise(cachedResp[1], cachedResp[0], shallowCopy(cachedResp[2]), cachedResp[3]);
 18361             } else {
 18800             } else {
 18425         (isSuccess(status) ? deferred.resolve : deferred.reject)({
 18864         (isSuccess(status) ? deferred.resolve : deferred.reject)({
 18426           data: response,
 18865           data: response,
 18427           status: status,
 18866           status: status,
 18428           headers: headersGetter(headers),
 18867           headers: headersGetter(headers),
 18429           config: config,
 18868           config: config,
 18430           statusText : statusText
 18869           statusText: statusText
 18431         });
 18870         });
 18432       }
 18871       }
 18433 
 18872 
       
 18873       function resolvePromiseWithResult(result) {
       
 18874         resolvePromise(result.data, result.status, shallowCopy(result.headers()), result.statusText);
       
 18875       }
 18434 
 18876 
 18435       function removePendingReq() {
 18877       function removePendingReq() {
 18436         var idx = $http.pendingRequests.indexOf(config);
 18878         var idx = $http.pendingRequests.indexOf(config);
 18437         if (idx !== -1) $http.pendingRequests.splice(idx, 1);
 18879         if (idx !== -1) $http.pendingRequests.splice(idx, 1);
 18438       }
 18880       }
 18446         if (value === null || isUndefined(value)) return;
 18888         if (value === null || isUndefined(value)) return;
 18447         if (!isArray(value)) value = [value];
 18889         if (!isArray(value)) value = [value];
 18448 
 18890 
 18449         forEach(value, function(v) {
 18891         forEach(value, function(v) {
 18450           if (isObject(v)) {
 18892           if (isObject(v)) {
 18451             if (isDate(v)){
 18893             if (isDate(v)) {
 18452               v = v.toISOString();
 18894               v = v.toISOString();
 18453             } else {
 18895             } else {
 18454               v = toJson(v);
 18896               v = toJson(v);
 18455             }
 18897             }
 18456           }
 18898           }
 18457           parts.push(encodeUriQuery(key) + '=' +
 18899           parts.push(encodeUriQuery(key) + '=' +
 18458                      encodeUriQuery(v));
 18900                      encodeUriQuery(v));
 18459         });
 18901         });
 18460       });
 18902       });
 18461       if(parts.length > 0) {
 18903       if (parts.length > 0) {
 18462         url += ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');
 18904         url += ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');
 18463       }
 18905       }
 18464       return url;
 18906       return url;
 18465     }
 18907     }
 18466   }];
 18908   }];
 18543             response,
 18985             response,
 18544             xhr.getAllResponseHeaders(),
 18986             xhr.getAllResponseHeaders(),
 18545             statusText);
 18987             statusText);
 18546       };
 18988       };
 18547 
 18989 
 18548       var requestError = function () {
 18990       var requestError = function() {
 18549         // The response is always empty
 18991         // The response is always empty
 18550         // See https://xhr.spec.whatwg.org/#request-error-steps and https://fetch.spec.whatwg.org/#concept-network-error
 18992         // See https://xhr.spec.whatwg.org/#request-error-steps and https://fetch.spec.whatwg.org/#concept-network-error
 18551         completeRequest(callback, -1, null, null, '');
 18993         completeRequest(callback, -1, null, null, '');
 18552       };
 18994       };
 18553 
 18995 
 18590       xhr && xhr.abort();
 19032       xhr && xhr.abort();
 18591     }
 19033     }
 18592 
 19034 
 18593     function completeRequest(callback, status, response, headersString, statusText) {
 19035     function completeRequest(callback, status, response, headersString, statusText) {
 18594       // cancel timeout and subsequent timeout promise resolution
 19036       // cancel timeout and subsequent timeout promise resolution
 18595       timeoutId && $browserDefer.cancel(timeoutId);
 19037       if (timeoutId !== undefined) {
       
 19038         $browserDefer.cancel(timeoutId);
       
 19039       }
 18596       jsonpDone = xhr = null;
 19040       jsonpDone = xhr = null;
 18597 
 19041 
 18598       callback(status, response, headersString, statusText);
 19042       callback(status, response, headersString, statusText);
 18599       $browser.$$completeOutstandingRequest(noop);
 19043       $browser.$$completeOutstandingRequest(noop);
 18600     }
 19044     }
 18685    * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.
 19129    * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.
 18686    *
 19130    *
 18687    * @param {string=} value new value to set the starting symbol to.
 19131    * @param {string=} value new value to set the starting symbol to.
 18688    * @returns {string|self} Returns the symbol when used as getter and self if used as setter.
 19132    * @returns {string|self} Returns the symbol when used as getter and self if used as setter.
 18689    */
 19133    */
 18690   this.startSymbol = function(value){
 19134   this.startSymbol = function(value) {
 18691     if (value) {
 19135     if (value) {
 18692       startSymbol = value;
 19136       startSymbol = value;
 18693       return this;
 19137       return this;
 18694     } else {
 19138     } else {
 18695       return startSymbol;
 19139       return startSymbol;
 18703    * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.
 19147    * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.
 18704    *
 19148    *
 18705    * @param {string=} value new value to set the ending symbol to.
 19149    * @param {string=} value new value to set the ending symbol to.
 18706    * @returns {string|self} Returns the symbol when used as getter and self if used as setter.
 19150    * @returns {string|self} Returns the symbol when used as getter and self if used as setter.
 18707    */
 19151    */
 18708   this.endSymbol = function(value){
 19152   this.endSymbol = function(value) {
 18709     if (value) {
 19153     if (value) {
 18710       endSymbol = value;
 19154       endSymbol = value;
 18711       return this;
 19155       return this;
 18712     } else {
 19156     } else {
 18713       return endSymbol;
 19157       return endSymbol;
 18829           textLength = text.length,
 19273           textLength = text.length,
 18830           exp,
 19274           exp,
 18831           concat = [],
 19275           concat = [],
 18832           expressionPositions = [];
 19276           expressionPositions = [];
 18833 
 19277 
 18834       while(index < textLength) {
 19278       while (index < textLength) {
 18835         if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&
 19279         if (((startIndex = text.indexOf(startSymbol, index)) != -1) &&
 18836              ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {
 19280              ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1)) {
 18837           if (index !== startIndex) {
 19281           if (index !== startIndex) {
 18838             concat.push(unescapeText(text.substring(index, startIndex)));
 19282             concat.push(unescapeText(text.substring(index, startIndex)));
 18839           }
 19283           }
 18840           exp = text.substring(startIndex + startSymbolLength, endIndex);
 19284           exp = text.substring(startIndex + startSymbolLength, endIndex);
 18841           expressions.push(exp);
 19285           expressions.push(exp);
 18865               "required.  See http://docs.angularjs.org/api/ng.$sce", text);
 19309               "required.  See http://docs.angularjs.org/api/ng.$sce", text);
 18866       }
 19310       }
 18867 
 19311 
 18868       if (!mustHaveExpression || expressions.length) {
 19312       if (!mustHaveExpression || expressions.length) {
 18869         var compute = function(values) {
 19313         var compute = function(values) {
 18870           for(var i = 0, ii = expressions.length; i < ii; i++) {
 19314           for (var i = 0, ii = expressions.length; i < ii; i++) {
 18871             if (allOrNothing && isUndefined(values[i])) return;
 19315             if (allOrNothing && isUndefined(values[i])) return;
 18872             concat[expressionPositions[i]] = values[i];
 19316             concat[expressionPositions[i]] = values[i];
 18873           }
 19317           }
 18874           return concat.join('');
 19318           return concat.join('');
 18875         };
 19319         };
 18876 
 19320 
 18877         var getValue = function (value) {
 19321         var getValue = function(value) {
 18878           return trustedContext ?
 19322           return trustedContext ?
 18879             $sce.getTrusted(trustedContext, value) :
 19323             $sce.getTrusted(trustedContext, value) :
 18880             $sce.valueOf(value);
 19324             $sce.valueOf(value);
 18881         };
 19325         };
 18882 
 19326 
 18883         var stringify = function (value) {
 19327         var stringify = function(value) {
 18884           if (value == null) { // null || undefined
 19328           if (value == null) { // null || undefined
 18885             return '';
 19329             return '';
 18886           }
 19330           }
 18887           switch (typeof value) {
 19331           switch (typeof value) {
 18888             case 'string': {
 19332             case 'string':
 18889               break;
 19333               break;
 18890             }
 19334             case 'number':
 18891             case 'number': {
       
 18892               value = '' + value;
 19335               value = '' + value;
 18893               break;
 19336               break;
 18894             }
 19337             default:
 18895             default: {
       
 18896               value = toJson(value);
 19338               value = toJson(value);
 18897             }
       
 18898           }
 19339           }
 18899 
 19340 
 18900           return value;
 19341           return value;
 18901         };
 19342         };
 18902 
 19343 
 18909               for (; i < ii; i++) {
 19350               for (; i < ii; i++) {
 18910                 values[i] = parseFns[i](context);
 19351                 values[i] = parseFns[i](context);
 18911               }
 19352               }
 18912 
 19353 
 18913               return compute(values);
 19354               return compute(values);
 18914             } catch(err) {
 19355             } catch (err) {
 18915               var newErr = $interpolateMinErr('interr', "Can't interpolate: {0}\n{1}", text,
 19356               var newErr = $interpolateMinErr('interr', "Can't interpolate: {0}\n{1}", text,
 18916                   err.toString());
 19357                   err.toString());
 18917               $exceptionHandler(newErr);
 19358               $exceptionHandler(newErr);
 18918             }
 19359             }
 18919 
 19360 
 18920           }, {
 19361           }, {
 18921           // all of these properties are undocumented for now
 19362           // all of these properties are undocumented for now
 18922           exp: text, //just for compatibility with regular watchers created via $watch
 19363           exp: text, //just for compatibility with regular watchers created via $watch
 18923           expressions: expressions,
 19364           expressions: expressions,
 18924           $$watchDelegate: function (scope, listener, objectEquality) {
 19365           $$watchDelegate: function(scope, listener, objectEquality) {
 18925             var lastValue;
 19366             var lastValue;
 18926             return scope.$watchGroup(parseFns, function interpolateFnWatcher(values, oldValues) {
 19367             return scope.$watchGroup(parseFns, function interpolateFnWatcher(values, oldValues) {
 18927               var currValue = compute(values);
 19368               var currValue = compute(values);
 18928               if (isFunction(listener)) {
 19369               if (isFunction(listener)) {
 18929                 listener.call(this, currValue, values !== oldValues ? lastValue : currValue, scope);
 19370                 listener.call(this, currValue, values !== oldValues ? lastValue : currValue, scope);
 18939           replace(escapedEndRegexp, endSymbol);
 19380           replace(escapedEndRegexp, endSymbol);
 18940       }
 19381       }
 18941 
 19382 
 18942       function parseStringifyInterceptor(value) {
 19383       function parseStringifyInterceptor(value) {
 18943         try {
 19384         try {
 18944           return stringify(getValue(value));
 19385           value = getValue(value);
 18945         } catch(err) {
 19386           return allOrNothing && !isDefined(value) ? value : stringify(value);
       
 19387         } catch (err) {
 18946           var newErr = $interpolateMinErr('interr', "Can't interpolate: {0}\n{1}", text,
 19388           var newErr = $interpolateMinErr('interr', "Can't interpolate: {0}\n{1}", text,
 18947             err.toString());
 19389             err.toString());
 18948           $exceptionHandler(newErr);
 19390           $exceptionHandler(newErr);
 18949         }
 19391         }
 18950       }
 19392       }
 19040       *           var stop;
 19482       *           var stop;
 19041       *           $scope.fight = function() {
 19483       *           $scope.fight = function() {
 19042       *             // Don't start a new fight if we are already fighting
 19484       *             // Don't start a new fight if we are already fighting
 19043       *             if ( angular.isDefined(stop) ) return;
 19485       *             if ( angular.isDefined(stop) ) return;
 19044       *
 19486       *
 19045       *           stop = $interval(function() {
 19487       *             stop = $interval(function() {
 19046       *             if ($scope.blood_1 > 0 && $scope.blood_2 > 0) {
 19488       *               if ($scope.blood_1 > 0 && $scope.blood_2 > 0) {
 19047       *               $scope.blood_1 = $scope.blood_1 - 3;
 19489       *                 $scope.blood_1 = $scope.blood_1 - 3;
 19048       *               $scope.blood_2 = $scope.blood_2 - 4;
 19490       *                 $scope.blood_2 = $scope.blood_2 - 4;
 19049       *             } else {
 19491       *               } else {
 19050       *               $scope.stopFight();
 19492       *                 $scope.stopFight();
       
 19493       *               }
       
 19494       *             }, 100);
       
 19495       *           };
       
 19496       *
       
 19497       *           $scope.stopFight = function() {
       
 19498       *             if (angular.isDefined(stop)) {
       
 19499       *               $interval.cancel(stop);
       
 19500       *               stop = undefined;
 19051       *             }
 19501       *             }
 19052       *           }, 100);
 19502       *           };
 19053       *         };
       
 19054       *
 19503       *
 19055       *         $scope.stopFight = function() {
 19504       *           $scope.resetFight = function() {
 19056       *           if (angular.isDefined(stop)) {
 19505       *             $scope.blood_1 = 100;
 19057       *             $interval.cancel(stop);
 19506       *             $scope.blood_2 = 120;
 19058       *             stop = undefined;
 19507       *           };
 19059       *           }
       
 19060       *         };
       
 19061       *
 19508       *
 19062       *         $scope.resetFight = function() {
 19509       *           $scope.$on('$destroy', function() {
 19063       *           $scope.blood_1 = 100;
 19510       *             // Make sure that the interval is destroyed too
 19064       *           $scope.blood_2 = 120;
 19511       *             $scope.stopFight();
 19065       *         };
 19512       *           });
 19066       *
 19513       *         }])
 19067       *         $scope.$on('$destroy', function() {
       
 19068       *           // Make sure that the interval is destroyed too
       
 19069       *           $scope.stopFight();
       
 19070       *         });
       
 19071       *       }])
       
 19072       *       // Register the 'myCurrentTime' directive factory method.
 19514       *       // Register the 'myCurrentTime' directive factory method.
 19073       *       // We inject $interval and dateFilter service since the factory method is DI.
 19515       *       // We inject $interval and dateFilter service since the factory method is DI.
 19074       *       .directive('myCurrentTime', ['$interval', 'dateFilter',
 19516       *       .directive('myCurrentTime', ['$interval', 'dateFilter',
 19075       *         function($interval, dateFilter) {
 19517       *         function($interval, dateFilter) {
 19076       *           // return the directive link function. (compile function not needed)
 19518       *           // return the directive link function. (compile function not needed)
 19179  * $locale service provides localization rules for various Angular components. As of right now the
 19621  * $locale service provides localization rules for various Angular components. As of right now the
 19180  * only public api is:
 19622  * only public api is:
 19181  *
 19623  *
 19182  * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)
 19624  * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)
 19183  */
 19625  */
 19184 function $LocaleProvider(){
 19626 function $LocaleProvider() {
 19185   this.$get = function() {
 19627   this.$get = function() {
 19186     return {
 19628     return {
 19187       id: 'en-us',
 19629       id: 'en-us',
 19188 
 19630 
 19189       NUMBER_FORMATS: {
 19631       NUMBER_FORMATS: {
 19222         SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),
 19664         SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),
 19223         DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),
 19665         DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),
 19224         SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),
 19666         SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),
 19225         AMPMS: ['AM','PM'],
 19667         AMPMS: ['AM','PM'],
 19226         medium: 'MMM d, y h:mm:ss a',
 19668         medium: 'MMM d, y h:mm:ss a',
 19227         short: 'M/d/yy h:mm a',
 19669         'short': 'M/d/yy h:mm a',
 19228         fullDate: 'EEEE, MMMM d, y',
 19670         fullDate: 'EEEE, MMMM d, y',
 19229         longDate: 'MMMM d, y',
 19671         longDate: 'MMMM d, y',
 19230         mediumDate: 'MMM d, y',
 19672         mediumDate: 'MMM d, y',
 19231         shortDate: 'M/d/yy',
 19673         shortDate: 'M/d/yy',
 19232         mediumTime: 'h:mm:ss a',
 19674         mediumTime: 'h:mm:ss a',
 19263   }
 19705   }
 19264 
 19706 
 19265   return segments.join('/');
 19707   return segments.join('/');
 19266 }
 19708 }
 19267 
 19709 
 19268 function parseAbsoluteUrl(absoluteUrl, locationObj, appBase) {
 19710 function parseAbsoluteUrl(absoluteUrl, locationObj) {
 19269   var parsedUrl = urlResolve(absoluteUrl, appBase);
 19711   var parsedUrl = urlResolve(absoluteUrl);
 19270 
 19712 
 19271   locationObj.$$protocol = parsedUrl.protocol;
 19713   locationObj.$$protocol = parsedUrl.protocol;
 19272   locationObj.$$host = parsedUrl.hostname;
 19714   locationObj.$$host = parsedUrl.hostname;
 19273   locationObj.$$port = int(parsedUrl.port) || DEFAULT_PORTS[parsedUrl.protocol] || null;
 19715   locationObj.$$port = int(parsedUrl.port) || DEFAULT_PORTS[parsedUrl.protocol] || null;
 19274 }
 19716 }
 19275 
 19717 
 19276 
 19718 
 19277 function parseAppUrl(relativeUrl, locationObj, appBase) {
 19719 function parseAppUrl(relativeUrl, locationObj) {
 19278   var prefixed = (relativeUrl.charAt(0) !== '/');
 19720   var prefixed = (relativeUrl.charAt(0) !== '/');
 19279   if (prefixed) {
 19721   if (prefixed) {
 19280     relativeUrl = '/' + relativeUrl;
 19722     relativeUrl = '/' + relativeUrl;
 19281   }
 19723   }
 19282   var match = urlResolve(relativeUrl, appBase);
 19724   var match = urlResolve(relativeUrl);
 19283   locationObj.$$path = decodeURIComponent(prefixed && match.pathname.charAt(0) === '/' ?
 19725   locationObj.$$path = decodeURIComponent(prefixed && match.pathname.charAt(0) === '/' ?
 19284       match.pathname.substring(1) : match.pathname);
 19726       match.pathname.substring(1) : match.pathname);
 19285   locationObj.$$search = parseKeyValue(match.search);
 19727   locationObj.$$search = parseKeyValue(match.search);
 19286   locationObj.$$hash = decodeURIComponent(match.hash);
 19728   locationObj.$$hash = decodeURIComponent(match.hash);
 19287 
 19729 
 19309 function stripHash(url) {
 19751 function stripHash(url) {
 19310   var index = url.indexOf('#');
 19752   var index = url.indexOf('#');
 19311   return index == -1 ? url : url.substr(0, index);
 19753   return index == -1 ? url : url.substr(0, index);
 19312 }
 19754 }
 19313 
 19755 
       
 19756 function trimEmptyHash(url) {
       
 19757   return url.replace(/(#.+)|#$/, '$1');
       
 19758 }
       
 19759 
 19314 
 19760 
 19315 function stripFile(url) {
 19761 function stripFile(url) {
 19316   return url.substr(0, stripHash(url).lastIndexOf('/') + 1);
 19762   return url.substr(0, stripHash(url).lastIndexOf('/') + 1);
 19317 }
 19763 }
 19318 
 19764 
 19332  */
 19778  */
 19333 function LocationHtml5Url(appBase, basePrefix) {
 19779 function LocationHtml5Url(appBase, basePrefix) {
 19334   this.$$html5 = true;
 19780   this.$$html5 = true;
 19335   basePrefix = basePrefix || '';
 19781   basePrefix = basePrefix || '';
 19336   var appBaseNoFile = stripFile(appBase);
 19782   var appBaseNoFile = stripFile(appBase);
 19337   parseAbsoluteUrl(appBase, this, appBase);
 19783   parseAbsoluteUrl(appBase, this);
 19338 
 19784 
 19339 
 19785 
 19340   /**
 19786   /**
 19341    * Parse given html5 (regular) url string into properties
 19787    * Parse given html5 (regular) url string into properties
 19342    * @param {string} newAbsoluteUrl HTML5 url
 19788    * @param {string} url HTML5 url
 19343    * @private
 19789    * @private
 19344    */
 19790    */
 19345   this.$$parse = function(url) {
 19791   this.$$parse = function(url) {
 19346     var pathUrl = beginsWith(appBaseNoFile, url);
 19792     var pathUrl = beginsWith(appBaseNoFile, url);
 19347     if (!isString(pathUrl)) {
 19793     if (!isString(pathUrl)) {
 19348       throw $locationMinErr('ipthprfx', 'Invalid url "{0}", missing path prefix "{1}".', url,
 19794       throw $locationMinErr('ipthprfx', 'Invalid url "{0}", missing path prefix "{1}".', url,
 19349           appBaseNoFile);
 19795           appBaseNoFile);
 19350     }
 19796     }
 19351 
 19797 
 19352     parseAppUrl(pathUrl, this, appBase);
 19798     parseAppUrl(pathUrl, this);
 19353 
 19799 
 19354     if (!this.$$path) {
 19800     if (!this.$$path) {
 19355       this.$$path = '/';
 19801       this.$$path = '/';
 19356     }
 19802     }
 19357 
 19803 
 19378       return true;
 19824       return true;
 19379     }
 19825     }
 19380     var appUrl, prevAppUrl;
 19826     var appUrl, prevAppUrl;
 19381     var rewrittenUrl;
 19827     var rewrittenUrl;
 19382 
 19828 
 19383     if ( (appUrl = beginsWith(appBase, url)) !== undefined ) {
 19829     if ((appUrl = beginsWith(appBase, url)) !== undefined) {
 19384       prevAppUrl = appUrl;
 19830       prevAppUrl = appUrl;
 19385       if ( (appUrl = beginsWith(basePrefix, appUrl)) !== undefined ) {
 19831       if ((appUrl = beginsWith(basePrefix, appUrl)) !== undefined) {
 19386         rewrittenUrl = appBaseNoFile + (beginsWith('/', appUrl) || appUrl);
 19832         rewrittenUrl = appBaseNoFile + (beginsWith('/', appUrl) || appUrl);
 19387       } else {
 19833       } else {
 19388         rewrittenUrl = appBase + prevAppUrl;
 19834         rewrittenUrl = appBase + prevAppUrl;
 19389       }
 19835       }
 19390     } else if ( (appUrl = beginsWith(appBaseNoFile, url)) !== undefined ) {
 19836     } else if ((appUrl = beginsWith(appBaseNoFile, url)) !== undefined) {
 19391       rewrittenUrl = appBaseNoFile + appUrl;
 19837       rewrittenUrl = appBaseNoFile + appUrl;
 19392     } else if (appBaseNoFile == url + '/') {
 19838     } else if (appBaseNoFile == url + '/') {
 19393       rewrittenUrl = appBaseNoFile;
 19839       rewrittenUrl = appBaseNoFile;
 19394     }
 19840     }
 19395     if (rewrittenUrl) {
 19841     if (rewrittenUrl) {
 19410  * @param {string} hashPrefix hashbang prefix
 19856  * @param {string} hashPrefix hashbang prefix
 19411  */
 19857  */
 19412 function LocationHashbangUrl(appBase, hashPrefix) {
 19858 function LocationHashbangUrl(appBase, hashPrefix) {
 19413   var appBaseNoFile = stripFile(appBase);
 19859   var appBaseNoFile = stripFile(appBase);
 19414 
 19860 
 19415   parseAbsoluteUrl(appBase, this, appBase);
 19861   parseAbsoluteUrl(appBase, this);
 19416 
 19862 
 19417 
 19863 
 19418   /**
 19864   /**
 19419    * Parse given hashbang url into properties
 19865    * Parse given hashbang url into properties
 19420    * @param {string} url Hashbang url
 19866    * @param {string} url Hashbang url
 19421    * @private
 19867    * @private
 19422    */
 19868    */
 19423   this.$$parse = function(url) {
 19869   this.$$parse = function(url) {
 19424     var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url);
 19870     var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url);
 19425     var withoutHashUrl = withoutBaseUrl.charAt(0) == '#'
 19871     var withoutHashUrl;
 19426         ? beginsWith(hashPrefix, withoutBaseUrl)
 19872 
 19427         : (this.$$html5)
 19873     if (withoutBaseUrl.charAt(0) === '#') {
 19428           ? withoutBaseUrl
 19874 
 19429           : '';
 19875       // The rest of the url starts with a hash so we have
 19430 
 19876       // got either a hashbang path or a plain hash fragment
 19431     if (!isString(withoutHashUrl)) {
 19877       withoutHashUrl = beginsWith(hashPrefix, withoutBaseUrl);
 19432       throw $locationMinErr('ihshprfx', 'Invalid url "{0}", missing hash prefix "{1}".', url,
 19878       if (isUndefined(withoutHashUrl)) {
 19433           hashPrefix);
 19879         // There was no hashbang prefix so we just have a hash fragment
 19434     }
 19880         withoutHashUrl = withoutBaseUrl;
 19435     parseAppUrl(withoutHashUrl, this, appBase);
 19881       }
       
 19882 
       
 19883     } else {
       
 19884       // There was no hashbang path nor hash fragment:
       
 19885       // If we are in HTML5 mode we use what is left as the path;
       
 19886       // Otherwise we ignore what is left
       
 19887       withoutHashUrl = this.$$html5 ? withoutBaseUrl : '';
       
 19888     }
       
 19889 
       
 19890     parseAppUrl(withoutHashUrl, this);
 19436 
 19891 
 19437     this.$$path = removeWindowsDriveName(this.$$path, withoutHashUrl, appBase);
 19892     this.$$path = removeWindowsDriveName(this.$$path, withoutHashUrl, appBase);
 19438 
 19893 
 19439     this.$$compose();
 19894     this.$$compose();
 19440 
 19895 
 19447      *   * a.pathname === '/C:/foo' //true
 19902      *   * a.pathname === '/C:/foo' //true
 19448      *
 19903      *
 19449      * Inside of Angular, we're always using pathnames that
 19904      * Inside of Angular, we're always using pathnames that
 19450      * do not include drive names for routing.
 19905      * do not include drive names for routing.
 19451      */
 19906      */
 19452     function removeWindowsDriveName (path, url, base) {
 19907     function removeWindowsDriveName(path, url, base) {
 19453       /*
 19908       /*
 19454       Matches paths for file protocol on windows,
 19909       Matches paths for file protocol on windows,
 19455       such as /C:/foo/bar, and captures only /foo/bar.
 19910       such as /C:/foo/bar, and captures only /foo/bar.
 19456       */
 19911       */
 19457       var windowsFilePathExp = /^\/[A-Z]:(\/.*)/;
 19912       var windowsFilePathExp = /^\/[A-Z]:(\/.*)/;
 19484     this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
 19939     this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
 19485     this.$$absUrl = appBase + (this.$$url ? hashPrefix + this.$$url : '');
 19940     this.$$absUrl = appBase + (this.$$url ? hashPrefix + this.$$url : '');
 19486   };
 19941   };
 19487 
 19942 
 19488   this.$$parseLinkUrl = function(url, relHref) {
 19943   this.$$parseLinkUrl = function(url, relHref) {
 19489     if(stripHash(appBase) == stripHash(url)) {
 19944     if (stripHash(appBase) == stripHash(url)) {
 19490       this.$$parse(url);
 19945       this.$$parse(url);
 19491       return true;
 19946       return true;
 19492     }
 19947     }
 19493     return false;
 19948     return false;
 19494   };
 19949   };
 19519     }
 19974     }
 19520 
 19975 
 19521     var rewrittenUrl;
 19976     var rewrittenUrl;
 19522     var appUrl;
 19977     var appUrl;
 19523 
 19978 
 19524     if ( appBase == stripHash(url) ) {
 19979     if (appBase == stripHash(url)) {
 19525       rewrittenUrl = url;
 19980       rewrittenUrl = url;
 19526     } else if ( (appUrl = beginsWith(appBaseNoFile, url)) ) {
 19981     } else if ((appUrl = beginsWith(appBaseNoFile, url))) {
 19527       rewrittenUrl = appBase + hashPrefix + appUrl;
 19982       rewrittenUrl = appBase + hashPrefix + appUrl;
 19528     } else if ( appBaseNoFile === url + '/') {
 19983     } else if (appBaseNoFile === url + '/') {
 19529       rewrittenUrl = appBaseNoFile;
 19984       rewrittenUrl = appBaseNoFile;
 19530     }
 19985     }
 19531     if (rewrittenUrl) {
 19986     if (rewrittenUrl) {
 19532       this.$$parse(rewrittenUrl);
 19987       this.$$parse(rewrittenUrl);
 19533     }
 19988     }
 19567    * @description
 20022    * @description
 19568    * This method is getter only.
 20023    * This method is getter only.
 19569    *
 20024    *
 19570    * Return full url representation with all segments encoded according to rules specified in
 20025    * Return full url representation with all segments encoded according to rules specified in
 19571    * [RFC 3986](http://www.ietf.org/rfc/rfc3986.txt).
 20026    * [RFC 3986](http://www.ietf.org/rfc/rfc3986.txt).
       
 20027    *
       
 20028    *
       
 20029    * ```js
       
 20030    * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
       
 20031    * var absUrl = $location.absUrl();
       
 20032    * // => "http://example.com/#/some/path?foo=bar&baz=xoxo"
       
 20033    * ```
 19572    *
 20034    *
 19573    * @return {string} full url
 20035    * @return {string} full url
 19574    */
 20036    */
 19575   absUrl: locationGetter('$$absUrl'),
 20037   absUrl: locationGetter('$$absUrl'),
 19576 
 20038 
 19583    *
 20045    *
 19584    * Return url (e.g. `/path?a=b#hash`) when called without any parameter.
 20046    * Return url (e.g. `/path?a=b#hash`) when called without any parameter.
 19585    *
 20047    *
 19586    * Change path, search and hash, when called with parameter and return `$location`.
 20048    * Change path, search and hash, when called with parameter and return `$location`.
 19587    *
 20049    *
       
 20050    *
       
 20051    * ```js
       
 20052    * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
       
 20053    * var url = $location.url();
       
 20054    * // => "/some/path?foo=bar&baz=xoxo"
       
 20055    * ```
       
 20056    *
 19588    * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)
 20057    * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)
 19589    * @return {string} url
 20058    * @return {string} url
 19590    */
 20059    */
 19591   url: function(url) {
 20060   url: function(url) {
 19592     if (isUndefined(url))
 20061     if (isUndefined(url))
 19593       return this.$$url;
 20062       return this.$$url;
 19594 
 20063 
 19595     var match = PATH_MATCH.exec(url);
 20064     var match = PATH_MATCH.exec(url);
 19596     if (match[1]) this.path(decodeURIComponent(match[1]));
 20065     if (match[1] || url === '') this.path(decodeURIComponent(match[1]));
 19597     if (match[2] || match[1]) this.search(match[3] || '');
 20066     if (match[2] || match[1] || url === '') this.search(match[3] || '');
 19598     this.hash(match[5] || '');
 20067     this.hash(match[5] || '');
 19599 
 20068 
 19600     return this;
 20069     return this;
 19601   },
 20070   },
 19602 
 20071 
 19607    * @description
 20076    * @description
 19608    * This method is getter only.
 20077    * This method is getter only.
 19609    *
 20078    *
 19610    * Return protocol of current url.
 20079    * Return protocol of current url.
 19611    *
 20080    *
       
 20081    *
       
 20082    * ```js
       
 20083    * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
       
 20084    * var protocol = $location.protocol();
       
 20085    * // => "http"
       
 20086    * ```
       
 20087    *
 19612    * @return {string} protocol of current url
 20088    * @return {string} protocol of current url
 19613    */
 20089    */
 19614   protocol: locationGetter('$$protocol'),
 20090   protocol: locationGetter('$$protocol'),
 19615 
 20091 
 19616   /**
 20092   /**
 19620    * @description
 20096    * @description
 19621    * This method is getter only.
 20097    * This method is getter only.
 19622    *
 20098    *
 19623    * Return host of current url.
 20099    * Return host of current url.
 19624    *
 20100    *
       
 20101    *
       
 20102    * ```js
       
 20103    * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
       
 20104    * var host = $location.host();
       
 20105    * // => "example.com"
       
 20106    * ```
       
 20107    *
 19625    * @return {string} host of current url.
 20108    * @return {string} host of current url.
 19626    */
 20109    */
 19627   host: locationGetter('$$host'),
 20110   host: locationGetter('$$host'),
 19628 
 20111 
 19629   /**
 20112   /**
 19632    *
 20115    *
 19633    * @description
 20116    * @description
 19634    * This method is getter only.
 20117    * This method is getter only.
 19635    *
 20118    *
 19636    * Return port of current url.
 20119    * Return port of current url.
       
 20120    *
       
 20121    *
       
 20122    * ```js
       
 20123    * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
       
 20124    * var port = $location.port();
       
 20125    * // => 80
       
 20126    * ```
 19637    *
 20127    *
 19638    * @return {Number} port
 20128    * @return {Number} port
 19639    */
 20129    */
 19640   port: locationGetter('$$port'),
 20130   port: locationGetter('$$port'),
 19641 
 20131 
 19650    *
 20140    *
 19651    * Change path when called with parameter and return `$location`.
 20141    * Change path when called with parameter and return `$location`.
 19652    *
 20142    *
 19653    * Note: Path should always begin with forward slash (/), this method will add the forward slash
 20143    * Note: Path should always begin with forward slash (/), this method will add the forward slash
 19654    * if it is missing.
 20144    * if it is missing.
       
 20145    *
       
 20146    *
       
 20147    * ```js
       
 20148    * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
       
 20149    * var path = $location.path();
       
 20150    * // => "/some/path"
       
 20151    * ```
 19655    *
 20152    *
 19656    * @param {(string|number)=} path New path
 20153    * @param {(string|number)=} path New path
 19657    * @return {string} path
 20154    * @return {string} path
 19658    */
 20155    */
 19659   path: locationGetterSetter('$$path', function(path) {
 20156   path: locationGetterSetter('$$path', function(path) {
 19676    * ```js
 20173    * ```js
 19677    * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
 20174    * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
 19678    * var searchObject = $location.search();
 20175    * var searchObject = $location.search();
 19679    * // => {foo: 'bar', baz: 'xoxo'}
 20176    * // => {foo: 'bar', baz: 'xoxo'}
 19680    *
 20177    *
 19681    *
       
 19682    * // set foo to 'yipee'
 20178    * // set foo to 'yipee'
 19683    * $location.search('foo', 'yipee');
 20179    * $location.search('foo', 'yipee');
 19684    * // => $location
 20180    * // $location.search() => {foo: 'yipee', baz: 'xoxo'}
 19685    * ```
 20181    * ```
 19686    *
 20182    *
 19687    * @param {string|Object.<string>|Object.<Array.<string>>} search New search params - string or
 20183    * @param {string|Object.<string>|Object.<Array.<string>>} search New search params - string or
 19688    * hash object.
 20184    * hash object.
 19689    *
 20185    *
 19714       case 1:
 20210       case 1:
 19715         if (isString(search) || isNumber(search)) {
 20211         if (isString(search) || isNumber(search)) {
 19716           search = search.toString();
 20212           search = search.toString();
 19717           this.$$search = parseKeyValue(search);
 20213           this.$$search = parseKeyValue(search);
 19718         } else if (isObject(search)) {
 20214         } else if (isObject(search)) {
       
 20215           search = copy(search, {});
 19719           // remove object undefined or null properties
 20216           // remove object undefined or null properties
 19720           forEach(search, function(value, key) {
 20217           forEach(search, function(value, key) {
 19721             if (value == null) delete search[key];
 20218             if (value == null) delete search[key];
 19722           });
 20219           });
 19723 
 20220 
 19747    * This method is getter / setter.
 20244    * This method is getter / setter.
 19748    *
 20245    *
 19749    * Return hash fragment when called without any parameter.
 20246    * Return hash fragment when called without any parameter.
 19750    *
 20247    *
 19751    * Change hash fragment when called with parameter and return `$location`.
 20248    * Change hash fragment when called with parameter and return `$location`.
       
 20249    *
       
 20250    *
       
 20251    * ```js
       
 20252    * // given url http://example.com/#/some/path?foo=bar&baz=xoxo#hashValue
       
 20253    * var hash = $location.hash();
       
 20254    * // => "hashValue"
       
 20255    * ```
 19752    *
 20256    *
 19753    * @param {(string|number)=} hash New hash fragment
 20257    * @param {(string|number)=} hash New hash fragment
 19754    * @return {string} hash
 20258    * @return {string} hash
 19755    */
 20259    */
 19756   hash: locationGetterSetter('$$hash', function(hash) {
 20260   hash: locationGetterSetter('$$hash', function(hash) {
 19769     this.$$replace = true;
 20273     this.$$replace = true;
 19770     return this;
 20274     return this;
 19771   }
 20275   }
 19772 };
 20276 };
 19773 
 20277 
 19774 forEach([LocationHashbangInHtml5Url, LocationHashbangUrl, LocationHtml5Url], function (Location) {
 20278 forEach([LocationHashbangInHtml5Url, LocationHashbangUrl, LocationHtml5Url], function(Location) {
 19775   Location.prototype = Object.create(locationPrototype);
 20279   Location.prototype = Object.create(locationPrototype);
 19776 
 20280 
 19777   /**
 20281   /**
 19778    * @ngdoc method
 20282    * @ngdoc method
 19779    * @name $location#state
 20283    * @name $location#state
 19861  * @ngdoc provider
 20365  * @ngdoc provider
 19862  * @name $locationProvider
 20366  * @name $locationProvider
 19863  * @description
 20367  * @description
 19864  * Use the `$locationProvider` to configure how the application deep linking paths are stored.
 20368  * Use the `$locationProvider` to configure how the application deep linking paths are stored.
 19865  */
 20369  */
 19866 function $LocationProvider(){
 20370 function $LocationProvider() {
 19867   var hashPrefix = '',
 20371   var hashPrefix = '',
 19868       html5Mode = {
 20372       html5Mode = {
 19869         enabled: false,
 20373         enabled: false,
 19870         requireBase: true,
 20374         requireBase: true,
 19871         rewriteLinks: true
 20375         rewriteLinks: true
 19899    *     support `pushState`.
 20403    *     support `pushState`.
 19900    *   - **requireBase** - `{boolean}` - (default: `true`) When html5Mode is enabled, specifies
 20404    *   - **requireBase** - `{boolean}` - (default: `true`) When html5Mode is enabled, specifies
 19901    *     whether or not a <base> tag is required to be present. If `enabled` and `requireBase` are
 20405    *     whether or not a <base> tag is required to be present. If `enabled` and `requireBase` are
 19902    *     true, and a base tag is not present, an error will be thrown when `$location` is injected.
 20406    *     true, and a base tag is not present, an error will be thrown when `$location` is injected.
 19903    *     See the {@link guide/$location $location guide for more information}
 20407    *     See the {@link guide/$location $location guide for more information}
 19904    *   - **rewriteLinks** - `{boolean}` - (default: `false`) When html5Mode is enabled, disables
 20408    *   - **rewriteLinks** - `{boolean}` - (default: `true`) When html5Mode is enabled,
 19905    *     url rewriting for relative linksTurns off url rewriting for relative links.
 20409    *     enables/disables url rewriting for relative links.
 19906    *
 20410    *
 19907    * @returns {Object} html5Mode object if used as getter or itself (chaining) if used as setter
 20411    * @returns {Object} html5Mode object if used as getter or itself (chaining) if used as setter
 19908    */
 20412    */
 19909   this.html5Mode = function(mode) {
 20413   this.html5Mode = function(mode) {
 19910     if (isBoolean(mode)) {
 20414     if (isBoolean(mode)) {
 19911       html5Mode.enabled = mode;
 20415       html5Mode.enabled = mode;
 19912       return this;
 20416       return this;
 19913     } else if (isObject(mode)) {
 20417     } else if (isObject(mode)) {
 19914 
 20418 
 19915       if (isBoolean(mode.enabled)) {
 20419       if (isBoolean(mode.enabled)) {
 19916         html5Mode.enabled =  mode.enabled;
 20420         html5Mode.enabled = mode.enabled;
 19917       }
 20421       }
 19918 
 20422 
 19919       if (isBoolean(mode.requireBase)) {
 20423       if (isBoolean(mode.requireBase)) {
 19920         html5Mode.requireBase = mode.requireBase;
 20424         html5Mode.requireBase = mode.requireBase;
 19921       }
 20425       }
 19922 
 20426 
 19923       if (isBoolean(mode.rewriteLinks)) {
 20427       if (isBoolean(mode.rewriteLinks)) {
 19924         html5Mode.rewriteLinks =  mode.rewriteLinks;
 20428         html5Mode.rewriteLinks = mode.rewriteLinks;
 19925       }
 20429       }
 19926 
 20430 
 19927       return this;
 20431       return this;
 19928     } else {
 20432     } else {
 19929       return html5Mode;
 20433       return html5Mode;
 19938    * Broadcasted before a URL will change.
 20442    * Broadcasted before a URL will change.
 19939    *
 20443    *
 19940    * This change can be prevented by calling
 20444    * This change can be prevented by calling
 19941    * `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on} for more
 20445    * `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on} for more
 19942    * details about event object. Upon successful change
 20446    * details about event object. Upon successful change
 19943    * {@link ng.$location#events_$locationChangeSuccess $locationChangeSuccess} is fired.
 20447    * {@link ng.$location#$locationChangeSuccess $locationChangeSuccess} is fired.
 19944    *
 20448    *
 19945    * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when
 20449    * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when
 19946    * the browser supports the HTML5 History API.
 20450    * the browser supports the HTML5 History API.
 19947    *
 20451    *
 19948    * @param {Object} angularEvent Synthetic event object.
 20452    * @param {Object} angularEvent Synthetic event object.
 19967    * @param {string=} oldUrl URL that was before it was changed.
 20471    * @param {string=} oldUrl URL that was before it was changed.
 19968    * @param {string=} newState New history state object
 20472    * @param {string=} newState New history state object
 19969    * @param {string=} oldState History state object that was before it was changed.
 20473    * @param {string=} oldState History state object that was before it was changed.
 19970    */
 20474    */
 19971 
 20475 
 19972   this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',
 20476   this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement', '$window',
 19973       function( $rootScope,   $browser,   $sniffer,   $rootElement) {
 20477       function($rootScope, $browser, $sniffer, $rootElement, $window) {
 19974     var $location,
 20478     var $location,
 19975         LocationMode,
 20479         LocationMode,
 19976         baseHref = $browser.baseHref(), // if base[href] is undefined, it defaults to ''
 20480         baseHref = $browser.baseHref(), // if base[href] is undefined, it defaults to ''
 19977         initialUrl = $browser.url(),
 20481         initialUrl = $browser.url(),
 19978         appBase;
 20482         appBase;
 20050           event.preventDefault();
 20554           event.preventDefault();
 20051           // update location manually
 20555           // update location manually
 20052           if ($location.absUrl() != $browser.url()) {
 20556           if ($location.absUrl() != $browser.url()) {
 20053             $rootScope.$apply();
 20557             $rootScope.$apply();
 20054             // hack to work around FF6 bug 684208 when scenario runner clicks on links
 20558             // hack to work around FF6 bug 684208 when scenario runner clicks on links
 20055             window.angular['ff-684208-preventDefault'] = true;
 20559             $window.angular['ff-684208-preventDefault'] = true;
 20056           }
 20560           }
 20057         }
 20561         }
 20058       }
 20562       }
 20059     });
 20563     });
 20060 
 20564 
 20069     // update $location when $browser url changes
 20573     // update $location when $browser url changes
 20070     $browser.onUrlChange(function(newUrl, newState) {
 20574     $browser.onUrlChange(function(newUrl, newState) {
 20071       $rootScope.$evalAsync(function() {
 20575       $rootScope.$evalAsync(function() {
 20072         var oldUrl = $location.absUrl();
 20576         var oldUrl = $location.absUrl();
 20073         var oldState = $location.$$state;
 20577         var oldState = $location.$$state;
       
 20578         var defaultPrevented;
 20074 
 20579 
 20075         $location.$$parse(newUrl);
 20580         $location.$$parse(newUrl);
 20076         $location.$$state = newState;
 20581         $location.$$state = newState;
 20077         if ($rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl,
 20582 
 20078             newState, oldState).defaultPrevented) {
 20583         defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl,
       
 20584             newState, oldState).defaultPrevented;
       
 20585 
       
 20586         // if the location was changed by a `$locationChangeStart` handler then stop
       
 20587         // processing this location change
       
 20588         if ($location.absUrl() !== newUrl) return;
       
 20589 
       
 20590         if (defaultPrevented) {
 20079           $location.$$parse(oldUrl);
 20591           $location.$$parse(oldUrl);
 20080           $location.$$state = oldState;
 20592           $location.$$state = oldState;
 20081           setBrowserUrlWithFallback(oldUrl, false, oldState);
 20593           setBrowserUrlWithFallback(oldUrl, false, oldState);
 20082         } else {
 20594         } else {
 20083           initializing = false;
 20595           initializing = false;
 20087       if (!$rootScope.$$phase) $rootScope.$digest();
 20599       if (!$rootScope.$$phase) $rootScope.$digest();
 20088     });
 20600     });
 20089 
 20601 
 20090     // update browser
 20602     // update browser
 20091     $rootScope.$watch(function $locationWatch() {
 20603     $rootScope.$watch(function $locationWatch() {
 20092       var oldUrl = $browser.url();
 20604       var oldUrl = trimEmptyHash($browser.url());
       
 20605       var newUrl = trimEmptyHash($location.absUrl());
 20093       var oldState = $browser.state();
 20606       var oldState = $browser.state();
 20094       var currentReplace = $location.$$replace;
 20607       var currentReplace = $location.$$replace;
 20095 
 20608       var urlOrStateChanged = oldUrl !== newUrl ||
 20096       if (initializing || oldUrl !== $location.absUrl() ||
 20609         ($location.$$html5 && $sniffer.history && oldState !== $location.$$state);
 20097           ($location.$$html5 && $sniffer.history && oldState !== $location.$$state)) {
 20610 
       
 20611       if (initializing || urlOrStateChanged) {
 20098         initializing = false;
 20612         initializing = false;
 20099 
 20613 
 20100         $rootScope.$evalAsync(function() {
 20614         $rootScope.$evalAsync(function() {
 20101           if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl,
 20615           var newUrl = $location.absUrl();
 20102               $location.$$state, oldState).defaultPrevented) {
 20616           var defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl,
       
 20617               $location.$$state, oldState).defaultPrevented;
       
 20618 
       
 20619           // if the location was changed by a `$locationChangeStart` handler then stop
       
 20620           // processing this location change
       
 20621           if ($location.absUrl() !== newUrl) return;
       
 20622 
       
 20623           if (defaultPrevented) {
 20103             $location.$$parse(oldUrl);
 20624             $location.$$parse(oldUrl);
 20104             $location.$$state = oldState;
 20625             $location.$$state = oldState;
 20105           } else {
 20626           } else {
 20106             setBrowserUrlWithFallback($location.absUrl(), currentReplace,
 20627             if (urlOrStateChanged) {
 20107                                       oldState === $location.$$state ? null : $location.$$state);
 20628               setBrowserUrlWithFallback(newUrl, currentReplace,
       
 20629                                         oldState === $location.$$state ? null : $location.$$state);
       
 20630             }
 20108             afterLocationChange(oldUrl, oldState);
 20631             afterLocationChange(oldUrl, oldState);
 20109           }
 20632           }
 20110         });
 20633         });
 20111       }
 20634       }
 20112 
 20635 
 20166  * @ngdoc provider
 20689  * @ngdoc provider
 20167  * @name $logProvider
 20690  * @name $logProvider
 20168  * @description
 20691  * @description
 20169  * Use the `$logProvider` to configure how the application logs messages
 20692  * Use the `$logProvider` to configure how the application logs messages
 20170  */
 20693  */
 20171 function $LogProvider(){
 20694 function $LogProvider() {
 20172   var debug = true,
 20695   var debug = true,
 20173       self = this;
 20696       self = this;
 20174 
 20697 
 20175   /**
 20698   /**
 20176    * @ngdoc method
 20699    * @ngdoc method
 20186     } else {
 20709     } else {
 20187       return debug;
 20710       return debug;
 20188     }
 20711     }
 20189   };
 20712   };
 20190 
 20713 
 20191   this.$get = ['$window', function($window){
 20714   this.$get = ['$window', function($window) {
 20192     return {
 20715     return {
 20193       /**
 20716       /**
 20194        * @ngdoc method
 20717        * @ngdoc method
 20195        * @name $log#log
 20718        * @name $log#log
 20196        *
 20719        *
 20231        * @name $log#debug
 20754        * @name $log#debug
 20232        *
 20755        *
 20233        * @description
 20756        * @description
 20234        * Write a debug message
 20757        * Write a debug message
 20235        */
 20758        */
 20236       debug: (function () {
 20759       debug: (function() {
 20237         var fn = consoleLog('debug');
 20760         var fn = consoleLog('debug');
 20238 
 20761 
 20239         return function() {
 20762         return function() {
 20240           if (debug) {
 20763           if (debug) {
 20241             fn.apply(self, arguments);
 20764             fn.apply(self, arguments);
 20290 var $parseMinErr = minErr('$parse');
 20813 var $parseMinErr = minErr('$parse');
 20291 
 20814 
 20292 // Sandboxing Angular Expressions
 20815 // Sandboxing Angular Expressions
 20293 // ------------------------------
 20816 // ------------------------------
 20294 // Angular expressions are generally considered safe because these expressions only have direct
 20817 // Angular expressions are generally considered safe because these expressions only have direct
 20295 // access to $scope and locals. However, one can obtain the ability to execute arbitrary JS code by
 20818 // access to `$scope` and locals. However, one can obtain the ability to execute arbitrary JS code by
 20296 // obtaining a reference to native JS functions such as the Function constructor.
 20819 // obtaining a reference to native JS functions such as the Function constructor.
 20297 //
 20820 //
 20298 // As an example, consider the following Angular expression:
 20821 // As an example, consider the following Angular expression:
 20299 //
 20822 //
 20300 //   {}.toString.constructor('alert("evil JS code")')
 20823 //   {}.toString.constructor('alert("evil JS code")')
 20301 //
 20824 //
 20302 // This sandboxing technique is not perfect and doesn't aim to be. The goal is to prevent exploits
 20825 // This sandboxing technique is not perfect and doesn't aim to be. The goal is to prevent exploits
 20303 // against the expression language, but not to prevent exploits that were enabled by exposing
 20826 // against the expression language, but not to prevent exploits that were enabled by exposing
 20304 // sensitive JavaScript or browser apis on Scope. Exposing such objects on a Scope is never a good
 20827 // sensitive JavaScript or browser APIs on Scope. Exposing such objects on a Scope is never a good
 20305 // practice and therefore we are not even trying to protect against interaction with an object
 20828 // practice and therefore we are not even trying to protect against interaction with an object
 20306 // explicitly exposed in this way.
 20829 // explicitly exposed in this way.
 20307 //
 20830 //
 20308 // In general, it is not possible to access a Window object from an angular expression unless a
 20831 // In general, it is not possible to access a Window object from an angular expression unless a
 20309 // window or some DOM object that has a reference to window is published onto a Scope.
 20832 // window or some DOM object that has a reference to window is published onto a Scope.
 20310 // Similarly we prevent invocations of function known to be dangerous, as well as assignments to
 20833 // Similarly we prevent invocations of function known to be dangerous, as well as assignments to
 20311 // native objects.
 20834 // native objects.
       
 20835 //
       
 20836 // See https://docs.angularjs.org/guide/security
 20312 
 20837 
 20313 
 20838 
 20314 function ensureSafeMemberName(name, fullExpression) {
 20839 function ensureSafeMemberName(name, fullExpression) {
 20315   if (name === "__defineGetter__" || name === "__defineSetter__"
 20840   if (name === "__defineGetter__" || name === "__defineSetter__"
 20316       || name === "__lookupGetter__" || name === "__lookupSetter__"
 20841       || name === "__lookupGetter__" || name === "__lookupSetter__"
 20317       || name === "__proto__") {
 20842       || name === "__proto__") {
 20318     throw $parseMinErr('isecfld',
 20843     throw $parseMinErr('isecfld',
 20319         'Attempting to access a disallowed field in Angular expressions! '
 20844         'Attempting to access a disallowed field in Angular expressions! '
 20320         +'Expression: {0}', fullExpression);
 20845         + 'Expression: {0}', fullExpression);
 20321   }
 20846   }
 20322   return name;
 20847   return name;
 20323 }
 20848 }
 20324 
 20849 
 20325 function ensureSafeObject(obj, fullExpression) {
 20850 function ensureSafeObject(obj, fullExpression) {
 20384 CONSTANTS['this'].sharedGetter = true;
 20909 CONSTANTS['this'].sharedGetter = true;
 20385 
 20910 
 20386 
 20911 
 20387 //Operators - will be wrapped by binaryFn/unaryFn/assignment/filter
 20912 //Operators - will be wrapped by binaryFn/unaryFn/assignment/filter
 20388 var OPERATORS = extend(createMap(), {
 20913 var OPERATORS = extend(createMap(), {
 20389     /* jshint bitwise : false */
 20914     '+':function(self, locals, a, b) {
 20390     '+':function(self, locals, a,b){
       
 20391       a=a(self, locals); b=b(self, locals);
 20915       a=a(self, locals); b=b(self, locals);
 20392       if (isDefined(a)) {
 20916       if (isDefined(a)) {
 20393         if (isDefined(b)) {
 20917         if (isDefined(b)) {
 20394           return a + b;
 20918           return a + b;
 20395         }
 20919         }
 20396         return a;
 20920         return a;
 20397       }
 20921       }
 20398       return isDefined(b)?b:undefined;},
 20922       return isDefined(b) ? b : undefined;},
 20399     '-':function(self, locals, a,b){
 20923     '-':function(self, locals, a, b) {
 20400           a=a(self, locals); b=b(self, locals);
 20924           a=a(self, locals); b=b(self, locals);
 20401           return (isDefined(a)?a:0)-(isDefined(b)?b:0);
 20925           return (isDefined(a) ? a : 0) - (isDefined(b) ? b : 0);
 20402         },
 20926         },
 20403     '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},
 20927     '*':function(self, locals, a, b) {return a(self, locals) * b(self, locals);},
 20404     '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},
 20928     '/':function(self, locals, a, b) {return a(self, locals) / b(self, locals);},
 20405     '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},
 20929     '%':function(self, locals, a, b) {return a(self, locals) % b(self, locals);},
 20406     '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},
 20930     '===':function(self, locals, a, b) {return a(self, locals) === b(self, locals);},
 20407     '===':function(self, locals, a, b){return a(self, locals)===b(self, locals);},
 20931     '!==':function(self, locals, a, b) {return a(self, locals) !== b(self, locals);},
 20408     '!==':function(self, locals, a, b){return a(self, locals)!==b(self, locals);},
 20932     '==':function(self, locals, a, b) {return a(self, locals) == b(self, locals);},
 20409     '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},
 20933     '!=':function(self, locals, a, b) {return a(self, locals) != b(self, locals);},
 20410     '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},
 20934     '<':function(self, locals, a, b) {return a(self, locals) < b(self, locals);},
 20411     '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},
 20935     '>':function(self, locals, a, b) {return a(self, locals) > b(self, locals);},
 20412     '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},
 20936     '<=':function(self, locals, a, b) {return a(self, locals) <= b(self, locals);},
 20413     '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},
 20937     '>=':function(self, locals, a, b) {return a(self, locals) >= b(self, locals);},
 20414     '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},
 20938     '&&':function(self, locals, a, b) {return a(self, locals) && b(self, locals);},
 20415     '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},
 20939     '||':function(self, locals, a, b) {return a(self, locals) || b(self, locals);},
 20416     '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},
 20940     '!':function(self, locals, a) {return !a(self, locals);},
 20417     '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},
       
 20418     '!':function(self, locals, a){return !a(self, locals);},
       
 20419 
 20941 
 20420     //Tokenized as operators but parsed as assignment/filters
 20942     //Tokenized as operators but parsed as assignment/filters
 20421     '=':true,
 20943     '=':true,
 20422     '|':true
 20944     '|':true
 20423 });
 20945 });
 20424 /* jshint bitwise: true */
       
 20425 var ESCAPE = {"n":"\n", "f":"\f", "r":"\r", "t":"\t", "v":"\v", "'":"'", '"':'"'};
 20946 var ESCAPE = {"n":"\n", "f":"\f", "r":"\r", "t":"\t", "v":"\v", "'":"'", '"':'"'};
 20426 
 20947 
 20427 
 20948 
 20428 /////////////////////////////////////////
 20949 /////////////////////////////////////////
 20429 
 20950 
 20430 
 20951 
 20431 /**
 20952 /**
 20432  * @constructor
 20953  * @constructor
 20433  */
 20954  */
 20434 var Lexer = function (options) {
 20955 var Lexer = function(options) {
 20435   this.options = options;
 20956   this.options = options;
 20436 };
 20957 };
 20437 
 20958 
 20438 Lexer.prototype = {
 20959 Lexer.prototype = {
 20439   constructor: Lexer,
 20960   constructor: Lexer,
 20440 
 20961 
 20441   lex: function (text) {
 20962   lex: function(text) {
 20442     this.text = text;
 20963     this.text = text;
 20443     this.index = 0;
 20964     this.index = 0;
 20444     this.ch = undefined;
       
 20445     this.tokens = [];
 20965     this.tokens = [];
 20446 
 20966 
 20447     while (this.index < this.text.length) {
 20967     while (this.index < this.text.length) {
 20448       this.ch = this.text.charAt(this.index);
 20968       var ch = this.text.charAt(this.index);
 20449       if (this.is('"\'')) {
 20969       if (ch === '"' || ch === "'") {
 20450         this.readString(this.ch);
 20970         this.readString(ch);
 20451       } else if (this.isNumber(this.ch) || this.is('.') && this.isNumber(this.peek())) {
 20971       } else if (this.isNumber(ch) || ch === '.' && this.isNumber(this.peek())) {
 20452         this.readNumber();
 20972         this.readNumber();
 20453       } else if (this.isIdent(this.ch)) {
 20973       } else if (this.isIdent(ch)) {
 20454         this.readIdent();
 20974         this.readIdent();
 20455       } else if (this.is('(){}[].,;:?')) {
 20975       } else if (this.is(ch, '(){}[].,;:?')) {
 20456         this.tokens.push({
 20976         this.tokens.push({index: this.index, text: ch});
 20457           index: this.index,
       
 20458           text: this.ch
       
 20459         });
       
 20460         this.index++;
 20977         this.index++;
 20461       } else if (this.isWhitespace(this.ch)) {
 20978       } else if (this.isWhitespace(ch)) {
 20462         this.index++;
 20979         this.index++;
 20463       } else {
 20980       } else {
 20464         var ch2 = this.ch + this.peek();
 20981         var ch2 = ch + this.peek();
 20465         var ch3 = ch2 + this.peek(2);
 20982         var ch3 = ch2 + this.peek(2);
 20466         var fn = OPERATORS[this.ch];
 20983         var op1 = OPERATORS[ch];
 20467         var fn2 = OPERATORS[ch2];
 20984         var op2 = OPERATORS[ch2];
 20468         var fn3 = OPERATORS[ch3];
 20985         var op3 = OPERATORS[ch3];
 20469         if (fn3) {
 20986         if (op1 || op2 || op3) {
 20470           this.tokens.push({index: this.index, text: ch3, fn: fn3});
 20987           var token = op3 ? ch3 : (op2 ? ch2 : ch);
 20471           this.index += 3;
 20988           this.tokens.push({index: this.index, text: token, operator: true});
 20472         } else if (fn2) {
 20989           this.index += token.length;
 20473           this.tokens.push({index: this.index, text: ch2, fn: fn2});
       
 20474           this.index += 2;
       
 20475         } else if (fn) {
       
 20476           this.tokens.push({
       
 20477             index: this.index,
       
 20478             text: this.ch,
       
 20479             fn: fn
       
 20480           });
       
 20481           this.index += 1;
       
 20482         } else {
 20990         } else {
 20483           this.throwError('Unexpected next character ', this.index, this.index + 1);
 20991           this.throwError('Unexpected next character ', this.index, this.index + 1);
 20484         }
 20992         }
 20485       }
 20993       }
 20486     }
 20994     }
 20487     return this.tokens;
 20995     return this.tokens;
 20488   },
 20996   },
 20489 
 20997 
 20490   is: function(chars) {
 20998   is: function(ch, chars) {
 20491     return chars.indexOf(this.ch) !== -1;
 20999     return chars.indexOf(ch) !== -1;
 20492   },
 21000   },
 20493 
 21001 
 20494   peek: function(i) {
 21002   peek: function(i) {
 20495     var num = i || 1;
 21003     var num = i || 1;
 20496     return (this.index + num < this.text.length) ? this.text.charAt(this.index + num) : false;
 21004     return (this.index + num < this.text.length) ? this.text.charAt(this.index + num) : false;
 20497   },
 21005   },
 20498 
 21006 
 20499   isNumber: function(ch) {
 21007   isNumber: function(ch) {
 20500     return ('0' <= ch && ch <= '9');
 21008     return ('0' <= ch && ch <= '9') && typeof ch === "string";
 20501   },
 21009   },
 20502 
 21010 
 20503   isWhitespace: function(ch) {
 21011   isWhitespace: function(ch) {
 20504     // IE treats non-breaking space as \u00A0
 21012     // IE treats non-breaking space as \u00A0
 20505     return (ch === ' ' || ch === '\r' || ch === '\t' ||
 21013     return (ch === ' ' || ch === '\r' || ch === '\t' ||
 20548           break;
 21056           break;
 20549         }
 21057         }
 20550       }
 21058       }
 20551       this.index++;
 21059       this.index++;
 20552     }
 21060     }
 20553     number = 1 * number;
       
 20554     this.tokens.push({
 21061     this.tokens.push({
 20555       index: start,
 21062       index: start,
 20556       text: number,
 21063       text: number,
 20557       constant: true,
 21064       constant: true,
 20558       fn: function() { return number; }
 21065       value: Number(number)
 20559     });
 21066     });
 20560   },
 21067   },
 20561 
 21068 
 20562   readIdent: function() {
 21069   readIdent: function() {
 20563     var expression = this.text;
       
 20564 
       
 20565     var ident = '';
       
 20566     var start = this.index;
 21070     var start = this.index;
 20567 
       
 20568     var lastDot, peekIndex, methodName, ch;
       
 20569 
       
 20570     while (this.index < this.text.length) {
 21071     while (this.index < this.text.length) {
 20571       ch = this.text.charAt(this.index);
 21072       var ch = this.text.charAt(this.index);
 20572       if (ch === '.' || this.isIdent(ch) || this.isNumber(ch)) {
 21073       if (!(this.isIdent(ch) || this.isNumber(ch))) {
 20573         if (ch === '.') lastDot = this.index;
       
 20574         ident += ch;
       
 20575       } else {
       
 20576         break;
 21074         break;
 20577       }
 21075       }
 20578       this.index++;
 21076       this.index++;
 20579     }
 21077     }
 20580 
       
 20581     //check if the identifier ends with . and if so move back one char
       
 20582     if (lastDot && ident[ident.length - 1] === '.') {
       
 20583       this.index--;
       
 20584       ident = ident.slice(0, -1);
       
 20585       lastDot = ident.lastIndexOf('.');
       
 20586       if (lastDot === -1) {
       
 20587         lastDot = undefined;
       
 20588       }
       
 20589     }
       
 20590 
       
 20591     //check if this is not a method invocation and if it is back out to last dot
       
 20592     if (lastDot) {
       
 20593       peekIndex = this.index;
       
 20594       while (peekIndex < this.text.length) {
       
 20595         ch = this.text.charAt(peekIndex);
       
 20596         if (ch === '(') {
       
 20597           methodName = ident.substr(lastDot - start + 1);
       
 20598           ident = ident.substr(0, lastDot - start);
       
 20599           this.index = peekIndex;
       
 20600           break;
       
 20601         }
       
 20602         if (this.isWhitespace(ch)) {
       
 20603           peekIndex++;
       
 20604         } else {
       
 20605           break;
       
 20606         }
       
 20607       }
       
 20608     }
       
 20609 
       
 20610     this.tokens.push({
 21078     this.tokens.push({
 20611       index: start,
 21079       index: start,
 20612       text: ident,
 21080       text: this.text.slice(start, this.index),
 20613       fn: CONSTANTS[ident] || getterFn(ident, this.options, expression)
 21081       identifier: true
 20614     });
 21082     });
 20615 
       
 20616     if (methodName) {
       
 20617       this.tokens.push({
       
 20618         index: lastDot,
       
 20619         text: '.'
       
 20620       });
       
 20621       this.tokens.push({
       
 20622         index: lastDot + 1,
       
 20623         text: methodName
       
 20624       });
       
 20625     }
       
 20626   },
 21083   },
 20627 
 21084 
 20628   readString: function(quote) {
 21085   readString: function(quote) {
 20629     var start = this.index;
 21086     var start = this.index;
 20630     this.index++;
 21087     this.index++;
 20651       } else if (ch === quote) {
 21108       } else if (ch === quote) {
 20652         this.index++;
 21109         this.index++;
 20653         this.tokens.push({
 21110         this.tokens.push({
 20654           index: start,
 21111           index: start,
 20655           text: rawString,
 21112           text: rawString,
 20656           string: string,
       
 20657           constant: true,
 21113           constant: true,
 20658           fn: function() { return string; }
 21114           value: string
 20659         });
 21115         });
 20660         return;
 21116         return;
 20661       } else {
 21117       } else {
 20662         string += ch;
 21118         string += ch;
 20663       }
 21119       }
 20673 }
 21129 }
 20674 
 21130 
 20675 /**
 21131 /**
 20676  * @constructor
 21132  * @constructor
 20677  */
 21133  */
 20678 var Parser = function (lexer, $filter, options) {
 21134 var Parser = function(lexer, $filter, options) {
 20679   this.lexer = lexer;
 21135   this.lexer = lexer;
 20680   this.$filter = $filter;
 21136   this.$filter = $filter;
 20681   this.options = options;
 21137   this.options = options;
 20682 };
 21138 };
 20683 
 21139 
 20684 Parser.ZERO = extend(function () {
 21140 Parser.ZERO = extend(function() {
 20685   return 0;
 21141   return 0;
 20686 }, {
 21142 }, {
 20687   sharedGetter: true,
 21143   sharedGetter: true,
 20688   constant: true
 21144   constant: true
 20689 });
 21145 });
 20690 
 21146 
 20691 Parser.prototype = {
 21147 Parser.prototype = {
 20692   constructor: Parser,
 21148   constructor: Parser,
 20693 
 21149 
 20694   parse: function (text) {
 21150   parse: function(text) {
 20695     this.text = text;
 21151     this.text = text;
 20696     this.tokens = this.lexer.lex(text);
 21152     this.tokens = this.lexer.lex(text);
 20697 
 21153 
 20698     var value = this.statements();
 21154     var value = this.statements();
 20699 
 21155 
 20705     value.constant = !!value.constant;
 21161     value.constant = !!value.constant;
 20706 
 21162 
 20707     return value;
 21163     return value;
 20708   },
 21164   },
 20709 
 21165 
 20710   primary: function () {
 21166   primary: function() {
 20711     var primary;
 21167     var primary;
 20712     if (this.expect('(')) {
 21168     if (this.expect('(')) {
 20713       primary = this.filterChain();
 21169       primary = this.filterChain();
 20714       this.consume(')');
 21170       this.consume(')');
 20715     } else if (this.expect('[')) {
 21171     } else if (this.expect('[')) {
 20716       primary = this.arrayDeclaration();
 21172       primary = this.arrayDeclaration();
 20717     } else if (this.expect('{')) {
 21173     } else if (this.expect('{')) {
 20718       primary = this.object();
 21174       primary = this.object();
       
 21175     } else if (this.peek().identifier && this.peek().text in CONSTANTS) {
       
 21176       primary = CONSTANTS[this.consume().text];
       
 21177     } else if (this.peek().identifier) {
       
 21178       primary = this.identifier();
       
 21179     } else if (this.peek().constant) {
       
 21180       primary = this.constant();
 20719     } else {
 21181     } else {
 20720       var token = this.expect();
 21182       this.throwError('not a primary expression', this.peek());
 20721       primary = token.fn;
       
 20722       if (!primary) {
       
 20723         this.throwError('not a primary expression', token);
       
 20724       }
       
 20725       if (token.constant) {
       
 20726         primary.constant = true;
       
 20727         primary.literal = true;
       
 20728       }
       
 20729     }
 21183     }
 20730 
 21184 
 20731     var next, context;
 21185     var next, context;
 20732     while ((next = this.expect('(', '[', '.'))) {
 21186     while ((next = this.expect('(', '[', '.'))) {
 20733       if (next.text === '(') {
 21187       if (next.text === '(') {
 20757       throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text);
 21211       throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text);
 20758     return this.tokens[0];
 21212     return this.tokens[0];
 20759   },
 21213   },
 20760 
 21214 
 20761   peek: function(e1, e2, e3, e4) {
 21215   peek: function(e1, e2, e3, e4) {
 20762     if (this.tokens.length > 0) {
 21216     return this.peekAhead(0, e1, e2, e3, e4);
 20763       var token = this.tokens[0];
 21217   },
       
 21218   peekAhead: function(i, e1, e2, e3, e4) {
       
 21219     if (this.tokens.length > i) {
       
 21220       var token = this.tokens[i];
 20764       var t = token.text;
 21221       var t = token.text;
 20765       if (t === e1 || t === e2 || t === e3 || t === e4 ||
 21222       if (t === e1 || t === e2 || t === e3 || t === e4 ||
 20766           (!e1 && !e2 && !e3 && !e4)) {
 21223           (!e1 && !e2 && !e3 && !e4)) {
 20767         return token;
 21224         return token;
 20768       }
 21225       }
 20769     }
 21226     }
 20770     return false;
 21227     return false;
 20771   },
 21228   },
 20772 
 21229 
 20773   expect: function(e1, e2, e3, e4){
 21230   expect: function(e1, e2, e3, e4) {
 20774     var token = this.peek(e1, e2, e3, e4);
 21231     var token = this.peek(e1, e2, e3, e4);
 20775     if (token) {
 21232     if (token) {
 20776       this.tokens.shift();
 21233       this.tokens.shift();
 20777       return token;
 21234       return token;
 20778     }
 21235     }
 20779     return false;
 21236     return false;
 20780   },
 21237   },
 20781 
 21238 
 20782   consume: function(e1){
 21239   consume: function(e1) {
 20783     if (!this.expect(e1)) {
 21240     if (this.tokens.length === 0) {
       
 21241       throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text);
       
 21242     }
       
 21243 
       
 21244     var token = this.expect(e1);
       
 21245     if (!token) {
 20784       this.throwError('is unexpected, expecting [' + e1 + ']', this.peek());
 21246       this.throwError('is unexpected, expecting [' + e1 + ']', this.peek());
 20785     }
 21247     }
       
 21248     return token;
 20786   },
 21249   },
 20787 
 21250 
 20788   unaryFn: function(fn, right) {
 21251   unaryFn: function(op, right) {
       
 21252     var fn = OPERATORS[op];
 20789     return extend(function $parseUnaryFn(self, locals) {
 21253     return extend(function $parseUnaryFn(self, locals) {
 20790       return fn(self, locals, right);
 21254       return fn(self, locals, right);
 20791     }, {
 21255     }, {
 20792       constant:right.constant,
 21256       constant:right.constant,
 20793       inputs: [right]
 21257       inputs: [right]
 20794     });
 21258     });
 20795   },
 21259   },
 20796 
 21260 
 20797   binaryFn: function(left, fn, right, isBranching) {
 21261   binaryFn: function(left, op, right, isBranching) {
       
 21262     var fn = OPERATORS[op];
 20798     return extend(function $parseBinaryFn(self, locals) {
 21263     return extend(function $parseBinaryFn(self, locals) {
 20799       return fn(self, locals, left, right);
 21264       return fn(self, locals, left, right);
 20800     }, {
 21265     }, {
 20801       constant: left.constant && right.constant,
 21266       constant: left.constant && right.constant,
 20802       inputs: !isBranching && [left, right]
 21267       inputs: !isBranching && [left, right]
       
 21268     });
       
 21269   },
       
 21270 
       
 21271   identifier: function() {
       
 21272     var id = this.consume().text;
       
 21273 
       
 21274     //Continue reading each `.identifier` unless it is a method invocation
       
 21275     while (this.peek('.') && this.peekAhead(1).identifier && !this.peekAhead(2, '(')) {
       
 21276       id += this.consume().text + this.consume().text;
       
 21277     }
       
 21278 
       
 21279     return getterFn(id, this.options, this.text);
       
 21280   },
       
 21281 
       
 21282   constant: function() {
       
 21283     var value = this.consume().value;
       
 21284 
       
 21285     return extend(function $parseConstant() {
       
 21286       return value;
       
 21287     }, {
       
 21288       constant: true,
       
 21289       literal: true
 20803     });
 21290     });
 20804   },
 21291   },
 20805 
 21292 
 20806   statements: function() {
 21293   statements: function() {
 20807     var statements = [];
 21294     var statements = [];
 20832     }
 21319     }
 20833     return left;
 21320     return left;
 20834   },
 21321   },
 20835 
 21322 
 20836   filter: function(inputFn) {
 21323   filter: function(inputFn) {
 20837     var token = this.expect();
 21324     var fn = this.$filter(this.consume().text);
 20838     var fn = this.$filter(token.text);
       
 20839     var argsFn;
 21325     var argsFn;
 20840     var args;
 21326     var args;
 20841 
 21327 
 20842     if (this.peek(':')) {
 21328     if (this.peek(':')) {
 20843       argsFn = [];
 21329       argsFn = [];
 20896     var left = this.logicalOR();
 21382     var left = this.logicalOR();
 20897     var middle;
 21383     var middle;
 20898     var token;
 21384     var token;
 20899     if ((token = this.expect('?'))) {
 21385     if ((token = this.expect('?'))) {
 20900       middle = this.assignment();
 21386       middle = this.assignment();
 20901       if ((token = this.expect(':'))) {
 21387       if (this.consume(':')) {
 20902         var right = this.assignment();
 21388         var right = this.assignment();
 20903 
 21389 
 20904         return extend(function $parseTernary(self, locals){
 21390         return extend(function $parseTernary(self, locals) {
 20905           return left(self, locals) ? middle(self, locals) : right(self, locals);
 21391           return left(self, locals) ? middle(self, locals) : right(self, locals);
 20906         }, {
 21392         }, {
 20907           constant: left.constant && middle.constant && right.constant
 21393           constant: left.constant && middle.constant && right.constant
 20908         });
 21394         });
 20909 
       
 20910       } else {
       
 20911         this.throwError('expected :', token);
       
 20912       }
 21395       }
 20913     }
 21396     }
 20914 
 21397 
 20915     return left;
 21398     return left;
 20916   },
 21399   },
 20917 
 21400 
 20918   logicalOR: function() {
 21401   logicalOR: function() {
 20919     var left = this.logicalAND();
 21402     var left = this.logicalAND();
 20920     var token;
 21403     var token;
 20921     while ((token = this.expect('||'))) {
 21404     while ((token = this.expect('||'))) {
 20922       left = this.binaryFn(left, token.fn, this.logicalAND(), true);
 21405       left = this.binaryFn(left, token.text, this.logicalAND(), true);
 20923     }
 21406     }
 20924     return left;
 21407     return left;
 20925   },
 21408   },
 20926 
 21409 
 20927   logicalAND: function() {
 21410   logicalAND: function() {
 20928     var left = this.equality();
 21411     var left = this.equality();
 20929     var token;
 21412     var token;
 20930     if ((token = this.expect('&&'))) {
 21413     while ((token = this.expect('&&'))) {
 20931       left = this.binaryFn(left, token.fn, this.logicalAND(), true);
 21414       left = this.binaryFn(left, token.text, this.equality(), true);
 20932     }
 21415     }
 20933     return left;
 21416     return left;
 20934   },
 21417   },
 20935 
 21418 
 20936   equality: function() {
 21419   equality: function() {
 20937     var left = this.relational();
 21420     var left = this.relational();
 20938     var token;
 21421     var token;
 20939     if ((token = this.expect('==','!=','===','!=='))) {
 21422     while ((token = this.expect('==','!=','===','!=='))) {
 20940       left = this.binaryFn(left, token.fn, this.equality());
 21423       left = this.binaryFn(left, token.text, this.relational());
 20941     }
 21424     }
 20942     return left;
 21425     return left;
 20943   },
 21426   },
 20944 
 21427 
 20945   relational: function() {
 21428   relational: function() {
 20946     var left = this.additive();
 21429     var left = this.additive();
 20947     var token;
 21430     var token;
 20948     if ((token = this.expect('<', '>', '<=', '>='))) {
 21431     while ((token = this.expect('<', '>', '<=', '>='))) {
 20949       left = this.binaryFn(left, token.fn, this.relational());
 21432       left = this.binaryFn(left, token.text, this.additive());
 20950     }
 21433     }
 20951     return left;
 21434     return left;
 20952   },
 21435   },
 20953 
 21436 
 20954   additive: function() {
 21437   additive: function() {
 20955     var left = this.multiplicative();
 21438     var left = this.multiplicative();
 20956     var token;
 21439     var token;
 20957     while ((token = this.expect('+','-'))) {
 21440     while ((token = this.expect('+','-'))) {
 20958       left = this.binaryFn(left, token.fn, this.multiplicative());
 21441       left = this.binaryFn(left, token.text, this.multiplicative());
 20959     }
 21442     }
 20960     return left;
 21443     return left;
 20961   },
 21444   },
 20962 
 21445 
 20963   multiplicative: function() {
 21446   multiplicative: function() {
 20964     var left = this.unary();
 21447     var left = this.unary();
 20965     var token;
 21448     var token;
 20966     while ((token = this.expect('*','/','%'))) {
 21449     while ((token = this.expect('*','/','%'))) {
 20967       left = this.binaryFn(left, token.fn, this.unary());
 21450       left = this.binaryFn(left, token.text, this.unary());
 20968     }
 21451     }
 20969     return left;
 21452     return left;
 20970   },
 21453   },
 20971 
 21454 
 20972   unary: function() {
 21455   unary: function() {
 20973     var token;
 21456     var token;
 20974     if (this.expect('+')) {
 21457     if (this.expect('+')) {
 20975       return this.primary();
 21458       return this.primary();
 20976     } else if ((token = this.expect('-'))) {
 21459     } else if ((token = this.expect('-'))) {
 20977       return this.binaryFn(Parser.ZERO, token.fn, this.unary());
 21460       return this.binaryFn(Parser.ZERO, token.text, this.unary());
 20978     } else if ((token = this.expect('!'))) {
 21461     } else if ((token = this.expect('!'))) {
 20979       return this.unaryFn(token.fn, this.unary());
 21462       return this.unaryFn(token.text, this.unary());
 20980     } else {
 21463     } else {
 20981       return this.primary();
 21464       return this.primary();
 20982     }
 21465     }
 20983   },
 21466   },
 20984 
 21467 
 20985   fieldAccess: function(object) {
 21468   fieldAccess: function(object) {
 20986     var expression = this.text;
 21469     var getter = this.identifier();
 20987     var field = this.expect().text;
       
 20988     var getter = getterFn(field, this.options, expression);
       
 20989 
 21470 
 20990     return extend(function $parseFieldAccess(scope, locals, self) {
 21471     return extend(function $parseFieldAccess(scope, locals, self) {
 20991       return getter(self || object(scope, locals));
 21472       var o = self || object(scope, locals);
       
 21473       return (o == null) ? undefined : getter(o);
 20992     }, {
 21474     }, {
 20993       assign: function(scope, value, locals) {
 21475       assign: function(scope, value, locals) {
 20994         var o = object(scope, locals);
 21476         var o = object(scope, locals);
 20995         if (!o) object.assign(scope, o = {});
 21477         if (!o) object.assign(scope, o = {});
 20996         return setter(o, field, value, expression);
 21478         return getter.assign(o, value);
 20997       }
 21479       }
 20998     });
 21480     });
 20999   },
 21481   },
 21000 
 21482 
 21001   objectIndex: function(obj) {
 21483   objectIndex: function(obj) {
 21036     var expressionText = this.text;
 21518     var expressionText = this.text;
 21037     // we can safely reuse the array across invocations
 21519     // we can safely reuse the array across invocations
 21038     var args = argsFn.length ? [] : null;
 21520     var args = argsFn.length ? [] : null;
 21039 
 21521 
 21040     return function $parseFunctionCall(scope, locals) {
 21522     return function $parseFunctionCall(scope, locals) {
 21041       var context = contextGetter ? contextGetter(scope, locals) : scope;
 21523       var context = contextGetter ? contextGetter(scope, locals) : isDefined(contextGetter) ? undefined : scope;
 21042       var fn = fnGetter(scope, locals, context) || noop;
 21524       var fn = fnGetter(scope, locals, context) || noop;
 21043 
 21525 
 21044       if (args) {
 21526       if (args) {
 21045         var i = argsFn.length;
 21527         var i = argsFn.length;
 21046         while (i--) {
 21528         while (i--) {
 21049       }
 21531       }
 21050 
 21532 
 21051       ensureSafeObject(context, expressionText);
 21533       ensureSafeObject(context, expressionText);
 21052       ensureSafeFunction(fn, expressionText);
 21534       ensureSafeFunction(fn, expressionText);
 21053 
 21535 
 21054       // IE stupidity! (IE doesn't have apply for some native functions)
 21536       // IE doesn't have apply for some native functions
 21055       var v = fn.apply
 21537       var v = fn.apply
 21056             ? fn.apply(context, args)
 21538             ? fn.apply(context, args)
 21057             : fn(args[0], args[1], args[2], args[3], args[4]);
 21539             : fn(args[0], args[1], args[2], args[3], args[4]);
 21058 
 21540 
 21059       return ensureSafeObject(v, expressionText);
 21541       return ensureSafeObject(v, expressionText);
 21060     };
 21542       };
 21061   },
 21543   },
 21062 
 21544 
 21063   // This is used with json array declaration
 21545   // This is used with json array declaration
 21064   arrayDeclaration: function () {
 21546   arrayDeclaration: function() {
 21065     var elementFns = [];
 21547     var elementFns = [];
 21066     if (this.peekToken().text !== ']') {
 21548     if (this.peekToken().text !== ']') {
 21067       do {
 21549       do {
 21068         if (this.peek(']')) {
 21550         if (this.peek(']')) {
 21069           // Support trailing commas per ES5.1.
 21551           // Support trailing commas per ES5.1.
 21070           break;
 21552           break;
 21071         }
 21553         }
 21072         var elementFn = this.expression();
 21554         elementFns.push(this.expression());
 21073         elementFns.push(elementFn);
       
 21074       } while (this.expect(','));
 21555       } while (this.expect(','));
 21075     }
 21556     }
 21076     this.consume(']');
 21557     this.consume(']');
 21077 
 21558 
 21078     return extend(function $parseArrayLiteral(self, locals) {
 21559     return extend(function $parseArrayLiteral(self, locals) {
 21086       constant: elementFns.every(isConstant),
 21567       constant: elementFns.every(isConstant),
 21087       inputs: elementFns
 21568       inputs: elementFns
 21088     });
 21569     });
 21089   },
 21570   },
 21090 
 21571 
 21091   object: function () {
 21572   object: function() {
 21092     var keys = [], valueFns = [];
 21573     var keys = [], valueFns = [];
 21093     if (this.peekToken().text !== '}') {
 21574     if (this.peekToken().text !== '}') {
 21094       do {
 21575       do {
 21095         if (this.peek('}')) {
 21576         if (this.peek('}')) {
 21096           // Support trailing commas per ES5.1.
 21577           // Support trailing commas per ES5.1.
 21097           break;
 21578           break;
 21098         }
 21579         }
 21099         var token = this.expect();
 21580         var token = this.consume();
 21100         keys.push(token.string || token.text);
 21581         if (token.constant) {
       
 21582           keys.push(token.value);
       
 21583         } else if (token.identifier) {
       
 21584           keys.push(token.text);
       
 21585         } else {
       
 21586           this.throwError("invalid key", token);
       
 21587         }
 21101         this.consume(':');
 21588         this.consume(':');
 21102         var value = this.expression();
 21589         valueFns.push(this.expression());
 21103         valueFns.push(value);
       
 21104       } while (this.expect(','));
 21590       } while (this.expect(','));
 21105     }
 21591     }
 21106     this.consume('}');
 21592     this.consume('}');
 21107 
 21593 
 21108     return extend(function $parseObjectLiteral(self, locals) {
 21594     return extend(function $parseObjectLiteral(self, locals) {
 21141   ensureSafeObject(obj[key], fullExp);
 21627   ensureSafeObject(obj[key], fullExp);
 21142   obj[key] = setValue;
 21628   obj[key] = setValue;
 21143   return setValue;
 21629   return setValue;
 21144 }
 21630 }
 21145 
 21631 
 21146 var getterFnCache = createMap();
 21632 var getterFnCacheDefault = createMap();
       
 21633 var getterFnCacheExpensive = createMap();
       
 21634 
       
 21635 function isPossiblyDangerousMemberName(name) {
       
 21636   return name == 'constructor';
       
 21637 }
 21147 
 21638 
 21148 /**
 21639 /**
 21149  * Implementation of the "Black Hole" variant from:
 21640  * Implementation of the "Black Hole" variant from:
 21150  * - http://jsperf.com/angularjs-parse-getter/4
 21641  * - http://jsperf.com/angularjs-parse-getter/4
 21151  * - http://jsperf.com/path-evaluation-simplified/7
 21642  * - http://jsperf.com/path-evaluation-simplified/7
 21152  */
 21643  */
 21153 function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp) {
 21644 function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, expensiveChecks) {
 21154   ensureSafeMemberName(key0, fullExp);
 21645   ensureSafeMemberName(key0, fullExp);
 21155   ensureSafeMemberName(key1, fullExp);
 21646   ensureSafeMemberName(key1, fullExp);
 21156   ensureSafeMemberName(key2, fullExp);
 21647   ensureSafeMemberName(key2, fullExp);
 21157   ensureSafeMemberName(key3, fullExp);
 21648   ensureSafeMemberName(key3, fullExp);
 21158   ensureSafeMemberName(key4, fullExp);
 21649   ensureSafeMemberName(key4, fullExp);
       
 21650   var eso = function(o) {
       
 21651     return ensureSafeObject(o, fullExp);
       
 21652   };
       
 21653   var eso0 = (expensiveChecks || isPossiblyDangerousMemberName(key0)) ? eso : identity;
       
 21654   var eso1 = (expensiveChecks || isPossiblyDangerousMemberName(key1)) ? eso : identity;
       
 21655   var eso2 = (expensiveChecks || isPossiblyDangerousMemberName(key2)) ? eso : identity;
       
 21656   var eso3 = (expensiveChecks || isPossiblyDangerousMemberName(key3)) ? eso : identity;
       
 21657   var eso4 = (expensiveChecks || isPossiblyDangerousMemberName(key4)) ? eso : identity;
 21159 
 21658 
 21160   return function cspSafeGetter(scope, locals) {
 21659   return function cspSafeGetter(scope, locals) {
 21161     var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope;
 21660     var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope;
 21162 
 21661 
 21163     if (pathVal == null) return pathVal;
 21662     if (pathVal == null) return pathVal;
 21164     pathVal = pathVal[key0];
 21663     pathVal = eso0(pathVal[key0]);
 21165 
 21664 
 21166     if (!key1) return pathVal;
 21665     if (!key1) return pathVal;
 21167     if (pathVal == null) return undefined;
 21666     if (pathVal == null) return undefined;
 21168     pathVal = pathVal[key1];
 21667     pathVal = eso1(pathVal[key1]);
 21169 
 21668 
 21170     if (!key2) return pathVal;
 21669     if (!key2) return pathVal;
 21171     if (pathVal == null) return undefined;
 21670     if (pathVal == null) return undefined;
 21172     pathVal = pathVal[key2];
 21671     pathVal = eso2(pathVal[key2]);
 21173 
 21672 
 21174     if (!key3) return pathVal;
 21673     if (!key3) return pathVal;
 21175     if (pathVal == null) return undefined;
 21674     if (pathVal == null) return undefined;
 21176     pathVal = pathVal[key3];
 21675     pathVal = eso3(pathVal[key3]);
 21177 
 21676 
 21178     if (!key4) return pathVal;
 21677     if (!key4) return pathVal;
 21179     if (pathVal == null) return undefined;
 21678     if (pathVal == null) return undefined;
 21180     pathVal = pathVal[key4];
 21679     pathVal = eso4(pathVal[key4]);
 21181 
 21680 
 21182     return pathVal;
 21681     return pathVal;
 21183   };
 21682   };
 21184 }
 21683 }
 21185 
 21684 
       
 21685 function getterFnWithEnsureSafeObject(fn, fullExpression) {
       
 21686   return function(s, l) {
       
 21687     return fn(s, l, ensureSafeObject, fullExpression);
       
 21688   };
       
 21689 }
       
 21690 
 21186 function getterFn(path, options, fullExp) {
 21691 function getterFn(path, options, fullExp) {
       
 21692   var expensiveChecks = options.expensiveChecks;
       
 21693   var getterFnCache = (expensiveChecks ? getterFnCacheExpensive : getterFnCacheDefault);
 21187   var fn = getterFnCache[path];
 21694   var fn = getterFnCache[path];
 21188 
       
 21189   if (fn) return fn;
 21695   if (fn) return fn;
       
 21696 
 21190 
 21697 
 21191   var pathKeys = path.split('.'),
 21698   var pathKeys = path.split('.'),
 21192       pathKeysLength = pathKeys.length;
 21699       pathKeysLength = pathKeys.length;
 21193 
 21700 
 21194   // http://jsperf.com/angularjs-parse-getter/6
 21701   // http://jsperf.com/angularjs-parse-getter/6
 21195   if (options.csp) {
 21702   if (options.csp) {
 21196     if (pathKeysLength < 6) {
 21703     if (pathKeysLength < 6) {
 21197       fn = cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4], fullExp);
 21704       fn = cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4], fullExp, expensiveChecks);
 21198     } else {
 21705     } else {
 21199       fn = function cspSafeGetter(scope, locals) {
 21706       fn = function cspSafeGetter(scope, locals) {
 21200         var i = 0, val;
 21707         var i = 0, val;
 21201         do {
 21708         do {
 21202           val = cspSafeGetterFn(pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++],
 21709           val = cspSafeGetterFn(pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++],
 21203                                 pathKeys[i++], fullExp)(scope, locals);
 21710                                 pathKeys[i++], fullExp, expensiveChecks)(scope, locals);
 21204 
 21711 
 21205           locals = undefined; // clear after first iteration
 21712           locals = undefined; // clear after first iteration
 21206           scope = val;
 21713           scope = val;
 21207         } while (i < pathKeysLength);
 21714         } while (i < pathKeysLength);
 21208         return val;
 21715         return val;
 21209       };
 21716       };
 21210     }
 21717     }
 21211   } else {
 21718   } else {
 21212     var code = '';
 21719     var code = '';
       
 21720     if (expensiveChecks) {
       
 21721       code += 's = eso(s, fe);\nl = eso(l, fe);\n';
       
 21722     }
       
 21723     var needsEnsureSafeObject = expensiveChecks;
 21213     forEach(pathKeys, function(key, index) {
 21724     forEach(pathKeys, function(key, index) {
 21214       ensureSafeMemberName(key, fullExp);
 21725       ensureSafeMemberName(key, fullExp);
 21215       code += 'if(s == null) return undefined;\n' +
 21726       var lookupJs = (index
 21216               's='+ (index
       
 21217                       // we simply dereference 's' on any .dot notation
 21727                       // we simply dereference 's' on any .dot notation
 21218                       ? 's'
 21728                       ? 's'
 21219                       // but if we are first then we check locals first, and if so read it first
 21729                       // but if we are first then we check locals first, and if so read it first
 21220                       : '((l&&l.hasOwnProperty("' + key + '"))?l:s)') + '.' + key + ';\n';
 21730                       : '((l&&l.hasOwnProperty("' + key + '"))?l:s)') + '.' + key;
       
 21731       if (expensiveChecks || isPossiblyDangerousMemberName(key)) {
       
 21732         lookupJs = 'eso(' + lookupJs + ', fe)';
       
 21733         needsEnsureSafeObject = true;
       
 21734       }
       
 21735       code += 'if(s == null) return undefined;\n' +
       
 21736               's=' + lookupJs + ';\n';
 21221     });
 21737     });
 21222     code += 'return s;';
 21738     code += 'return s;';
 21223 
 21739 
 21224     /* jshint -W054 */
 21740     /* jshint -W054 */
 21225     var evaledFnGetter = new Function('s', 'l', code); // s=scope, l=locals
 21741     var evaledFnGetter = new Function('s', 'l', 'eso', 'fe', code); // s=scope, l=locals, eso=ensureSafeObject
 21226     /* jshint +W054 */
 21742     /* jshint +W054 */
 21227     evaledFnGetter.toString = valueFn(code);
 21743     evaledFnGetter.toString = valueFn(code);
 21228 
 21744     if (needsEnsureSafeObject) {
       
 21745       evaledFnGetter = getterFnWithEnsureSafeObject(evaledFnGetter, fullExp);
       
 21746     }
 21229     fn = evaledFnGetter;
 21747     fn = evaledFnGetter;
 21230   }
 21748   }
 21231 
 21749 
 21232   fn.sharedGetter = true;
 21750   fn.sharedGetter = true;
 21233   fn.assign = function(self, value) {
 21751   fn.assign = function(self, value) {
 21235   };
 21753   };
 21236   getterFnCache[path] = fn;
 21754   getterFnCache[path] = fn;
 21237   return fn;
 21755   return fn;
 21238 }
 21756 }
 21239 
 21757 
       
 21758 var objectValueOf = Object.prototype.valueOf;
       
 21759 
       
 21760 function getValueOf(value) {
       
 21761   return isFunction(value.valueOf) ? value.valueOf() : objectValueOf.call(value);
       
 21762 }
       
 21763 
 21240 ///////////////////////////////////
 21764 ///////////////////////////////////
 21241 
 21765 
 21242 /**
 21766 /**
 21243  * @ngdoc service
 21767  * @ngdoc service
 21244  * @name $parse
 21768  * @name $parse
 21287  * @description
 21811  * @description
 21288  * `$parseProvider` can be used for configuring the default behavior of the {@link ng.$parse $parse}
 21812  * `$parseProvider` can be used for configuring the default behavior of the {@link ng.$parse $parse}
 21289  *  service.
 21813  *  service.
 21290  */
 21814  */
 21291 function $ParseProvider() {
 21815 function $ParseProvider() {
 21292   var cache = createMap();
 21816   var cacheDefault = createMap();
 21293 
 21817   var cacheExpensive = createMap();
 21294   var $parseOptions = {
 21818 
 21295     csp: false
       
 21296   };
       
 21297 
 21819 
 21298 
 21820 
 21299   this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {
 21821   this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {
 21300     $parseOptions.csp = $sniffer.csp;
 21822     var $parseOptions = {
       
 21823           csp: $sniffer.csp,
       
 21824           expensiveChecks: false
       
 21825         },
       
 21826         $parseOptionsExpensive = {
       
 21827           csp: $sniffer.csp,
       
 21828           expensiveChecks: true
       
 21829         };
 21301 
 21830 
 21302     function wrapSharedExpression(exp) {
 21831     function wrapSharedExpression(exp) {
 21303       var wrapped = exp;
 21832       var wrapped = exp;
 21304 
 21833 
 21305       if (exp.sharedGetter) {
 21834       if (exp.sharedGetter) {
 21312       }
 21841       }
 21313 
 21842 
 21314       return wrapped;
 21843       return wrapped;
 21315     }
 21844     }
 21316 
 21845 
 21317     return function $parse(exp, interceptorFn) {
 21846     return function $parse(exp, interceptorFn, expensiveChecks) {
 21318       var parsedExpression, oneTime, cacheKey;
 21847       var parsedExpression, oneTime, cacheKey;
 21319 
 21848 
 21320       switch (typeof exp) {
 21849       switch (typeof exp) {
 21321         case 'string':
 21850         case 'string':
 21322           cacheKey = exp = exp.trim();
 21851           cacheKey = exp = exp.trim();
 21323 
 21852 
       
 21853           var cache = (expensiveChecks ? cacheExpensive : cacheDefault);
 21324           parsedExpression = cache[cacheKey];
 21854           parsedExpression = cache[cacheKey];
 21325 
 21855 
 21326           if (!parsedExpression) {
 21856           if (!parsedExpression) {
 21327             if (exp.charAt(0) === ':' && exp.charAt(1) === ':') {
 21857             if (exp.charAt(0) === ':' && exp.charAt(1) === ':') {
 21328               oneTime = true;
 21858               oneTime = true;
 21329               exp = exp.substring(2);
 21859               exp = exp.substring(2);
 21330             }
 21860             }
 21331 
 21861 
 21332             var lexer = new Lexer($parseOptions);
 21862             var parseOptions = expensiveChecks ? $parseOptionsExpensive : $parseOptions;
 21333             var parser = new Parser(lexer, $filter, $parseOptions);
 21863             var lexer = new Lexer(parseOptions);
       
 21864             var parser = new Parser(lexer, $filter, parseOptions);
 21334             parsedExpression = parser.parse(exp);
 21865             parsedExpression = parser.parse(exp);
 21335 
 21866 
 21336             if (parsedExpression.constant) {
 21867             if (parsedExpression.constant) {
 21337               parsedExpression.$$watchDelegate = constantWatchDelegate;
 21868               parsedExpression.$$watchDelegate = constantWatchDelegate;
 21338             } else if (oneTime) {
 21869             } else if (oneTime) {
 21381       if (typeof newValue === 'object') {
 21912       if (typeof newValue === 'object') {
 21382 
 21913 
 21383         // attempt to convert the value to a primitive type
 21914         // attempt to convert the value to a primitive type
 21384         // TODO(docs): add a note to docs that by implementing valueOf even objects and arrays can
 21915         // TODO(docs): add a note to docs that by implementing valueOf even objects and arrays can
 21385         //             be cheaply dirty-checked
 21916         //             be cheaply dirty-checked
 21386         newValue = newValue.valueOf();
 21917         newValue = getValueOf(newValue);
 21387 
 21918 
 21388         if (typeof newValue === 'object') {
 21919         if (typeof newValue === 'object') {
 21389           // objects/arrays are not supported - deep-watching them would be too expensive
 21920           // objects/arrays are not supported - deep-watching them would be too expensive
 21390           return false;
 21921           return false;
 21391         }
 21922         }
 21408         inputExpressions = inputExpressions[0];
 21939         inputExpressions = inputExpressions[0];
 21409         return scope.$watch(function expressionInputWatch(scope) {
 21940         return scope.$watch(function expressionInputWatch(scope) {
 21410           var newInputValue = inputExpressions(scope);
 21941           var newInputValue = inputExpressions(scope);
 21411           if (!expressionInputDirtyCheck(newInputValue, oldInputValue)) {
 21942           if (!expressionInputDirtyCheck(newInputValue, oldInputValue)) {
 21412             lastResult = parsedExpression(scope);
 21943             lastResult = parsedExpression(scope);
 21413             oldInputValue = newInputValue && newInputValue.valueOf();
 21944             oldInputValue = newInputValue && getValueOf(newInputValue);
 21414           }
 21945           }
 21415           return lastResult;
 21946           return lastResult;
 21416         }, listener, objectEquality);
 21947         }, listener, objectEquality);
 21417       }
 21948       }
 21418 
 21949 
 21425         var changed = false;
 21956         var changed = false;
 21426 
 21957 
 21427         for (var i = 0, ii = inputExpressions.length; i < ii; i++) {
 21958         for (var i = 0, ii = inputExpressions.length; i < ii; i++) {
 21428           var newInputValue = inputExpressions[i](scope);
 21959           var newInputValue = inputExpressions[i](scope);
 21429           if (changed || (changed = !expressionInputDirtyCheck(newInputValue, oldInputValueOfValues[i]))) {
 21960           if (changed || (changed = !expressionInputDirtyCheck(newInputValue, oldInputValueOfValues[i]))) {
 21430             oldInputValueOfValues[i] = newInputValue && newInputValue.valueOf();
 21961             oldInputValueOfValues[i] = newInputValue && getValueOf(newInputValue);
 21431           }
 21962           }
 21432         }
 21963         }
 21433 
 21964 
 21434         if (changed) {
 21965         if (changed) {
 21435           lastResult = parsedExpression(scope);
 21966           lastResult = parsedExpression(scope);
 21447         lastValue = value;
 21978         lastValue = value;
 21448         if (isFunction(listener)) {
 21979         if (isFunction(listener)) {
 21449           listener.apply(this, arguments);
 21980           listener.apply(this, arguments);
 21450         }
 21981         }
 21451         if (isDefined(value)) {
 21982         if (isDefined(value)) {
 21452           scope.$$postDigest(function () {
 21983           scope.$$postDigest(function() {
 21453             if (isDefined(lastValue)) {
 21984             if (isDefined(lastValue)) {
 21454               unwatch();
 21985               unwatch();
 21455             }
 21986             }
 21456           });
 21987           });
 21457         }
 21988         }
 21458       }, objectEquality);
 21989       }, objectEquality);
 21459     }
 21990     }
 21460 
 21991 
 21461     function oneTimeLiteralWatchDelegate(scope, listener, objectEquality, parsedExpression) {
 21992     function oneTimeLiteralWatchDelegate(scope, listener, objectEquality, parsedExpression) {
 21462       var unwatch;
 21993       var unwatch, lastValue;
 21463       return unwatch = scope.$watch(function oneTimeWatch(scope) {
 21994       return unwatch = scope.$watch(function oneTimeWatch(scope) {
 21464         return parsedExpression(scope);
 21995         return parsedExpression(scope);
 21465       }, function oneTimeListener(value, old, scope) {
 21996       }, function oneTimeListener(value, old, scope) {
       
 21997         lastValue = value;
 21466         if (isFunction(listener)) {
 21998         if (isFunction(listener)) {
 21467           listener.call(this, value, old, scope);
 21999           listener.call(this, value, old, scope);
 21468         }
 22000         }
 21469         if (isAllDefined(value)) {
 22001         if (isAllDefined(value)) {
 21470           scope.$$postDigest(function () {
 22002           scope.$$postDigest(function() {
 21471             if(isAllDefined(value)) unwatch();
 22003             if (isAllDefined(lastValue)) unwatch();
 21472           });
 22004           });
 21473         }
 22005         }
 21474       }, objectEquality);
 22006       }, objectEquality);
 21475 
 22007 
 21476       function isAllDefined(value) {
 22008       function isAllDefined(value) {
 21477         var allDefined = true;
 22009         var allDefined = true;
 21478         forEach(value, function (val) {
 22010         forEach(value, function(val) {
 21479           if (!isDefined(val)) allDefined = false;
 22011           if (!isDefined(val)) allDefined = false;
 21480         });
 22012         });
 21481         return allDefined;
 22013         return allDefined;
 21482       }
 22014       }
 21483     }
 22015     }
 21494       }, objectEquality);
 22026       }, objectEquality);
 21495     }
 22027     }
 21496 
 22028 
 21497     function addInterceptor(parsedExpression, interceptorFn) {
 22029     function addInterceptor(parsedExpression, interceptorFn) {
 21498       if (!interceptorFn) return parsedExpression;
 22030       if (!interceptorFn) return parsedExpression;
 21499 
 22031       var watchDelegate = parsedExpression.$$watchDelegate;
 21500       var fn = function interceptedExpression(scope, locals) {
 22032 
       
 22033       var regularWatch =
       
 22034           watchDelegate !== oneTimeLiteralWatchDelegate &&
       
 22035           watchDelegate !== oneTimeWatchDelegate;
       
 22036 
       
 22037       var fn = regularWatch ? function regularInterceptedExpression(scope, locals) {
       
 22038         var value = parsedExpression(scope, locals);
       
 22039         return interceptorFn(value, scope, locals);
       
 22040       } : function oneTimeInterceptedExpression(scope, locals) {
 21501         var value = parsedExpression(scope, locals);
 22041         var value = parsedExpression(scope, locals);
 21502         var result = interceptorFn(value, scope, locals);
 22042         var result = interceptorFn(value, scope, locals);
 21503         // we only return the interceptor's result if the
 22043         // we only return the interceptor's result if the
 21504         // initial value is defined (for bind-once)
 22044         // initial value is defined (for bind-once)
 21505         return isDefined(value) ? result : value;
 22045         return isDefined(value) ? result : value;
 21525  * @ngdoc service
 22065  * @ngdoc service
 21526  * @name $q
 22066  * @name $q
 21527  * @requires $rootScope
 22067  * @requires $rootScope
 21528  *
 22068  *
 21529  * @description
 22069  * @description
 21530  * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).
 22070  * A service that helps you run functions asynchronously, and use their return values (or exceptions)
       
 22071  * when they are done processing.
       
 22072  *
       
 22073  * This is an implementation of promises/deferred objects inspired by
       
 22074  * [Kris Kowal's Q](https://github.com/kriskowal/q).
 21531  *
 22075  *
 21532  * $q can be used in two fashions --- one which is more similar to Kris Kowal's Q or jQuery's Deferred
 22076  * $q can be used in two fashions --- one which is more similar to Kris Kowal's Q or jQuery's Deferred
 21533  * implementations, and the other which resembles ES6 promises to some degree.
 22077  * implementations, and the other which resembles ES6 promises to some degree.
 21534  *
 22078  *
 21535  * # $q constructor
 22079  * # $q constructor
 21542  * available yet.
 22086  * available yet.
 21543  *
 22087  *
 21544  * It can be used like so:
 22088  * It can be used like so:
 21545  *
 22089  *
 21546  * ```js
 22090  * ```js
 21547  * return $q(function(resolve, reject) {
 22091  *   // for the purpose of this example let's assume that variables `$q` and `okToGreet`
 21548  *   // perform some asynchronous operation, resolve or reject the promise when appropriate.
 22092  *   // are available in the current lexical scope (they could have been injected or passed in).
 21549  *   setInterval(function() {
 22093  *
 21550  *     if (pollStatus > 0) {
 22094  *   function asyncGreet(name) {
 21551  *       resolve(polledValue);
 22095  *     // perform some asynchronous operation, resolve or reject the promise when appropriate.
 21552  *     } else if (pollStatus < 0) {
 22096  *     return $q(function(resolve, reject) {
 21553  *       reject(polledValue);
 22097  *       setTimeout(function() {
 21554  *     } else {
 22098  *         if (okToGreet(name)) {
 21555  *       pollStatus = pollAgain(function(value) {
 22099  *           resolve('Hello, ' + name + '!');
 21556  *         polledValue = value;
 22100  *         } else {
 21557  *       });
 22101  *           reject('Greeting ' + name + ' is not allowed.');
 21558  *     }
 22102  *         }
 21559  *   }, 10000);
 22103  *       }, 1000);
 21560  * }).
 22104  *     });
 21561  *   then(function(value) {
 22105  *   }
 21562  *     // handle success
 22106  *
       
 22107  *   var promise = asyncGreet('Robin Hood');
       
 22108  *   promise.then(function(greeting) {
       
 22109  *     alert('Success: ' + greeting);
 21563  *   }, function(reason) {
 22110  *   }, function(reason) {
 21564  *     // handle failure
 22111  *     alert('Failed: ' + reason);
 21565  *   });
 22112  *   });
 21566  * ```
 22113  * ```
 21567  *
 22114  *
 21568  * Note: progress/notify callbacks are not currently supported via the ES6-style interface.
 22115  * Note: progress/notify callbacks are not currently supported via the ES6-style interface.
 21569  *
 22116  *
 21575  *
 22122  *
 21576  * From the perspective of dealing with error handling, deferred and promise APIs are to
 22123  * From the perspective of dealing with error handling, deferred and promise APIs are to
 21577  * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.
 22124  * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.
 21578  *
 22125  *
 21579  * ```js
 22126  * ```js
 21580  *   // for the purpose of this example let's assume that variables `$q`, `scope` and `okToGreet`
 22127  *   // for the purpose of this example let's assume that variables `$q` and `okToGreet`
 21581  *   // are available in the current lexical scope (they could have been injected or passed in).
 22128  *   // are available in the current lexical scope (they could have been injected or passed in).
 21582  *
 22129  *
 21583  *   function asyncGreet(name) {
 22130  *   function asyncGreet(name) {
 21584  *     var deferred = $q.defer();
 22131  *     var deferred = $q.defer();
 21585  *
 22132  *
 21658  *   `notifyCallback` method. The promise cannot be resolved or rejected from the notifyCallback
 22205  *   `notifyCallback` method. The promise cannot be resolved or rejected from the notifyCallback
 21659  *   method.
 22206  *   method.
 21660  *
 22207  *
 21661  * - `catch(errorCallback)` – shorthand for `promise.then(null, errorCallback)`
 22208  * - `catch(errorCallback)` – shorthand for `promise.then(null, errorCallback)`
 21662  *
 22209  *
 21663  * - `finally(callback)` – allows you to observe either the fulfillment or rejection of a promise,
 22210  * - `finally(callback, notifyCallback)` – allows you to observe either the fulfillment or rejection of a promise,
 21664  *   but to do so without modifying the final value. This is useful to release resources or do some
 22211  *   but to do so without modifying the final value. This is useful to release resources or do some
 21665  *   clean-up that needs to be done whether the promise was rejected or resolved. See the [full
 22212  *   clean-up that needs to be done whether the promise was rejected or resolved. See the [full
 21666  *   specification](https://github.com/kriskowal/q/wiki/API-Reference#promisefinallycallback) for
 22213  *   specification](https://github.com/kriskowal/q/wiki/API-Reference#promisefinallycallback) for
 21667  *   more information.
 22214  *   more information.
 21668  *
       
 21669  *   Because `finally` is a reserved word in JavaScript and reserved keywords are not supported as
       
 21670  *   property names by ES3, you'll need to invoke the method like `promise['finally'](callback)` to
       
 21671  *   make your code IE8 and Android 2.x compatible.
       
 21672  *
 22215  *
 21673  * # Chaining promises
 22216  * # Chaining promises
 21674  *
 22217  *
 21675  * Because calling the `then` method of a promise returns a new derived promise, it is easily
 22218  * Because calling the `then` method of a promise returns a new derived promise, it is easily
 21676  * possible to create a chain of promises:
 22219  * possible to create a chain of promises:
 21834         } else if (state.status === 1) {
 22377         } else if (state.status === 1) {
 21835           promise.resolve(state.value);
 22378           promise.resolve(state.value);
 21836         } else {
 22379         } else {
 21837           promise.reject(state.value);
 22380           promise.reject(state.value);
 21838         }
 22381         }
 21839       } catch(e) {
 22382       } catch (e) {
 21840         promise.reject(e);
 22383         promise.reject(e);
 21841         exceptionHandler(e);
 22384         exceptionHandler(e);
 21842       }
 22385       }
 21843     }
 22386     }
 21844   }
 22387   }
 21884         } else {
 22427         } else {
 21885           this.promise.$$state.value = val;
 22428           this.promise.$$state.value = val;
 21886           this.promise.$$state.status = 1;
 22429           this.promise.$$state.status = 1;
 21887           scheduleProcessQueue(this.promise.$$state);
 22430           scheduleProcessQueue(this.promise.$$state);
 21888         }
 22431         }
 21889       } catch(e) {
 22432       } catch (e) {
 21890         fns[1](e);
 22433         fns[1](e);
 21891         exceptionHandler(e);
 22434         exceptionHandler(e);
 21892       }
 22435       }
 21893     },
 22436     },
 21894 
 22437 
 21912           for (var i = 0, ii = callbacks.length; i < ii; i++) {
 22455           for (var i = 0, ii = callbacks.length; i < ii; i++) {
 21913             result = callbacks[i][0];
 22456             result = callbacks[i][0];
 21914             callback = callbacks[i][3];
 22457             callback = callbacks[i][3];
 21915             try {
 22458             try {
 21916               result.notify(isFunction(callback) ? callback(progress) : progress);
 22459               result.notify(isFunction(callback) ? callback(progress) : progress);
 21917             } catch(e) {
 22460             } catch (e) {
 21918               exceptionHandler(e);
 22461               exceptionHandler(e);
 21919             }
 22462             }
 21920           }
 22463           }
 21921         });
 22464         });
 21922       }
 22465       }
 21977 
 22520 
 21978   var handleCallback = function handleCallback(value, isResolved, callback) {
 22521   var handleCallback = function handleCallback(value, isResolved, callback) {
 21979     var callbackOutput = null;
 22522     var callbackOutput = null;
 21980     try {
 22523     try {
 21981       if (isFunction(callback)) callbackOutput = callback();
 22524       if (isFunction(callback)) callbackOutput = callback();
 21982     } catch(e) {
 22525     } catch (e) {
 21983       return makePromise(e, false);
 22526       return makePromise(e, false);
 21984     }
 22527     }
 21985     if (isPromiseLike(callbackOutput)) {
 22528     if (isPromiseLike(callbackOutput)) {
 21986       return callbackOutput.then(function() {
 22529       return callbackOutput.then(function() {
 21987         return makePromise(value, isResolved);
 22530         return makePromise(value, isResolved);
 22085   $Q.all = all;
 22628   $Q.all = all;
 22086 
 22629 
 22087   return $Q;
 22630   return $Q;
 22088 }
 22631 }
 22089 
 22632 
 22090 function $$RAFProvider(){ //rAF
 22633 function $$RAFProvider() { //rAF
 22091   this.$get = ['$window', '$timeout', function($window, $timeout) {
 22634   this.$get = ['$window', '$timeout', function($window, $timeout) {
 22092     var requestAnimationFrame = $window.requestAnimationFrame ||
 22635     var requestAnimationFrame = $window.requestAnimationFrame ||
 22093                                 $window.webkitRequestAnimationFrame ||
 22636                                 $window.webkitRequestAnimationFrame;
 22094                                 $window.mozRequestAnimationFrame;
       
 22095 
 22637 
 22096     var cancelAnimationFrame = $window.cancelAnimationFrame ||
 22638     var cancelAnimationFrame = $window.cancelAnimationFrame ||
 22097                                $window.webkitCancelAnimationFrame ||
 22639                                $window.webkitCancelAnimationFrame ||
 22098                                $window.mozCancelAnimationFrame ||
       
 22099                                $window.webkitCancelRequestAnimationFrame;
 22640                                $window.webkitCancelRequestAnimationFrame;
 22100 
 22641 
 22101     var rafSupported = !!requestAnimationFrame;
 22642     var rafSupported = !!requestAnimationFrame;
 22102     var raf = rafSupported
 22643     var raf = rafSupported
 22103       ? function(fn) {
 22644       ? function(fn) {
 22184  * All other scopes are descendant scopes of the root scope. Scopes provide separation
 22725  * All other scopes are descendant scopes of the root scope. Scopes provide separation
 22185  * between the model and the view, via a mechanism for watching the model for changes.
 22726  * between the model and the view, via a mechanism for watching the model for changes.
 22186  * They also provide an event emission/broadcast and subscription facility. See the
 22727  * They also provide an event emission/broadcast and subscription facility. See the
 22187  * {@link guide/scope developer guide on scopes}.
 22728  * {@link guide/scope developer guide on scopes}.
 22188  */
 22729  */
 22189 function $RootScopeProvider(){
 22730 function $RootScopeProvider() {
 22190   var TTL = 10;
 22731   var TTL = 10;
 22191   var $rootScopeMinErr = minErr('$rootScope');
 22732   var $rootScopeMinErr = minErr('$rootScope');
 22192   var lastDirtyWatch = null;
 22733   var lastDirtyWatch = null;
 22193   var applyAsyncId = null;
 22734   var applyAsyncId = null;
 22194 
 22735 
 22198     }
 22739     }
 22199     return TTL;
 22740     return TTL;
 22200   };
 22741   };
 22201 
 22742 
 22202   this.$get = ['$injector', '$exceptionHandler', '$parse', '$browser',
 22743   this.$get = ['$injector', '$exceptionHandler', '$parse', '$browser',
 22203       function( $injector,   $exceptionHandler,   $parse,   $browser) {
 22744       function($injector, $exceptionHandler, $parse, $browser) {
 22204 
 22745 
 22205     /**
 22746     /**
 22206      * @ngdoc type
 22747      * @ngdoc type
 22207      * @name $rootScope.Scope
 22748      * @name $rootScope.Scope
 22208      *
 22749      *
 22222      * ```js
 22763      * ```js
 22223          var parent = $rootScope;
 22764          var parent = $rootScope;
 22224          var child = parent.$new();
 22765          var child = parent.$new();
 22225 
 22766 
 22226          parent.salutation = "Hello";
 22767          parent.salutation = "Hello";
 22227          child.name = "World";
       
 22228          expect(child.salutation).toEqual('Hello');
 22768          expect(child.salutation).toEqual('Hello');
 22229 
 22769 
 22230          child.salutation = "Welcome";
 22770          child.salutation = "Welcome";
 22231          expect(child.salutation).toEqual('Welcome');
 22771          expect(child.salutation).toEqual('Welcome');
 22232          expect(parent.salutation).toEqual('Hello');
 22772          expect(parent.salutation).toEqual('Hello');
 22233      * ```
 22773      * ```
       
 22774      *
       
 22775      * When interacting with `Scope` in tests, additional helper methods are available on the
       
 22776      * instances of `Scope` type. See {@link ngMock.$rootScope.Scope ngMock Scope} for additional
       
 22777      * details.
 22234      *
 22778      *
 22235      *
 22779      *
 22236      * @param {Object.<string, function()>=} providers Map of service factory which need to be
 22780      * @param {Object.<string, function()>=} providers Map of service factory which need to be
 22237      *                                       provided for the current scope. Defaults to {@link ng}.
 22781      *                                       provided for the current scope. Defaults to {@link ng}.
 22238      * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should
 22782      * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should
 22541         var firstRun = true;
 23085         var firstRun = true;
 22542 
 23086 
 22543         if (!watchExpressions.length) {
 23087         if (!watchExpressions.length) {
 22544           // No expressions means we call the listener ASAP
 23088           // No expressions means we call the listener ASAP
 22545           var shouldCall = true;
 23089           var shouldCall = true;
 22546           self.$evalAsync(function () {
 23090           self.$evalAsync(function() {
 22547             if (shouldCall) listener(newValues, newValues, self);
 23091             if (shouldCall) listener(newValues, newValues, self);
 22548           });
 23092           });
 22549           return function deregisterWatchGroup() {
 23093           return function deregisterWatchGroup() {
 22550             shouldCall = false;
 23094             shouldCall = false;
 22551           };
 23095           };
 22558             oldValues[0] = oldValue;
 23102             oldValues[0] = oldValue;
 22559             listener(newValues, (value === oldValue) ? newValues : oldValues, scope);
 23103             listener(newValues, (value === oldValue) ? newValues : oldValues, scope);
 22560           });
 23104           });
 22561         }
 23105         }
 22562 
 23106 
 22563         forEach(watchExpressions, function (expr, i) {
 23107         forEach(watchExpressions, function(expr, i) {
 22564           var unwatchFn = self.$watch(expr, function watchGroupSubAction(value, oldValue) {
 23108           var unwatchFn = self.$watch(expr, function watchGroupSubAction(value, oldValue) {
 22565             newValues[i] = value;
 23109             newValues[i] = value;
 22566             oldValues[i] = oldValue;
 23110             oldValues[i] = oldValue;
 22567             if (!changeReactionScheduled) {
 23111             if (!changeReactionScheduled) {
 22568               changeReactionScheduled = true;
 23112               changeReactionScheduled = true;
 22668 
 23212 
 22669         function $watchCollectionInterceptor(_value) {
 23213         function $watchCollectionInterceptor(_value) {
 22670           newValue = _value;
 23214           newValue = _value;
 22671           var newLength, key, bothNaN, newItem, oldItem;
 23215           var newLength, key, bothNaN, newItem, oldItem;
 22672 
 23216 
       
 23217           // If the new value is undefined, then return undefined as the watch may be a one-time watch
       
 23218           if (isUndefined(newValue)) return;
       
 23219 
 22673           if (!isObject(newValue)) { // if primitive
 23220           if (!isObject(newValue)) { // if primitive
 22674             if (oldValue !== newValue) {
 23221             if (oldValue !== newValue) {
 22675               oldValue = newValue;
 23222               oldValue = newValue;
 22676               changeDetected++;
 23223               changeDetected++;
 22677             }
 23224             }
 22730               }
 23277               }
 22731             }
 23278             }
 22732             if (oldLength > newLength) {
 23279             if (oldLength > newLength) {
 22733               // we used to have more keys, need to find them and destroy them.
 23280               // we used to have more keys, need to find them and destroy them.
 22734               changeDetected++;
 23281               changeDetected++;
 22735               for(key in oldValue) {
 23282               for (key in oldValue) {
 22736                 if (!newValue.hasOwnProperty(key)) {
 23283                 if (!newValue.hasOwnProperty(key)) {
 22737                   oldLength--;
 23284                   oldLength--;
 22738                   delete oldValue[key];
 23285                   delete oldValue[key];
 22739                 }
 23286                 }
 22740               }
 23287               }
 22850 
 23397 
 22851         do { // "while dirty" loop
 23398         do { // "while dirty" loop
 22852           dirty = false;
 23399           dirty = false;
 22853           current = target;
 23400           current = target;
 22854 
 23401 
 22855           while(asyncQueue.length) {
 23402           while (asyncQueue.length) {
 22856             try {
 23403             try {
 22857               asyncTask = asyncQueue.shift();
 23404               asyncTask = asyncQueue.shift();
 22858               asyncTask.scope.$eval(asyncTask.expression);
 23405               asyncTask.scope.$eval(asyncTask.expression, asyncTask.locals);
 22859             } catch (e) {
 23406             } catch (e) {
 22860               $exceptionHandler(e);
 23407               $exceptionHandler(e);
 22861             }
 23408             }
 22862             lastDirtyWatch = null;
 23409             lastDirtyWatch = null;
 22863           }
 23410           }
 22883                       watch.last = watch.eq ? copy(value, null) : value;
 23430                       watch.last = watch.eq ? copy(value, null) : value;
 22884                       watch.fn(value, ((last === initWatchVal) ? value : last), current);
 23431                       watch.fn(value, ((last === initWatchVal) ? value : last), current);
 22885                       if (ttl < 5) {
 23432                       if (ttl < 5) {
 22886                         logIdx = 4 - ttl;
 23433                         logIdx = 4 - ttl;
 22887                         if (!watchLog[logIdx]) watchLog[logIdx] = [];
 23434                         if (!watchLog[logIdx]) watchLog[logIdx] = [];
 22888                         logMsg = (isFunction(watch.exp))
 23435                         watchLog[logIdx].push({
 22889                             ? 'fn: ' + (watch.exp.name || watch.exp.toString())
 23436                           msg: isFunction(watch.exp) ? 'fn: ' + (watch.exp.name || watch.exp.toString()) : watch.exp,
 22890                             : watch.exp;
 23437                           newVal: value,
 22891                         logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);
 23438                           oldVal: last
 22892                         watchLog[logIdx].push(logMsg);
 23439                         });
 22893                       }
 23440                       }
 22894                     } else if (watch === lastDirtyWatch) {
 23441                     } else if (watch === lastDirtyWatch) {
 22895                       // If the most recently dirty watcher is now clean, short circuit since the remaining watchers
 23442                       // If the most recently dirty watcher is now clean, short circuit since the remaining watchers
 22896                       // have already been tested.
 23443                       // have already been tested.
 22897                       dirty = false;
 23444                       dirty = false;
 22907             // Insanity Warning: scope depth-first traversal
 23454             // Insanity Warning: scope depth-first traversal
 22908             // yes, this code is a bit crazy, but it works and we have tests to prove it!
 23455             // yes, this code is a bit crazy, but it works and we have tests to prove it!
 22909             // this piece should be kept in sync with the traversal in $broadcast
 23456             // this piece should be kept in sync with the traversal in $broadcast
 22910             if (!(next = (current.$$childHead ||
 23457             if (!(next = (current.$$childHead ||
 22911                 (current !== target && current.$$nextSibling)))) {
 23458                 (current !== target && current.$$nextSibling)))) {
 22912               while(current !== target && !(next = current.$$nextSibling)) {
 23459               while (current !== target && !(next = current.$$nextSibling)) {
 22913                 current = current.$parent;
 23460                 current = current.$parent;
 22914               }
 23461               }
 22915             }
 23462             }
 22916           } while ((current = next));
 23463           } while ((current = next));
 22917 
 23464 
 22918           // `break traverseScopesLoop;` takes us to here
 23465           // `break traverseScopesLoop;` takes us to here
 22919 
 23466 
 22920           if((dirty || asyncQueue.length) && !(ttl--)) {
 23467           if ((dirty || asyncQueue.length) && !(ttl--)) {
 22921             clearPhase();
 23468             clearPhase();
 22922             throw $rootScopeMinErr('infdig',
 23469             throw $rootScopeMinErr('infdig',
 22923                 '{0} $digest() iterations reached. Aborting!\n' +
 23470                 '{0} $digest() iterations reached. Aborting!\n' +
 22924                 'Watchers fired in the last 5 iterations: {1}',
 23471                 'Watchers fired in the last 5 iterations: {1}',
 22925                 TTL, toJson(watchLog));
 23472                 TTL, watchLog);
 22926           }
 23473           }
 22927 
 23474 
 22928         } while (dirty || asyncQueue.length);
 23475         } while (dirty || asyncQueue.length);
 22929 
 23476 
 22930         clearPhase();
 23477         clearPhase();
 22931 
 23478 
 22932         while(postDigestQueue.length) {
 23479         while (postDigestQueue.length) {
 22933           try {
 23480           try {
 22934             postDigestQueue.shift()();
 23481             postDigestQueue.shift()();
 22935           } catch (e) {
 23482           } catch (e) {
 22936             $exceptionHandler(e);
 23483             $exceptionHandler(e);
 22937           }
 23484           }
 23068        * @param {(string|function())=} expression An angular expression to be executed.
 23615        * @param {(string|function())=} expression An angular expression to be executed.
 23069        *
 23616        *
 23070        *    - `string`: execute using the rules as defined in {@link guide/expression expression}.
 23617        *    - `string`: execute using the rules as defined in {@link guide/expression expression}.
 23071        *    - `function(scope)`: execute the function with the current `scope` parameter.
 23618        *    - `function(scope)`: execute the function with the current `scope` parameter.
 23072        *
 23619        *
       
 23620        * @param {(object)=} locals Local variables object, useful for overriding values in scope.
 23073        */
 23621        */
 23074       $evalAsync: function(expr) {
 23622       $evalAsync: function(expr, locals) {
 23075         // if we are outside of an $digest loop and this is the first time we are scheduling async
 23623         // if we are outside of an $digest loop and this is the first time we are scheduling async
 23076         // task also schedule async auto-flush
 23624         // task also schedule async auto-flush
 23077         if (!$rootScope.$$phase && !asyncQueue.length) {
 23625         if (!$rootScope.$$phase && !asyncQueue.length) {
 23078           $browser.defer(function() {
 23626           $browser.defer(function() {
 23079             if (asyncQueue.length) {
 23627             if (asyncQueue.length) {
 23080               $rootScope.$digest();
 23628               $rootScope.$digest();
 23081             }
 23629             }
 23082           });
 23630           });
 23083         }
 23631         }
 23084 
 23632 
 23085         asyncQueue.push({scope: this, expression: expr});
 23633         asyncQueue.push({scope: this, expression: expr, locals: locals});
 23086       },
 23634       },
 23087 
 23635 
 23088       $$postDigest : function(fn) {
 23636       $$postDigest: function(fn) {
 23089         postDigestQueue.push(fn);
 23637         postDigestQueue.push(fn);
 23090       },
 23638       },
 23091 
 23639 
 23092       /**
 23640       /**
 23093        * @ngdoc method
 23641        * @ngdoc method
 23220           current.$$listenerCount[name]++;
 23768           current.$$listenerCount[name]++;
 23221         } while ((current = current.$parent));
 23769         } while ((current = current.$parent));
 23222 
 23770 
 23223         var self = this;
 23771         var self = this;
 23224         return function() {
 23772         return function() {
 23225           namedListeners[namedListeners.indexOf(listener)] = null;
 23773           var indexOfListener = namedListeners.indexOf(listener);
 23226           decrementListenerCount(self, 1, name);
 23774           if (indexOfListener !== -1) {
       
 23775             namedListeners[indexOfListener] = null;
       
 23776             decrementListenerCount(self, 1, name);
       
 23777           }
 23227         };
 23778         };
 23228       },
 23779       },
 23229 
 23780 
 23230 
 23781 
 23231       /**
 23782       /**
 23268             i, length;
 23819             i, length;
 23269 
 23820 
 23270         do {
 23821         do {
 23271           namedListeners = scope.$$listeners[name] || empty;
 23822           namedListeners = scope.$$listeners[name] || empty;
 23272           event.currentScope = scope;
 23823           event.currentScope = scope;
 23273           for (i=0, length=namedListeners.length; i<length; i++) {
 23824           for (i = 0, length = namedListeners.length; i < length; i++) {
 23274 
 23825 
 23275             // if listeners were deregistered, defragment the array
 23826             // if listeners were deregistered, defragment the array
 23276             if (!namedListeners[i]) {
 23827             if (!namedListeners[i]) {
 23277               namedListeners.splice(i, 1);
 23828               namedListeners.splice(i, 1);
 23278               i--;
 23829               i--;
 23342 
 23893 
 23343         //down while you can, then up and next sibling or up and next sibling until back at root
 23894         //down while you can, then up and next sibling or up and next sibling until back at root
 23344         while ((current = next)) {
 23895         while ((current = next)) {
 23345           event.currentScope = current;
 23896           event.currentScope = current;
 23346           listeners = current.$$listeners[name] || [];
 23897           listeners = current.$$listeners[name] || [];
 23347           for (i=0, length = listeners.length; i<length; i++) {
 23898           for (i = 0, length = listeners.length; i < length; i++) {
 23348             // if listeners were deregistered, defragment the array
 23899             // if listeners were deregistered, defragment the array
 23349             if (!listeners[i]) {
 23900             if (!listeners[i]) {
 23350               listeners.splice(i, 1);
 23901               listeners.splice(i, 1);
 23351               i--;
 23902               i--;
 23352               length--;
 23903               length--;
 23353               continue;
 23904               continue;
 23354             }
 23905             }
 23355 
 23906 
 23356             try {
 23907             try {
 23357               listeners[i].apply(null, listenerArgs);
 23908               listeners[i].apply(null, listenerArgs);
 23358             } catch(e) {
 23909             } catch (e) {
 23359               $exceptionHandler(e);
 23910               $exceptionHandler(e);
 23360             }
 23911             }
 23361           }
 23912           }
 23362 
 23913 
 23363           // Insanity Warning: scope depth-first traversal
 23914           // Insanity Warning: scope depth-first traversal
 23364           // yes, this code is a bit crazy, but it works and we have tests to prove it!
 23915           // yes, this code is a bit crazy, but it works and we have tests to prove it!
 23365           // this piece should be kept in sync with the traversal in $digest
 23916           // this piece should be kept in sync with the traversal in $digest
 23366           // (though it differs due to having the extra check for $$listenerCount)
 23917           // (though it differs due to having the extra check for $$listenerCount)
 23367           if (!(next = ((current.$$listenerCount[name] && current.$$childHead) ||
 23918           if (!(next = ((current.$$listenerCount[name] && current.$$childHead) ||
 23368               (current !== target && current.$$nextSibling)))) {
 23919               (current !== target && current.$$nextSibling)))) {
 23369             while(current !== target && !(next = current.$$nextSibling)) {
 23920             while (current !== target && !(next = current.$$nextSibling)) {
 23370               current = current.$parent;
 23921               current = current.$parent;
 23371             }
 23922             }
 23372           }
 23923           }
 23373         }
 23924         }
 23374 
 23925 
 23418 
 23969 
 23419     function flushApplyAsync() {
 23970     function flushApplyAsync() {
 23420       while (applyAsyncQueue.length) {
 23971       while (applyAsyncQueue.length) {
 23421         try {
 23972         try {
 23422           applyAsyncQueue.shift()();
 23973           applyAsyncQueue.shift()();
 23423         } catch(e) {
 23974         } catch (e) {
 23424           $exceptionHandler(e);
 23975           $exceptionHandler(e);
 23425         }
 23976         }
 23426       }
 23977       }
 23427       applyAsyncId = null;
 23978       applyAsyncId = null;
 23428     }
 23979     }
 23498     return function sanitizeUri(uri, isImage) {
 24049     return function sanitizeUri(uri, isImage) {
 23499       var regex = isImage ? imgSrcSanitizationWhitelist : aHrefSanitizationWhitelist;
 24050       var regex = isImage ? imgSrcSanitizationWhitelist : aHrefSanitizationWhitelist;
 23500       var normalizedVal;
 24051       var normalizedVal;
 23501       normalizedVal = urlResolve(uri).href;
 24052       normalizedVal = urlResolve(uri).href;
 23502       if (normalizedVal !== '' && !normalizedVal.match(regex)) {
 24053       if (normalizedVal !== '' && !normalizedVal.match(regex)) {
 23503         return 'unsafe:'+normalizedVal;
 24054         return 'unsafe:' + normalizedVal;
 23504       }
 24055       }
 23505       return uri;
 24056       return uri;
 23506     };
 24057     };
 23507   };
 24058   };
 23508 }
 24059 }
 23518   RESOURCE_URL: 'resourceUrl',
 24069   RESOURCE_URL: 'resourceUrl',
 23519   JS: 'js'
 24070   JS: 'js'
 23520 };
 24071 };
 23521 
 24072 
 23522 // Helper functions follow.
 24073 // Helper functions follow.
 23523 
       
 23524 // Copied from:
       
 23525 // http://docs.closure-library.googlecode.com/git/closure_goog_string_string.js.source.html#line962
       
 23526 // Prereq: s is a string.
       
 23527 function escapeForRegexp(s) {
       
 23528   return s.replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g, '\\$1').
       
 23529            replace(/\x08/g, '\\x08');
       
 23530 }
       
 23531 
       
 23532 
 24074 
 23533 function adjustMatcher(matcher) {
 24075 function adjustMatcher(matcher) {
 23534   if (matcher === 'self') {
 24076   if (matcher === 'self') {
 23535     return matcher;
 24077     return matcher;
 23536   } else if (isString(matcher)) {
 24078   } else if (isString(matcher)) {
 23663    * same origin resource requests.
 24205    * same origin resource requests.
 23664    *
 24206    *
 23665    * @description
 24207    * @description
 23666    * Sets/Gets the whitelist of trusted resource URLs.
 24208    * Sets/Gets the whitelist of trusted resource URLs.
 23667    */
 24209    */
 23668   this.resourceUrlWhitelist = function (value) {
 24210   this.resourceUrlWhitelist = function(value) {
 23669     if (arguments.length) {
 24211     if (arguments.length) {
 23670       resourceUrlWhitelist = adjustMatchers(value);
 24212       resourceUrlWhitelist = adjustMatchers(value);
 23671     }
 24213     }
 23672     return resourceUrlWhitelist;
 24214     return resourceUrlWhitelist;
 23673   };
 24215   };
 23697    *
 24239    *
 23698    * @description
 24240    * @description
 23699    * Sets/Gets the blacklist of trusted resource URLs.
 24241    * Sets/Gets the blacklist of trusted resource URLs.
 23700    */
 24242    */
 23701 
 24243 
 23702   this.resourceUrlBlacklist = function (value) {
 24244   this.resourceUrlBlacklist = function(value) {
 23703     if (arguments.length) {
 24245     if (arguments.length) {
 23704       resourceUrlBlacklist = adjustMatchers(value);
 24246       resourceUrlBlacklist = adjustMatchers(value);
 23705     }
 24247     }
 23706     return resourceUrlBlacklist;
 24248     return resourceUrlBlacklist;
 23707   };
 24249   };
 23915  * such a context is binding arbitrary html controlled by the user via `ng-bind-html`.  We refer
 24457  * such a context is binding arbitrary html controlled by the user via `ng-bind-html`.  We refer
 23916  * to these contexts as privileged or SCE contexts.
 24458  * to these contexts as privileged or SCE contexts.
 23917  *
 24459  *
 23918  * As of version 1.2, Angular ships with SCE enabled by default.
 24460  * As of version 1.2, Angular ships with SCE enabled by default.
 23919  *
 24461  *
 23920  * Note:  When enabled (the default), IE8 in quirks mode is not supported.  In this mode, IE8 allows
 24462  * Note:  When enabled (the default), IE<11 in quirks mode is not supported.  In this mode, IE<11 allow
 23921  * one to execute arbitrary javascript by the use of the expression() syntax.  Refer
 24463  * one to execute arbitrary javascript by the use of the expression() syntax.  Refer
 23922  * <http://blogs.msdn.com/b/ie/archive/2008/10/16/ending-expressions.aspx> to learn more about them.
 24464  * <http://blogs.msdn.com/b/ie/archive/2008/10/16/ending-expressions.aspx> to learn more about them.
 23923  * You can ensure your document is in standards mode and not quirks mode by adding `<!doctype html>`
 24465  * You can ensure your document is in standards mode and not quirks mode by adding `<!doctype html>`
 23924  * to the top of your HTML document.
 24466  * to the top of your HTML document.
 23925  *
 24467  *
 23962  *
 24504  *
 23963  * ## How does it work?
 24505  * ## How does it work?
 23964  *
 24506  *
 23965  * In privileged contexts, directives and code will bind to the result of {@link ng.$sce#getTrusted
 24507  * In privileged contexts, directives and code will bind to the result of {@link ng.$sce#getTrusted
 23966  * $sce.getTrusted(context, value)} rather than to the value directly.  Directives use {@link
 24508  * $sce.getTrusted(context, value)} rather than to the value directly.  Directives use {@link
 23967  * ng.$sce#parse $sce.parseAs} rather than `$parse` to watch attribute bindings, which performs the
 24509  * ng.$sce#parseAs $sce.parseAs} rather than `$parse` to watch attribute bindings, which performs the
 23968  * {@link ng.$sce#getTrusted $sce.getTrusted} behind the scenes on non-constant literals.
 24510  * {@link ng.$sce#getTrusted $sce.getTrusted} behind the scenes on non-constant literals.
 23969  *
 24511  *
 23970  * As an example, {@link ng.directive:ngBindHtml ngBindHtml} uses {@link
 24512  * As an example, {@link ng.directive:ngBindHtml ngBindHtml} uses {@link
 23971  * ng.$sce#parseAsHtml $sce.parseAsHtml(binding expression)}.  Here's the actual code (slightly
 24513  * ng.$sce#parseAsHtml $sce.parseAsHtml(binding expression)}.  Here's the actual code (slightly
 23972  * simplified):
 24514  * simplified):
 24178    * @return {boolean} true if SCE is enabled, false otherwise.
 24720    * @return {boolean} true if SCE is enabled, false otherwise.
 24179    *
 24721    *
 24180    * @description
 24722    * @description
 24181    * Enables/disables SCE and returns the current value.
 24723    * Enables/disables SCE and returns the current value.
 24182    */
 24724    */
 24183   this.enabled = function (value) {
 24725   this.enabled = function(value) {
 24184     if (arguments.length) {
 24726     if (arguments.length) {
 24185       enabled = !!value;
 24727       enabled = !!value;
 24186     }
 24728     }
 24187     return enabled;
 24729     return enabled;
 24188   };
 24730   };
 24232    * Inheritance happens to capture this in a natural way.  In some future, we
 24774    * Inheritance happens to capture this in a natural way.  In some future, we
 24233    * may not use inheritance anymore.  That is OK because no code outside of
 24775    * may not use inheritance anymore.  That is OK because no code outside of
 24234    * sce.js and sceSpecs.js would need to be aware of this detail.
 24776    * sce.js and sceSpecs.js would need to be aware of this detail.
 24235    */
 24777    */
 24236 
 24778 
 24237   this.$get = ['$parse', '$sniffer', '$sceDelegate', function(
 24779   this.$get = ['$parse', '$sceDelegate', function(
 24238                 $parse,   $sniffer,   $sceDelegate) {
 24780                 $parse,   $sceDelegate) {
 24239     // Prereq: Ensure that we're not running in IE8 quirks mode.  In that mode, IE allows
 24781     // Prereq: Ensure that we're not running in IE<11 quirks mode.  In that mode, IE < 11 allow
 24240     // the "expression(javascript expression)" syntax which is insecure.
 24782     // the "expression(javascript expression)" syntax which is insecure.
 24241     if (enabled && $sniffer.msie && $sniffer.msieDocumentMode < 8) {
 24783     if (enabled && msie < 8) {
 24242       throw $sceMinErr('iequirks',
 24784       throw $sceMinErr('iequirks',
 24243         'Strict Contextual Escaping does not support Internet Explorer version < 9 in quirks ' +
 24785         'Strict Contextual Escaping does not support Internet Explorer version < 11 in quirks ' +
 24244         'mode.  You can fix this by adding the text <!doctype html> to the top of your HTML ' +
 24786         'mode.  You can fix this by adding the text <!doctype html> to the top of your HTML ' +
 24245         'document.  See http://docs.angularjs.org/api/ng.$sce for more information.');
 24787         'document.  See http://docs.angularjs.org/api/ng.$sce for more information.');
 24246     }
 24788     }
 24247 
 24789 
 24248     var sce = shallowCopy(SCE_CONTEXTS);
 24790     var sce = shallowCopy(SCE_CONTEXTS);
 24256      * have to do it at module config time on {@link ng.$sceProvider $sceProvider}.
 24798      * have to do it at module config time on {@link ng.$sceProvider $sceProvider}.
 24257      *
 24799      *
 24258      * @description
 24800      * @description
 24259      * Returns a boolean indicating if SCE is enabled.
 24801      * Returns a boolean indicating if SCE is enabled.
 24260      */
 24802      */
 24261     sce.isEnabled = function () {
 24803     sce.isEnabled = function() {
 24262       return enabled;
 24804       return enabled;
 24263     };
 24805     };
 24264     sce.trustAs = $sceDelegate.trustAs;
 24806     sce.trustAs = $sceDelegate.trustAs;
 24265     sce.getTrusted = $sceDelegate.getTrusted;
 24807     sce.getTrusted = $sceDelegate.getTrusted;
 24266     sce.valueOf = $sceDelegate.valueOf;
 24808     sce.valueOf = $sceDelegate.valueOf;
 24292     sce.parseAs = function sceParseAs(type, expr) {
 24834     sce.parseAs = function sceParseAs(type, expr) {
 24293       var parsed = $parse(expr);
 24835       var parsed = $parse(expr);
 24294       if (parsed.literal && parsed.constant) {
 24836       if (parsed.literal && parsed.constant) {
 24295         return parsed;
 24837         return parsed;
 24296       } else {
 24838       } else {
 24297         return $parse(expr, function (value) {
 24839         return $parse(expr, function(value) {
 24298           return sce.getTrusted(type, value);
 24840           return sce.getTrusted(type, value);
 24299         });
 24841         });
 24300       }
 24842       }
 24301     };
 24843     };
 24302 
 24844 
 24461      * @ngdoc method
 25003      * @ngdoc method
 24462      * @name $sce#parseAsHtml
 25004      * @name $sce#parseAsHtml
 24463      *
 25005      *
 24464      * @description
 25006      * @description
 24465      * Shorthand method.  `$sce.parseAsHtml(expression string)` →
 25007      * Shorthand method.  `$sce.parseAsHtml(expression string)` →
 24466      *     {@link ng.$sce#parse `$sce.parseAs($sce.HTML, value)`}
 25008      *     {@link ng.$sce#parseAs `$sce.parseAs($sce.HTML, value)`}
 24467      *
 25009      *
 24468      * @param {string} expression String expression to compile.
 25010      * @param {string} expression String expression to compile.
 24469      * @returns {function(context, locals)} a function which represents the compiled expression:
 25011      * @returns {function(context, locals)} a function which represents the compiled expression:
 24470      *
 25012      *
 24471      *    * `context` – `{object}` – an object against which any expressions embedded in the strings
 25013      *    * `context` – `{object}` – an object against which any expressions embedded in the strings
 24478      * @ngdoc method
 25020      * @ngdoc method
 24479      * @name $sce#parseAsCss
 25021      * @name $sce#parseAsCss
 24480      *
 25022      *
 24481      * @description
 25023      * @description
 24482      * Shorthand method.  `$sce.parseAsCss(value)` →
 25024      * Shorthand method.  `$sce.parseAsCss(value)` →
 24483      *     {@link ng.$sce#parse `$sce.parseAs($sce.CSS, value)`}
 25025      *     {@link ng.$sce#parseAs `$sce.parseAs($sce.CSS, value)`}
 24484      *
 25026      *
 24485      * @param {string} expression String expression to compile.
 25027      * @param {string} expression String expression to compile.
 24486      * @returns {function(context, locals)} a function which represents the compiled expression:
 25028      * @returns {function(context, locals)} a function which represents the compiled expression:
 24487      *
 25029      *
 24488      *    * `context` – `{object}` – an object against which any expressions embedded in the strings
 25030      *    * `context` – `{object}` – an object against which any expressions embedded in the strings
 24495      * @ngdoc method
 25037      * @ngdoc method
 24496      * @name $sce#parseAsUrl
 25038      * @name $sce#parseAsUrl
 24497      *
 25039      *
 24498      * @description
 25040      * @description
 24499      * Shorthand method.  `$sce.parseAsUrl(value)` →
 25041      * Shorthand method.  `$sce.parseAsUrl(value)` →
 24500      *     {@link ng.$sce#parse `$sce.parseAs($sce.URL, value)`}
 25042      *     {@link ng.$sce#parseAs `$sce.parseAs($sce.URL, value)`}
 24501      *
 25043      *
 24502      * @param {string} expression String expression to compile.
 25044      * @param {string} expression String expression to compile.
 24503      * @returns {function(context, locals)} a function which represents the compiled expression:
 25045      * @returns {function(context, locals)} a function which represents the compiled expression:
 24504      *
 25046      *
 24505      *    * `context` – `{object}` – an object against which any expressions embedded in the strings
 25047      *    * `context` – `{object}` – an object against which any expressions embedded in the strings
 24512      * @ngdoc method
 25054      * @ngdoc method
 24513      * @name $sce#parseAsResourceUrl
 25055      * @name $sce#parseAsResourceUrl
 24514      *
 25056      *
 24515      * @description
 25057      * @description
 24516      * Shorthand method.  `$sce.parseAsResourceUrl(value)` →
 25058      * Shorthand method.  `$sce.parseAsResourceUrl(value)` →
 24517      *     {@link ng.$sce#parse `$sce.parseAs($sce.RESOURCE_URL, value)`}
 25059      *     {@link ng.$sce#parseAs `$sce.parseAs($sce.RESOURCE_URL, value)`}
 24518      *
 25060      *
 24519      * @param {string} expression String expression to compile.
 25061      * @param {string} expression String expression to compile.
 24520      * @returns {function(context, locals)} a function which represents the compiled expression:
 25062      * @returns {function(context, locals)} a function which represents the compiled expression:
 24521      *
 25063      *
 24522      *    * `context` – `{object}` – an object against which any expressions embedded in the strings
 25064      *    * `context` – `{object}` – an object against which any expressions embedded in the strings
 24529      * @ngdoc method
 25071      * @ngdoc method
 24530      * @name $sce#parseAsJs
 25072      * @name $sce#parseAsJs
 24531      *
 25073      *
 24532      * @description
 25074      * @description
 24533      * Shorthand method.  `$sce.parseAsJs(value)` →
 25075      * Shorthand method.  `$sce.parseAsJs(value)` →
 24534      *     {@link ng.$sce#parse `$sce.parseAs($sce.JS, value)`}
 25076      *     {@link ng.$sce#parseAs `$sce.parseAs($sce.JS, value)`}
 24535      *
 25077      *
 24536      * @param {string} expression String expression to compile.
 25078      * @param {string} expression String expression to compile.
 24537      * @returns {function(context, locals)} a function which represents the compiled expression:
 25079      * @returns {function(context, locals)} a function which represents the compiled expression:
 24538      *
 25080      *
 24539      *    * `context` – `{object}` – an object against which any expressions embedded in the strings
 25081      *    * `context` – `{object}` – an object against which any expressions embedded in the strings
 24545     // Shorthand delegations.
 25087     // Shorthand delegations.
 24546     var parse = sce.parseAs,
 25088     var parse = sce.parseAs,
 24547         getTrusted = sce.getTrusted,
 25089         getTrusted = sce.getTrusted,
 24548         trustAs = sce.trustAs;
 25090         trustAs = sce.trustAs;
 24549 
 25091 
 24550     forEach(SCE_CONTEXTS, function (enumValue, name) {
 25092     forEach(SCE_CONTEXTS, function(enumValue, name) {
 24551       var lName = lowercase(name);
 25093       var lName = lowercase(name);
 24552       sce[camelCase("parse_as_" + lName)] = function (expr) {
 25094       sce[camelCase("parse_as_" + lName)] = function(expr) {
 24553         return parse(enumValue, expr);
 25095         return parse(enumValue, expr);
 24554       };
 25096       };
 24555       sce[camelCase("get_trusted_" + lName)] = function (value) {
 25097       sce[camelCase("get_trusted_" + lName)] = function(value) {
 24556         return getTrusted(enumValue, value);
 25098         return getTrusted(enumValue, value);
 24557       };
 25099       };
 24558       sce[camelCase("trust_as_" + lName)] = function (value) {
 25100       sce[camelCase("trust_as_" + lName)] = function(value) {
 24559         return trustAs(enumValue, value);
 25101         return trustAs(enumValue, value);
 24560       };
 25102       };
 24561     });
 25103     });
 24562 
 25104 
 24563     return sce;
 25105     return sce;
 24583     var eventSupport = {},
 25125     var eventSupport = {},
 24584         android =
 25126         android =
 24585           int((/android (\d+)/.exec(lowercase(($window.navigator || {}).userAgent)) || [])[1]),
 25127           int((/android (\d+)/.exec(lowercase(($window.navigator || {}).userAgent)) || [])[1]),
 24586         boxee = /Boxee/i.test(($window.navigator || {}).userAgent),
 25128         boxee = /Boxee/i.test(($window.navigator || {}).userAgent),
 24587         document = $document[0] || {},
 25129         document = $document[0] || {},
 24588         documentMode = document.documentMode,
       
 24589         vendorPrefix,
 25130         vendorPrefix,
 24590         vendorRegex = /^(Moz|webkit|O|ms)(?=[A-Z])/,
 25131         vendorRegex = /^(Moz|webkit|ms)(?=[A-Z])/,
 24591         bodyStyle = document.body && document.body.style,
 25132         bodyStyle = document.body && document.body.style,
 24592         transitions = false,
 25133         transitions = false,
 24593         animations = false,
 25134         animations = false,
 24594         match;
 25135         match;
 24595 
 25136 
 24596     if (bodyStyle) {
 25137     if (bodyStyle) {
 24597       for(var prop in bodyStyle) {
 25138       for (var prop in bodyStyle) {
 24598         if(match = vendorRegex.exec(prop)) {
 25139         if (match = vendorRegex.exec(prop)) {
 24599           vendorPrefix = match[0];
 25140           vendorPrefix = match[0];
 24600           vendorPrefix = vendorPrefix.substr(0, 1).toUpperCase() + vendorPrefix.substr(1);
 25141           vendorPrefix = vendorPrefix.substr(0, 1).toUpperCase() + vendorPrefix.substr(1);
 24601           break;
 25142           break;
 24602         }
 25143         }
 24603       }
 25144       }
 24604 
 25145 
 24605       if(!vendorPrefix) {
 25146       if (!vendorPrefix) {
 24606         vendorPrefix = ('WebkitOpacity' in bodyStyle) && 'webkit';
 25147         vendorPrefix = ('WebkitOpacity' in bodyStyle) && 'webkit';
 24607       }
 25148       }
 24608 
 25149 
 24609       transitions = !!(('transition' in bodyStyle) || (vendorPrefix + 'Transition' in bodyStyle));
 25150       transitions = !!(('transition' in bodyStyle) || (vendorPrefix + 'Transition' in bodyStyle));
 24610       animations  = !!(('animation' in bodyStyle) || (vendorPrefix + 'Animation' in bodyStyle));
 25151       animations  = !!(('animation' in bodyStyle) || (vendorPrefix + 'Animation' in bodyStyle));
 24611 
 25152 
 24612       if (android && (!transitions||!animations)) {
 25153       if (android && (!transitions ||  !animations)) {
 24613         transitions = isString(document.body.style.webkitTransition);
 25154         transitions = isString(document.body.style.webkitTransition);
 24614         animations = isString(document.body.style.webkitAnimation);
 25155         animations = isString(document.body.style.webkitAnimation);
 24615       }
 25156       }
 24616     }
 25157     }
 24617 
 25158 
 24630       // jshint +W018
 25171       // jshint +W018
 24631       hasEvent: function(event) {
 25172       hasEvent: function(event) {
 24632         // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have
 25173         // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have
 24633         // it. In particular the event is not fired when backspace or delete key are pressed or
 25174         // it. In particular the event is not fired when backspace or delete key are pressed or
 24634         // when cut operation is performed.
 25175         // when cut operation is performed.
 24635         if (event == 'input' && msie == 9) return false;
 25176         // IE10+ implements 'input' event but it erroneously fires under various situations,
       
 25177         // e.g. when placeholder changes, or a form is focused.
       
 25178         if (event === 'input' && msie <= 11) return false;
 24636 
 25179 
 24637         if (isUndefined(eventSupport[event])) {
 25180         if (isUndefined(eventSupport[event])) {
 24638           var divElm = document.createElement('div');
 25181           var divElm = document.createElement('div');
 24639           eventSupport[event] = 'on' + event in divElm;
 25182           eventSupport[event] = 'on' + event in divElm;
 24640         }
 25183         }
 24641 
 25184 
 24642         return eventSupport[event];
 25185         return eventSupport[event];
 24643       },
 25186       },
 24644       csp: csp(),
 25187       csp: csp(),
 24645       vendorPrefix: vendorPrefix,
 25188       vendorPrefix: vendorPrefix,
 24646       transitions : transitions,
 25189       transitions: transitions,
 24647       animations : animations,
 25190       animations: animations,
 24648       android: android,
 25191       android: android
 24649       msie : msie,
       
 24650       msieDocumentMode: documentMode
       
 24651     };
 25192     };
 24652   }];
 25193   }];
 24653 }
 25194 }
 24654 
 25195 
 24655 var $compileMinErr = minErr('$compile');
 25196 var $compileMinErr = minErr('$compile');
 24659  * @name $templateRequest
 25200  * @name $templateRequest
 24660  *
 25201  *
 24661  * @description
 25202  * @description
 24662  * The `$templateRequest` service downloads the provided template using `$http` and, upon success,
 25203  * The `$templateRequest` service downloads the provided template using `$http` and, upon success,
 24663  * stores the contents inside of `$templateCache`. If the HTTP request fails or the response data
 25204  * stores the contents inside of `$templateCache`. If the HTTP request fails or the response data
 24664  * of the HTTP request is empty then a `$compile` error will be thrown (the exception can be thwarted
 25205  * of the HTTP request is empty, a `$compile` error will be thrown (the exception can be thwarted
 24665  * by setting the 2nd parameter of the function to true).
 25206  * by setting the 2nd parameter of the function to true).
 24666  *
 25207  *
 24667  * @param {string} tpl The HTTP request template URL
 25208  * @param {string} tpl The HTTP request template URL
 24668  * @param {boolean=} ignoreRequestError Whether or not to ignore the exception when the request fails or the template is empty
 25209  * @param {boolean=} ignoreRequestError Whether or not to ignore the exception when the request fails or the template is empty
 24669  *
 25210  *
 24675   this.$get = ['$templateCache', '$http', '$q', function($templateCache, $http, $q) {
 25216   this.$get = ['$templateCache', '$http', '$q', function($templateCache, $http, $q) {
 24676     function handleRequestFn(tpl, ignoreRequestError) {
 25217     function handleRequestFn(tpl, ignoreRequestError) {
 24677       var self = handleRequestFn;
 25218       var self = handleRequestFn;
 24678       self.totalPendingRequests++;
 25219       self.totalPendingRequests++;
 24679 
 25220 
 24680       return $http.get(tpl, { cache : $templateCache })
 25221       var transformResponse = $http.defaults && $http.defaults.transformResponse;
       
 25222 
       
 25223       if (isArray(transformResponse)) {
       
 25224         transformResponse = transformResponse.filter(function(transformer) {
       
 25225           return transformer !== defaultHttpResponseTransform;
       
 25226         });
       
 25227       } else if (transformResponse === defaultHttpResponseTransform) {
       
 25228         transformResponse = null;
       
 25229       }
       
 25230 
       
 25231       var httpOptions = {
       
 25232         cache: $templateCache,
       
 25233         transformResponse: transformResponse
       
 25234       };
       
 25235 
       
 25236       return $http.get(tpl, httpOptions)
 24681         .then(function(response) {
 25237         .then(function(response) {
 24682           var html = response.data;
       
 24683           if(!html || html.length === 0) {
       
 24684             return handleError();
       
 24685           }
       
 24686 
       
 24687           self.totalPendingRequests--;
 25238           self.totalPendingRequests--;
 24688           $templateCache.put(tpl, html);
 25239           return response.data;
 24689           return html;
       
 24690         }, handleError);
 25240         }, handleError);
 24691 
 25241 
 24692       function handleError() {
 25242       function handleError(resp) {
 24693         self.totalPendingRequests--;
 25243         self.totalPendingRequests--;
 24694         if (!ignoreRequestError) {
 25244         if (!ignoreRequestError) {
 24695           throw $compileMinErr('tpload', 'Failed to load template: {0}', tpl);
 25245           throw $compileMinErr('tpload', 'Failed to load template: {0}', tpl);
 24696         }
 25246         }
 24697         return $q.reject();
 25247         return $q.reject(resp);
 24698       }
 25248       }
 24699     }
 25249     }
 24700 
 25250 
 24701     handleRequestFn.totalPendingRequests = 0;
 25251     handleRequestFn.totalPendingRequests = 0;
 24702 
 25252 
 24735       forEach(bindings, function(binding) {
 25285       forEach(bindings, function(binding) {
 24736         var dataBinding = angular.element(binding).data('$binding');
 25286         var dataBinding = angular.element(binding).data('$binding');
 24737         if (dataBinding) {
 25287         if (dataBinding) {
 24738           forEach(dataBinding, function(bindingName) {
 25288           forEach(dataBinding, function(bindingName) {
 24739             if (opt_exactMatch) {
 25289             if (opt_exactMatch) {
 24740               var matcher = new RegExp('(^|\\s)' + expression + '(\\s|\\||$)');
 25290               var matcher = new RegExp('(^|\\s)' + escapeForRegexp(expression) + '(\\s|\\||$)');
 24741               if (matcher.test(bindingName)) {
 25291               if (matcher.test(bindingName)) {
 24742                 matches.push(binding);
 25292                 matches.push(binding);
 24743               }
 25293               }
 24744             } else {
 25294             } else {
 24745               if (bindingName.indexOf(expression) != -1) {
 25295               if (bindingName.indexOf(expression) != -1) {
 24857           timeoutId;
 25407           timeoutId;
 24858 
 25408 
 24859       timeoutId = $browser.defer(function() {
 25409       timeoutId = $browser.defer(function() {
 24860         try {
 25410         try {
 24861           deferred.resolve(fn());
 25411           deferred.resolve(fn());
 24862         } catch(e) {
 25412         } catch (e) {
 24863           deferred.reject(e);
 25413           deferred.reject(e);
 24864           $exceptionHandler(e);
 25414           $exceptionHandler(e);
 24865         }
 25415         }
 24866         finally {
 25416         finally {
 24867           delete deferreds[promise.$$timeoutId];
 25417           delete deferreds[promise.$$timeoutId];
 24908 // cause us to break tests.  In addition, when the browser resolves a URL for XHR, it
 25458 // cause us to break tests.  In addition, when the browser resolves a URL for XHR, it
 24909 // doesn't know about mocked locations and resolves URLs to the real document - which is
 25459 // doesn't know about mocked locations and resolves URLs to the real document - which is
 24910 // exactly the behavior needed here.  There is little value is mocking these out for this
 25460 // exactly the behavior needed here.  There is little value is mocking these out for this
 24911 // service.
 25461 // service.
 24912 var urlParsingNode = document.createElement("a");
 25462 var urlParsingNode = document.createElement("a");
 24913 var originUrl = urlResolve(window.location.href, true);
 25463 var originUrl = urlResolve(window.location.href);
 24914 
 25464 
 24915 
 25465 
 24916 /**
 25466 /**
 24917  *
 25467  *
 24918  * Implementation Notes for non-IE browsers
 25468  * Implementation Notes for non-IE browsers
 24963  *   | hostname      | The hostname
 25513  *   | hostname      | The hostname
 24964  *   | port          | The port, without ":"
 25514  *   | port          | The port, without ":"
 24965  *   | pathname      | The pathname, beginning with "/"
 25515  *   | pathname      | The pathname, beginning with "/"
 24966  *
 25516  *
 24967  */
 25517  */
 24968 function urlResolve(url, base) {
 25518 function urlResolve(url) {
 24969   var href = url;
 25519   var href = url;
 24970 
 25520 
 24971   if (msie) {
 25521   if (msie) {
 24972     // Normalize before parse.  Refer Implementation Notes on why this is
 25522     // Normalize before parse.  Refer Implementation Notes on why this is
 24973     // done in two steps on IE.
 25523     // done in two steps on IE.
 25023  * @example
 25573  * @example
 25024    <example module="windowExample">
 25574    <example module="windowExample">
 25025      <file name="index.html">
 25575      <file name="index.html">
 25026        <script>
 25576        <script>
 25027          angular.module('windowExample', [])
 25577          angular.module('windowExample', [])
 25028            .controller('ExampleController', ['$scope', '$window', function ($scope, $window) {
 25578            .controller('ExampleController', ['$scope', '$window', function($scope, $window) {
 25029              $scope.greeting = 'Hello, World!';
 25579              $scope.greeting = 'Hello, World!';
 25030              $scope.doGreeting = function(greeting) {
 25580              $scope.doGreeting = function(greeting) {
 25031                $window.alert(greeting);
 25581                $window.alert(greeting);
 25032              };
 25582              };
 25033            }]);
 25583            }]);
 25044        // element(':button').click();
 25594        // element(':button').click();
 25045       });
 25595       });
 25046      </file>
 25596      </file>
 25047    </example>
 25597    </example>
 25048  */
 25598  */
 25049 function $WindowProvider(){
 25599 function $WindowProvider() {
 25050   this.$get = valueFn(window);
 25600   this.$get = valueFn(window);
 25051 }
 25601 }
 25052 
 25602 
 25053 /* global currencyFilter: true,
 25603 /* global currencyFilter: true,
 25054  dateFilter: true,
 25604  dateFilter: true,
 25153    *    the keys are the filter names and the values are the filter factories.
 25703    *    the keys are the filter names and the values are the filter factories.
 25154    * @returns {Object} Registered filter instance, or if a map of filters was provided then a map
 25704    * @returns {Object} Registered filter instance, or if a map of filters was provided then a map
 25155    *    of the registered filter instances.
 25705    *    of the registered filter instances.
 25156    */
 25706    */
 25157   function register(name, factory) {
 25707   function register(name, factory) {
 25158     if(isObject(name)) {
 25708     if (isObject(name)) {
 25159       var filters = {};
 25709       var filters = {};
 25160       forEach(name, function(filter, key) {
 25710       forEach(name, function(filter, key) {
 25161         filters[key] = register(key, filter);
 25711         filters[key] = register(key, filter);
 25162       });
 25712       });
 25163       return filters;
 25713       return filters;
 25210  * @param {string|Object|function()} expression The predicate to be used for selecting items from
 25760  * @param {string|Object|function()} expression The predicate to be used for selecting items from
 25211  *   `array`.
 25761  *   `array`.
 25212  *
 25762  *
 25213  *   Can be one of:
 25763  *   Can be one of:
 25214  *
 25764  *
 25215  *   - `string`: The string is evaluated as an expression and the resulting value is used for substring match against
 25765  *   - `string`: The string is used for matching against the contents of the `array`. All strings or
 25216  *     the contents of the `array`. All strings or objects with string properties in `array` that contain this string
 25766  *     objects with string properties in `array` that match this string will be returned. This also
 25217  *     will be returned. The predicate can be negated by prefixing the string with `!`.
 25767  *     applies to nested object properties.
       
 25768  *     The predicate can be negated by prefixing the string with `!`.
 25218  *
 25769  *
 25219  *   - `Object`: A pattern object can be used to filter specific properties on objects contained
 25770  *   - `Object`: A pattern object can be used to filter specific properties on objects contained
 25220  *     by `array`. For example `{name:"M", phone:"1"}` predicate will return an array of items
 25771  *     by `array`. For example `{name:"M", phone:"1"}` predicate will return an array of items
 25221  *     which have property `name` containing "M" and property `phone` containing "1". A special
 25772  *     which have property `name` containing "M" and property `phone` containing "1". A special
 25222  *     property name `$` can be used (as in `{$:"text"}`) to accept a match against any
 25773  *     property name `$` can be used (as in `{$:"text"}`) to accept a match against any
 25223  *     property of the object. That's equivalent to the simple substring match with a `string`
 25774  *     property of the object or its nested object properties. That's equivalent to the simple
 25224  *     as described above. The predicate can be negated by prefixing the string with `!`.
 25775  *     substring match with a `string` as described above. The predicate can be negated by prefixing
 25225  *     For Example `{name: "!M"}` predicate will return an array of items which have property `name`
 25776  *     the string with `!`.
       
 25777  *     For example `{name: "!M"}` predicate will return an array of items which have property `name`
 25226  *     not containing "M".
 25778  *     not containing "M".
       
 25779  *
       
 25780  *     Note that a named property will match properties on the same level only, while the special
       
 25781  *     `$` property will match properties on the same level or deeper. E.g. an array item like
       
 25782  *     `{name: {first: 'John', last: 'Doe'}}` will **not** be matched by `{name: 'John'}`, but
       
 25783  *     **will** be matched by `{$: 'John'}`.
 25227  *
 25784  *
 25228  *   - `function(value, index)`: A predicate function can be used to write arbitrary filters. The
 25785  *   - `function(value, index)`: A predicate function can be used to write arbitrary filters. The
 25229  *     function is called for each element of `array`. The final result is an array of those
 25786  *     function is called for each element of `array`. The final result is an array of those
 25230  *     elements that the predicate returned true for.
 25787  *     elements that the predicate returned true for.
 25231  *
 25788  *
 25235  *
 25792  *
 25236  *   Can be one of:
 25793  *   Can be one of:
 25237  *
 25794  *
 25238  *   - `function(actual, expected)`:
 25795  *   - `function(actual, expected)`:
 25239  *     The function will be given the object value and the predicate value to compare and
 25796  *     The function will be given the object value and the predicate value to compare and
 25240  *     should return true if the item should be included in filtered result.
 25797  *     should return true if both values should be considered equal.
 25241  *
 25798  *
 25242  *   - `true`: A shorthand for `function(actual, expected) { return angular.equals(expected, actual)}`.
 25799  *   - `true`: A shorthand for `function(actual, expected) { return angular.equals(actual, expected)}`.
 25243  *     this is essentially strict comparison of expected and actual.
 25800  *     This is essentially strict comparison of expected and actual.
 25244  *
 25801  *
 25245  *   - `false|undefined`: A short hand for a function which will look for a substring match in case
 25802  *   - `false|undefined`: A short hand for a function which will look for a substring match in case
 25246  *     insensitive way.
 25803  *     insensitive way.
 25247  *
 25804  *
 25248  * @example
 25805  * @example
 25315  */
 25872  */
 25316 function filterFilter() {
 25873 function filterFilter() {
 25317   return function(array, expression, comparator) {
 25874   return function(array, expression, comparator) {
 25318     if (!isArray(array)) return array;
 25875     if (!isArray(array)) return array;
 25319 
 25876 
 25320     var comparatorType = typeof(comparator),
 25877     var predicateFn;
 25321         predicates = [];
 25878     var matchAgainstAnyProp;
 25322 
 25879 
 25323     predicates.check = function(value, index) {
       
 25324       for (var j = 0; j < predicates.length; j++) {
       
 25325         if(!predicates[j](value, index)) {
       
 25326           return false;
       
 25327         }
       
 25328       }
       
 25329       return true;
       
 25330     };
       
 25331 
       
 25332     if (comparatorType !== 'function') {
       
 25333       if (comparatorType === 'boolean' && comparator) {
       
 25334         comparator = function(obj, text) {
       
 25335           return angular.equals(obj, text);
       
 25336         };
       
 25337       } else {
       
 25338         comparator = function(obj, text) {
       
 25339           if (obj && text && typeof obj === 'object' && typeof text === 'object') {
       
 25340             for (var objKey in obj) {
       
 25341               if (objKey.charAt(0) !== '$' && hasOwnProperty.call(obj, objKey) &&
       
 25342                   comparator(obj[objKey], text[objKey])) {
       
 25343                 return true;
       
 25344               }
       
 25345             }
       
 25346             return false;
       
 25347           }
       
 25348           text = (''+text).toLowerCase();
       
 25349           return (''+obj).toLowerCase().indexOf(text) > -1;
       
 25350         };
       
 25351       }
       
 25352     }
       
 25353 
       
 25354     var search = function(obj, text){
       
 25355       if (typeof text == 'string' && text.charAt(0) === '!') {
       
 25356         return !search(obj, text.substr(1));
       
 25357       }
       
 25358       switch (typeof obj) {
       
 25359         case "boolean":
       
 25360         case "number":
       
 25361         case "string":
       
 25362           return comparator(obj, text);
       
 25363         case "object":
       
 25364           switch (typeof text) {
       
 25365             case "object":
       
 25366               return comparator(obj, text);
       
 25367             default:
       
 25368               for ( var objKey in obj) {
       
 25369                 if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {
       
 25370                   return true;
       
 25371                 }
       
 25372               }
       
 25373               break;
       
 25374           }
       
 25375           return false;
       
 25376         case "array":
       
 25377           for ( var i = 0; i < obj.length; i++) {
       
 25378             if (search(obj[i], text)) {
       
 25379               return true;
       
 25380             }
       
 25381           }
       
 25382           return false;
       
 25383         default:
       
 25384           return false;
       
 25385       }
       
 25386     };
       
 25387     switch (typeof expression) {
 25880     switch (typeof expression) {
 25388       case "boolean":
 25881       case 'function':
 25389       case "number":
 25882         predicateFn = expression;
 25390       case "string":
       
 25391         // Set up expression object and fall through
       
 25392         expression = {$:expression};
       
 25393         // jshint -W086
       
 25394       case "object":
       
 25395         // jshint +W086
       
 25396         for (var key in expression) {
       
 25397           (function(path) {
       
 25398             if (typeof expression[path] === 'undefined') return;
       
 25399             predicates.push(function(value) {
       
 25400               return search(path == '$' ? value : (value && value[path]), expression[path]);
       
 25401             });
       
 25402           })(key);
       
 25403         }
       
 25404         break;
 25883         break;
 25405       case 'function':
 25884       case 'boolean':
 25406         predicates.push(expression);
 25885       case 'number':
       
 25886       case 'string':
       
 25887         matchAgainstAnyProp = true;
       
 25888         //jshint -W086
       
 25889       case 'object':
       
 25890         //jshint +W086
       
 25891         predicateFn = createPredicateFn(expression, comparator, matchAgainstAnyProp);
 25407         break;
 25892         break;
 25408       default:
 25893       default:
 25409         return array;
 25894         return array;
 25410     }
 25895     }
 25411     var filtered = [];
 25896 
 25412     for ( var j = 0; j < array.length; j++) {
 25897     return array.filter(predicateFn);
 25413       var value = array[j];
 25898   };
 25414       if (predicates.check(value, j)) {
 25899 }
 25415         filtered.push(value);
 25900 
       
 25901 // Helper functions for `filterFilter`
       
 25902 function createPredicateFn(expression, comparator, matchAgainstAnyProp) {
       
 25903   var shouldMatchPrimitives = isObject(expression) && ('$' in expression);
       
 25904   var predicateFn;
       
 25905 
       
 25906   if (comparator === true) {
       
 25907     comparator = equals;
       
 25908   } else if (!isFunction(comparator)) {
       
 25909     comparator = function(actual, expected) {
       
 25910       if (isObject(actual) || isObject(expected)) {
       
 25911         // Prevent an object to be considered equal to a string like `'[object'`
       
 25912         return false;
 25416       }
 25913       }
 25417     }
 25914 
 25418     return filtered;
 25915       actual = lowercase('' + actual);
       
 25916       expected = lowercase('' + expected);
       
 25917       return actual.indexOf(expected) !== -1;
       
 25918     };
       
 25919   }
       
 25920 
       
 25921   predicateFn = function(item) {
       
 25922     if (shouldMatchPrimitives && !isObject(item)) {
       
 25923       return deepCompare(item, expression.$, comparator, false);
       
 25924     }
       
 25925     return deepCompare(item, expression, comparator, matchAgainstAnyProp);
 25419   };
 25926   };
       
 25927 
       
 25928   return predicateFn;
       
 25929 }
       
 25930 
       
 25931 function deepCompare(actual, expected, comparator, matchAgainstAnyProp, dontMatchWholeObject) {
       
 25932   var actualType = typeof actual;
       
 25933   var expectedType = typeof expected;
       
 25934 
       
 25935   if ((expectedType === 'string') && (expected.charAt(0) === '!')) {
       
 25936     return !deepCompare(actual, expected.substring(1), comparator, matchAgainstAnyProp);
       
 25937   } else if (actualType === 'array') {
       
 25938     // In case `actual` is an array, consider it a match
       
 25939     // if ANY of it's items matches `expected`
       
 25940     return actual.some(function(item) {
       
 25941       return deepCompare(item, expected, comparator, matchAgainstAnyProp);
       
 25942     });
       
 25943   }
       
 25944 
       
 25945   switch (actualType) {
       
 25946     case 'object':
       
 25947       var key;
       
 25948       if (matchAgainstAnyProp) {
       
 25949         for (key in actual) {
       
 25950           if ((key.charAt(0) !== '$') && deepCompare(actual[key], expected, comparator, true)) {
       
 25951             return true;
       
 25952           }
       
 25953         }
       
 25954         return dontMatchWholeObject ? false : deepCompare(actual, expected, comparator, false);
       
 25955       } else if (expectedType === 'object') {
       
 25956         for (key in expected) {
       
 25957           var expectedVal = expected[key];
       
 25958           if (isFunction(expectedVal)) {
       
 25959             continue;
       
 25960           }
       
 25961 
       
 25962           var matchAnyProperty = key === '$';
       
 25963           var actualVal = matchAnyProperty ? actual : actual[key];
       
 25964           if (!deepCompare(actualVal, expectedVal, comparator, matchAnyProperty, matchAnyProperty)) {
       
 25965             return false;
       
 25966           }
       
 25967         }
       
 25968         return true;
       
 25969       } else {
       
 25970         return comparator(actual, expected);
       
 25971       }
       
 25972       break;
       
 25973     case 'function':
       
 25974       return false;
       
 25975     default:
       
 25976       return comparator(actual, expected);
       
 25977   }
 25420 }
 25978 }
 25421 
 25979 
 25422 /**
 25980 /**
 25423  * @ngdoc filter
 25981  * @ngdoc filter
 25424  * @name currency
 25982  * @name currency
 25428  * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default
 25986  * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default
 25429  * symbol for current locale is used.
 25987  * symbol for current locale is used.
 25430  *
 25988  *
 25431  * @param {number} amount Input to filter.
 25989  * @param {number} amount Input to filter.
 25432  * @param {string=} symbol Currency symbol or identifier to be displayed.
 25990  * @param {string=} symbol Currency symbol or identifier to be displayed.
       
 25991  * @param {number=} fractionSize Number of decimal places to round the amount to, defaults to default max fraction size for current locale
 25433  * @returns {string} Formatted number.
 25992  * @returns {string} Formatted number.
 25434  *
 25993  *
 25435  *
 25994  *
 25436  * @example
 25995  * @example
 25437    <example module="currencyExample">
 25996    <example module="currencyExample">
 25443            }]);
 26002            }]);
 25444        </script>
 26003        </script>
 25445        <div ng-controller="ExampleController">
 26004        <div ng-controller="ExampleController">
 25446          <input type="number" ng-model="amount"> <br>
 26005          <input type="number" ng-model="amount"> <br>
 25447          default currency symbol ($): <span id="currency-default">{{amount | currency}}</span><br>
 26006          default currency symbol ($): <span id="currency-default">{{amount | currency}}</span><br>
 25448          custom currency identifier (USD$): <span>{{amount | currency:"USD$"}}</span>
 26007          custom currency identifier (USD$): <span id="currency-custom">{{amount | currency:"USD$"}}</span>
       
 26008          no fractions (0): <span id="currency-no-fractions">{{amount | currency:"USD$":0}}</span>
 25449        </div>
 26009        </div>
 25450      </file>
 26010      </file>
 25451      <file name="protractor.js" type="protractor">
 26011      <file name="protractor.js" type="protractor">
 25452        it('should init with 1234.56', function() {
 26012        it('should init with 1234.56', function() {
 25453          expect(element(by.id('currency-default')).getText()).toBe('$1,234.56');
 26013          expect(element(by.id('currency-default')).getText()).toBe('$1,234.56');
 25454          expect(element(by.binding('amount | currency:"USD$"')).getText()).toBe('USD$1,234.56');
 26014          expect(element(by.id('currency-custom')).getText()).toBe('USD$1,234.56');
       
 26015          expect(element(by.id('currency-no-fractions')).getText()).toBe('USD$1,235');
 25455        });
 26016        });
 25456        it('should update', function() {
 26017        it('should update', function() {
 25457          if (browser.params.browser == 'safari') {
 26018          if (browser.params.browser == 'safari') {
 25458            // Safari does not understand the minus key. See
 26019            // Safari does not understand the minus key. See
 25459            // https://github.com/angular/protractor/issues/481
 26020            // https://github.com/angular/protractor/issues/481
 25460            return;
 26021            return;
 25461          }
 26022          }
 25462          element(by.model('amount')).clear();
 26023          element(by.model('amount')).clear();
 25463          element(by.model('amount')).sendKeys('-1234');
 26024          element(by.model('amount')).sendKeys('-1234');
 25464          expect(element(by.id('currency-default')).getText()).toBe('($1,234.00)');
 26025          expect(element(by.id('currency-default')).getText()).toBe('($1,234.00)');
 25465          expect(element(by.binding('amount | currency:"USD$"')).getText()).toBe('(USD$1,234.00)');
 26026          expect(element(by.id('currency-custom')).getText()).toBe('(USD$1,234.00)');
       
 26027          expect(element(by.id('currency-no-fractions')).getText()).toBe('(USD$1,234)');
 25466        });
 26028        });
 25467      </file>
 26029      </file>
 25468    </example>
 26030    </example>
 25469  */
 26031  */
 25470 currencyFilter.$inject = ['$locale'];
 26032 currencyFilter.$inject = ['$locale'];
 25471 function currencyFilter($locale) {
 26033 function currencyFilter($locale) {
 25472   var formats = $locale.NUMBER_FORMATS;
 26034   var formats = $locale.NUMBER_FORMATS;
 25473   return function(amount, currencySymbol){
 26035   return function(amount, currencySymbol, fractionSize) {
 25474     if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;
 26036     if (isUndefined(currencySymbol)) {
       
 26037       currencySymbol = formats.CURRENCY_SYM;
       
 26038     }
       
 26039 
       
 26040     if (isUndefined(fractionSize)) {
       
 26041       fractionSize = formats.PATTERNS[1].maxFrac;
       
 26042     }
 25475 
 26043 
 25476     // if null or undefined pass it through
 26044     // if null or undefined pass it through
 25477     return (amount == null)
 26045     return (amount == null)
 25478         ? amount
 26046         ? amount
 25479         : formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).
 26047         : formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, fractionSize).
 25480             replace(/\u00A4/g, currencySymbol);
 26048             replace(/\u00A4/g, currencySymbol);
 25481   };
 26049   };
 25482 }
 26050 }
 25483 
 26051 
 25484 /**
 26052 /**
 25557 
 26125 
 25558   var hasExponent = false;
 26126   var hasExponent = false;
 25559   if (numStr.indexOf('e') !== -1) {
 26127   if (numStr.indexOf('e') !== -1) {
 25560     var match = numStr.match(/([\d\.]+)e(-?)(\d+)/);
 26128     var match = numStr.match(/([\d\.]+)e(-?)(\d+)/);
 25561     if (match && match[2] == '-' && match[3] > fractionSize + 1) {
 26129     if (match && match[2] == '-' && match[3] > fractionSize + 1) {
 25562       numStr = '0';
       
 25563       number = 0;
 26130       number = 0;
 25564     } else {
 26131     } else {
 25565       formatedText = numStr;
 26132       formatedText = numStr;
 25566       hasExponent = true;
 26133       hasExponent = true;
 25567     }
 26134     }
 25578     // safely round numbers in JS without hitting imprecisions of floating-point arithmetics
 26145     // safely round numbers in JS without hitting imprecisions of floating-point arithmetics
 25579     // inspired by:
 26146     // inspired by:
 25580     // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round
 26147     // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round
 25581     number = +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize);
 26148     number = +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize);
 25582 
 26149 
 25583     if (number === 0) {
       
 25584       isNegative = false;
       
 25585     }
       
 25586 
       
 25587     var fraction = ('' + number).split(DECIMAL_SEP);
 26150     var fraction = ('' + number).split(DECIMAL_SEP);
 25588     var whole = fraction[0];
 26151     var whole = fraction[0];
 25589     fraction = fraction[1] || '';
 26152     fraction = fraction[1] || '';
 25590 
 26153 
 25591     var i, pos = 0,
 26154     var i, pos = 0,
 25593         group = pattern.gSize;
 26156         group = pattern.gSize;
 25594 
 26157 
 25595     if (whole.length >= (lgroup + group)) {
 26158     if (whole.length >= (lgroup + group)) {
 25596       pos = whole.length - lgroup;
 26159       pos = whole.length - lgroup;
 25597       for (i = 0; i < pos; i++) {
 26160       for (i = 0; i < pos; i++) {
 25598         if ((pos - i)%group === 0 && i !== 0) {
 26161         if ((pos - i) % group === 0 && i !== 0) {
 25599           formatedText += groupSep;
 26162           formatedText += groupSep;
 25600         }
 26163         }
 25601         formatedText += whole.charAt(i);
 26164         formatedText += whole.charAt(i);
 25602       }
 26165       }
 25603     }
 26166     }
 25604 
 26167 
 25605     for (i = pos; i < whole.length; i++) {
 26168     for (i = pos; i < whole.length; i++) {
 25606       if ((whole.length - i)%lgroup === 0 && i !== 0) {
 26169       if ((whole.length - i) % lgroup === 0 && i !== 0) {
 25607         formatedText += groupSep;
 26170         formatedText += groupSep;
 25608       }
 26171       }
 25609       formatedText += whole.charAt(i);
 26172       formatedText += whole.charAt(i);
 25610     }
 26173     }
 25611 
 26174 
 25612     // format fraction part.
 26175     // format fraction part.
 25613     while(fraction.length < fractionSize) {
 26176     while (fraction.length < fractionSize) {
 25614       fraction += '0';
 26177       fraction += '0';
 25615     }
 26178     }
 25616 
 26179 
 25617     if (fractionSize && fractionSize !== "0") formatedText += decimalSep + fraction.substr(0, fractionSize);
 26180     if (fractionSize && fractionSize !== "0") formatedText += decimalSep + fraction.substr(0, fractionSize);
 25618   } else {
 26181   } else {
 25619 
 26182     if (fractionSize > 0 && number < 1) {
 25620     if (fractionSize > 0 && number > -1 && number < 1) {
       
 25621       formatedText = number.toFixed(fractionSize);
 26183       formatedText = number.toFixed(fractionSize);
       
 26184       number = parseFloat(formatedText);
 25622     }
 26185     }
 25623   }
 26186   }
 25624 
 26187 
 25625   parts.push(isNegative ? pattern.negPre : pattern.posPre);
 26188   if (number === 0) {
 25626   parts.push(formatedText);
 26189     isNegative = false;
 25627   parts.push(isNegative ? pattern.negSuf : pattern.posSuf);
 26190   }
       
 26191 
       
 26192   parts.push(isNegative ? pattern.negPre : pattern.posPre,
       
 26193              formatedText,
       
 26194              isNegative ? pattern.negSuf : pattern.posSuf);
 25628   return parts.join('');
 26195   return parts.join('');
 25629 }
 26196 }
 25630 
 26197 
 25631 function padNumber(num, digits, trim) {
 26198 function padNumber(num, digits, trim) {
 25632   var neg = '';
 26199   var neg = '';
 25633   if (num < 0) {
 26200   if (num < 0) {
 25634     neg =  '-';
 26201     neg =  '-';
 25635     num = -num;
 26202     num = -num;
 25636   }
 26203   }
 25637   num = '' + num;
 26204   num = '' + num;
 25638   while(num.length < digits) num = '0' + num;
 26205   while (num.length < digits) num = '0' + num;
 25639   if (trim)
 26206   if (trim)
 25640     num = num.substr(num.length - digits);
 26207     num = num.substr(num.length - digits);
 25641   return neg + num;
 26208   return neg + num;
 25642 }
 26209 }
 25643 
 26210 
 25646   offset = offset || 0;
 26213   offset = offset || 0;
 25647   return function(date) {
 26214   return function(date) {
 25648     var value = date['get' + name]();
 26215     var value = date['get' + name]();
 25649     if (offset > 0 || value > -offset)
 26216     if (offset > 0 || value > -offset)
 25650       value += offset;
 26217       value += offset;
 25651     if (value === 0 && offset == -12 ) value = 12;
 26218     if (value === 0 && offset == -12) value = 12;
 25652     return padNumber(value, size, trim);
 26219     return padNumber(value, size, trim);
 25653   };
 26220   };
 25654 }
 26221 }
 25655 
 26222 
 25656 function dateStrGetter(name, shortForm) {
 26223 function dateStrGetter(name, shortForm) {
 25764  *   * `'ss'`: Second in minute, padded (00-59)
 26331  *   * `'ss'`: Second in minute, padded (00-59)
 25765  *   * `'s'`: Second in minute (0-59)
 26332  *   * `'s'`: Second in minute (0-59)
 25766  *   * `'.sss' or ',sss'`: Millisecond in second, padded (000-999)
 26333  *   * `'.sss' or ',sss'`: Millisecond in second, padded (000-999)
 25767  *   * `'a'`: AM/PM marker
 26334  *   * `'a'`: AM/PM marker
 25768  *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200)
 26335  *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200)
 25769  *   * `'ww'`: ISO-8601 week of year (00-53)
 26336  *   * `'ww'`: Week of year, padded (00-53). Week 01 is the week with the first Thursday of the year
 25770  *   * `'w'`: ISO-8601 week of year (0-53)
 26337  *   * `'w'`: Week of year (0-53). Week 1 is the week with the first Thursday of the year
 25771  *
 26338  *
 25772  *   `format` string can also be one of the following predefined
 26339  *   `format` string can also be one of the following predefined
 25773  *   {@link guide/i18n localizable formats}:
 26340  *   {@link guide/i18n localizable formats}:
 25774  *
 26341  *
 25775  *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale
 26342  *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale
 25841       if (match[9]) {
 26408       if (match[9]) {
 25842         tzHour = int(match[9] + match[10]);
 26409         tzHour = int(match[9] + match[10]);
 25843         tzMin = int(match[9] + match[11]);
 26410         tzMin = int(match[9] + match[11]);
 25844       }
 26411       }
 25845       dateSetter.call(date, int(match[1]), int(match[2]) - 1, int(match[3]));
 26412       dateSetter.call(date, int(match[1]), int(match[2]) - 1, int(match[3]));
 25846       var h = int(match[4]||0) - tzHour;
 26413       var h = int(match[4] || 0) - tzHour;
 25847       var m = int(match[5]||0) - tzMin;
 26414       var m = int(match[5] || 0) - tzMin;
 25848       var s = int(match[6]||0);
 26415       var s = int(match[6] || 0);
 25849       var ms = Math.round(parseFloat('0.' + (match[7]||0)) * 1000);
 26416       var ms = Math.round(parseFloat('0.' + (match[7] || 0)) * 1000);
 25850       timeSetter.call(date, h, m, s, ms);
 26417       timeSetter.call(date, h, m, s, ms);
 25851       return date;
 26418       return date;
 25852     }
 26419     }
 25853     return string;
 26420     return string;
 25854   }
 26421   }
 25871 
 26438 
 25872     if (!isDate(date)) {
 26439     if (!isDate(date)) {
 25873       return date;
 26440       return date;
 25874     }
 26441     }
 25875 
 26442 
 25876     while(format) {
 26443     while (format) {
 25877       match = DATE_FORMATS_SPLIT.exec(format);
 26444       match = DATE_FORMATS_SPLIT.exec(format);
 25878       if (match) {
 26445       if (match) {
 25879         parts = concat(parts, match, 1);
 26446         parts = concat(parts, match, 1);
 25880         format = parts.pop();
 26447         format = parts.pop();
 25881       } else {
 26448       } else {
 25886 
 26453 
 25887     if (timezone && timezone === 'UTC') {
 26454     if (timezone && timezone === 'UTC') {
 25888       date = new Date(date.getTime());
 26455       date = new Date(date.getTime());
 25889       date.setMinutes(date.getMinutes() + date.getTimezoneOffset());
 26456       date.setMinutes(date.getMinutes() + date.getTimezoneOffset());
 25890     }
 26457     }
 25891     forEach(parts, function(value){
 26458     forEach(parts, function(value) {
 25892       fn = DATE_FORMATS[value];
 26459       fn = DATE_FORMATS[value];
 25893       text += fn ? fn(date, $locale.DATETIME_FORMATS)
 26460       text += fn ? fn(date, $locale.DATETIME_FORMATS)
 25894                  : value.replace(/(^'|'$)/g, '').replace(/''/g, "'");
 26461                  : value.replace(/(^'|'$)/g, '').replace(/''/g, "'");
 25895     });
 26462     });
 25896 
 26463 
 25909  *
 26476  *
 25910  *   This filter is mostly useful for debugging. When using the double curly {{value}} notation
 26477  *   This filter is mostly useful for debugging. When using the double curly {{value}} notation
 25911  *   the binding is automatically converted to JSON.
 26478  *   the binding is automatically converted to JSON.
 25912  *
 26479  *
 25913  * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.
 26480  * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.
       
 26481  * @param {number=} spacing The number of spaces to use per indentation, defaults to 2.
 25914  * @returns {string} JSON string.
 26482  * @returns {string} JSON string.
 25915  *
 26483  *
 25916  *
 26484  *
 25917  * @example
 26485  * @example
 25918    <example>
 26486    <example>
 25919      <file name="index.html">
 26487      <file name="index.html">
 25920        <pre>{{ {'name':'value'} | json }}</pre>
 26488        <pre id="default-spacing">{{ {'name':'value'} | json }}</pre>
       
 26489        <pre id="custom-spacing">{{ {'name':'value'} | json:4 }}</pre>
 25921      </file>
 26490      </file>
 25922      <file name="protractor.js" type="protractor">
 26491      <file name="protractor.js" type="protractor">
 25923        it('should jsonify filtered objects', function() {
 26492        it('should jsonify filtered objects', function() {
 25924          expect(element(by.binding("{'name':'value'}")).getText()).toMatch(/\{\n  "name": ?"value"\n}/);
 26493          expect(element(by.id('default-spacing')).getText()).toMatch(/\{\n  "name": ?"value"\n}/);
       
 26494          expect(element(by.id('custom-spacing')).getText()).toMatch(/\{\n    "name": ?"value"\n}/);
 25925        });
 26495        });
 25926      </file>
 26496      </file>
 25927    </example>
 26497    </example>
 25928  *
 26498  *
 25929  */
 26499  */
 25930 function jsonFilter() {
 26500 function jsonFilter() {
 25931   return function(object) {
 26501   return function(object, spacing) {
 25932     return toJson(object, true);
 26502     if (isUndefined(spacing)) {
       
 26503         spacing = 2;
       
 26504     }
       
 26505     return toJson(object, spacing);
 25933   };
 26506   };
 25934 }
 26507 }
 25935 
 26508 
 25936 
 26509 
 25937 /**
 26510 /**
 25991        <div ng-controller="ExampleController">
 26564        <div ng-controller="ExampleController">
 25992          Limit {{numbers}} to: <input type="number" step="1" ng-model="numLimit">
 26565          Limit {{numbers}} to: <input type="number" step="1" ng-model="numLimit">
 25993          <p>Output numbers: {{ numbers | limitTo:numLimit }}</p>
 26566          <p>Output numbers: {{ numbers | limitTo:numLimit }}</p>
 25994          Limit {{letters}} to: <input type="number" step="1" ng-model="letterLimit">
 26567          Limit {{letters}} to: <input type="number" step="1" ng-model="letterLimit">
 25995          <p>Output letters: {{ letters | limitTo:letterLimit }}</p>
 26568          <p>Output letters: {{ letters | limitTo:letterLimit }}</p>
 25996          Limit {{longNumber}} to: <input type="integer" ng-model="longNumberLimit">
 26569          Limit {{longNumber}} to: <input type="number" step="1" ng-model="longNumberLimit">
 25997          <p>Output long number: {{ longNumber | limitTo:longNumberLimit }}</p>
 26570          <p>Output long number: {{ longNumber | limitTo:longNumberLimit }}</p>
 25998        </div>
 26571        </div>
 25999      </file>
 26572      </file>
 26000      <file name="protractor.js" type="protractor">
 26573      <file name="protractor.js" type="protractor">
 26001        var numLimitInput = element(by.model('numLimit'));
 26574        var numLimitInput = element(by.model('numLimit'));
 26039          expect(limitedLongNumber.getText()).toEqual('Output long number: 2345432342');
 26612          expect(limitedLongNumber.getText()).toEqual('Output long number: 2345432342');
 26040        });
 26613        });
 26041      </file>
 26614      </file>
 26042    </example>
 26615    </example>
 26043 */
 26616 */
 26044 function limitToFilter(){
 26617 function limitToFilter() {
 26045   return function(input, limit) {
 26618   return function(input, limit) {
 26046     if (isNumber(input)) input = input.toString();
 26619     if (isNumber(input)) input = input.toString();
 26047     if (!isArray(input) && !isString(input)) return input;
 26620     if (!isArray(input) && !isString(input)) return input;
 26048 
 26621 
 26049     if (Math.abs(Number(limit)) === Infinity) {
 26622     if (Math.abs(Number(limit)) === Infinity) {
 26059       } else {
 26632       } else {
 26060         return "";
 26633         return "";
 26061       }
 26634       }
 26062     }
 26635     }
 26063 
 26636 
 26064     var out = [],
 26637     var i, n;
 26065       i, n;
       
 26066 
 26638 
 26067     // if abs(limit) exceeds maximum length, trim it
 26639     // if abs(limit) exceeds maximum length, trim it
 26068     if (limit > input.length)
 26640     if (limit > input.length)
 26069       limit = input.length;
 26641       limit = input.length;
 26070     else if (limit < -input.length)
 26642     else if (limit < -input.length)
 26072 
 26644 
 26073     if (limit > 0) {
 26645     if (limit > 0) {
 26074       i = 0;
 26646       i = 0;
 26075       n = limit;
 26647       n = limit;
 26076     } else {
 26648     } else {
       
 26649       // zero and NaN check on limit - return empty array
       
 26650       if (!limit) return [];
       
 26651 
 26077       i = input.length + limit;
 26652       i = input.length + limit;
 26078       n = input.length;
 26653       n = input.length;
 26079     }
 26654     }
 26080 
 26655 
 26081     for (; i<n; i++) {
 26656     return input.slice(i, n);
 26082       out.push(input[i]);
       
 26083     }
       
 26084 
       
 26085     return out;
       
 26086   };
 26657   };
 26087 }
 26658 }
 26088 
 26659 
 26089 /**
 26660 /**
 26090  * @ngdoc filter
 26661  * @ngdoc filter
 26200         }]);
 26771         }]);
 26201     </file>
 26772     </file>
 26202 </example>
 26773 </example>
 26203  */
 26774  */
 26204 orderByFilter.$inject = ['$parse'];
 26775 orderByFilter.$inject = ['$parse'];
 26205 function orderByFilter($parse){
 26776 function orderByFilter($parse) {
 26206   return function(array, sortPredicate, reverseOrder) {
 26777   return function(array, sortPredicate, reverseOrder) {
 26207     if (!(isArrayLike(array))) return array;
 26778     if (!(isArrayLike(array))) return array;
 26208     sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];
 26779     sortPredicate = isArray(sortPredicate) ? sortPredicate : [sortPredicate];
 26209     if (sortPredicate.length === 0) { sortPredicate = ['+']; }
 26780     if (sortPredicate.length === 0) { sortPredicate = ['+']; }
 26210     sortPredicate = sortPredicate.map(function(predicate){
 26781     sortPredicate = sortPredicate.map(function(predicate) {
 26211       var descending = false, get = predicate || identity;
 26782       var descending = false, get = predicate || identity;
 26212       if (isString(predicate)) {
 26783       if (isString(predicate)) {
 26213         if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {
 26784         if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {
 26214           descending = predicate.charAt(0) == '-';
 26785           descending = predicate.charAt(0) == '-';
 26215           predicate = predicate.substring(1);
 26786           predicate = predicate.substring(1);
 26216         }
 26787         }
 26217         if ( predicate === '' ) {
 26788         if (predicate === '') {
 26218           // Effectively no predicate was passed so we compare identity
 26789           // Effectively no predicate was passed so we compare identity
 26219           return reverseComparator(function(a,b) {
 26790           return reverseComparator(compare, descending);
 26220             return compare(a, b);
       
 26221           }, descending);
       
 26222         }
 26791         }
 26223         get = $parse(predicate);
 26792         get = $parse(predicate);
 26224         if (get.constant) {
 26793         if (get.constant) {
 26225           var key = get();
 26794           var key = get();
 26226           return reverseComparator(function(a,b) {
 26795           return reverseComparator(function(a, b) {
 26227             return compare(a[key], b[key]);
 26796             return compare(a[key], b[key]);
 26228           }, descending);
 26797           }, descending);
 26229         }
 26798         }
 26230       }
 26799       }
 26231       return reverseComparator(function(a,b){
 26800       return reverseComparator(function(a, b) {
 26232         return compare(get(a),get(b));
 26801         return compare(get(a),get(b));
 26233       }, descending);
 26802       }, descending);
 26234     });
 26803     });
 26235     var arrayCopy = [];
 26804     return slice.call(array).sort(reverseComparator(comparator, reverseOrder));
 26236     for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }
 26805 
 26237     return arrayCopy.sort(reverseComparator(comparator, reverseOrder));
 26806     function comparator(o1, o2) {
 26238 
 26807       for (var i = 0; i < sortPredicate.length; i++) {
 26239     function comparator(o1, o2){
       
 26240       for ( var i = 0; i < sortPredicate.length; i++) {
       
 26241         var comp = sortPredicate[i](o1, o2);
 26808         var comp = sortPredicate[i](o1, o2);
 26242         if (comp !== 0) return comp;
 26809         if (comp !== 0) return comp;
 26243       }
 26810       }
 26244       return 0;
 26811       return 0;
 26245     }
 26812     }
 26246     function reverseComparator(comp, descending) {
 26813     function reverseComparator(comp, descending) {
 26247       return descending
 26814       return descending
 26248           ? function(a,b){return comp(b,a);}
 26815           ? function(a, b) {return comp(b,a);}
 26249           : comp;
 26816           : comp;
 26250     }
 26817     }
 26251     function compare(v1, v2){
 26818 
       
 26819     function isPrimitive(value) {
       
 26820       switch (typeof value) {
       
 26821         case 'number': /* falls through */
       
 26822         case 'boolean': /* falls through */
       
 26823         case 'string':
       
 26824           return true;
       
 26825         default:
       
 26826           return false;
       
 26827       }
       
 26828     }
       
 26829 
       
 26830     function objectToString(value) {
       
 26831       if (value === null) return 'null';
       
 26832       if (typeof value.valueOf === 'function') {
       
 26833         value = value.valueOf();
       
 26834         if (isPrimitive(value)) return value;
       
 26835       }
       
 26836       if (typeof value.toString === 'function') {
       
 26837         value = value.toString();
       
 26838         if (isPrimitive(value)) return value;
       
 26839       }
       
 26840       return '';
       
 26841     }
       
 26842 
       
 26843     function compare(v1, v2) {
 26252       var t1 = typeof v1;
 26844       var t1 = typeof v1;
 26253       var t2 = typeof v2;
 26845       var t2 = typeof v2;
 26254       if (t1 == t2) {
 26846       if (t1 === t2 && t1 === "object") {
 26255         if (isDate(v1) && isDate(v2)) {
 26847         v1 = objectToString(v1);
 26256           v1 = v1.valueOf();
 26848         v2 = objectToString(v2);
 26257           v2 = v2.valueOf();
 26849       }
 26258         }
 26850       if (t1 === t2) {
 26259         if (t1 == "string") {
 26851         if (t1 === "string") {
 26260            v1 = v1.toLowerCase();
 26852            v1 = v1.toLowerCase();
 26261            v2 = v2.toLowerCase();
 26853            v2 = v2.toLowerCase();
 26262         }
 26854         }
 26263         if (v1 === v2) return 0;
 26855         if (v1 === v2) return 0;
 26264         return v1 < v2 ? -1 : 1;
 26856         return v1 < v2 ? -1 : 1;
 26298     if (!attr.href && !attr.xlinkHref && !attr.name) {
 26890     if (!attr.href && !attr.xlinkHref && !attr.name) {
 26299       return function(scope, element) {
 26891       return function(scope, element) {
 26300         // SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute.
 26892         // SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute.
 26301         var href = toString.call(element.prop('href')) === '[object SVGAnimatedString]' ?
 26893         var href = toString.call(element.prop('href')) === '[object SVGAnimatedString]' ?
 26302                    'xlink:href' : 'href';
 26894                    'xlink:href' : 'href';
 26303         element.on('click', function(event){
 26895         element.on('click', function(event) {
 26304           // if we have no href url, then don't navigate anywhere.
 26896           // if we have no href url, then don't navigate anywhere.
 26305           if (!element.attr(href)) {
 26897           if (!element.attr(href)) {
 26306             event.preventDefault();
 26898             event.preventDefault();
 26307           }
 26899           }
 26308         });
 26900         });
 26320  * @description
 26912  * @description
 26321  * Using Angular markup like `{{hash}}` in an href attribute will
 26913  * Using Angular markup like `{{hash}}` in an href attribute will
 26322  * make the link go to the wrong URL if the user clicks it before
 26914  * make the link go to the wrong URL if the user clicks it before
 26323  * Angular has a chance to replace the `{{hash}}` markup with its
 26915  * Angular has a chance to replace the `{{hash}}` markup with its
 26324  * value. Until Angular replaces the markup the link will be broken
 26916  * value. Until Angular replaces the markup the link will be broken
 26325  * and will most likely return a 404 error.
 26917  * and will most likely return a 404 error. The `ngHref` directive
 26326  *
 26918  * solves this problem.
 26327  * The `ngHref` directive solves this problem.
       
 26328  *
 26919  *
 26329  * The wrong way to write it:
 26920  * The wrong way to write it:
 26330  * ```html
 26921  * ```html
 26331  * <a href="http://www.gravatar.com/avatar/{{hash}}">link1</a>
 26922  * <a href="http://www.gravatar.com/avatar/{{hash}}">link1</a>
 26332  * ```
 26923  * ```
 26777  *  - `minlength`
 27368  *  - `minlength`
 26778  *  - `number`
 27369  *  - `number`
 26779  *  - `pattern`
 27370  *  - `pattern`
 26780  *  - `required`
 27371  *  - `required`
 26781  *  - `url`
 27372  *  - `url`
       
 27373  *  - `date`
       
 27374  *  - `datetimelocal`
       
 27375  *  - `time`
       
 27376  *  - `week`
       
 27377  *  - `month`
 26782  *
 27378  *
 26783  * @description
 27379  * @description
 26784  * `FormController` keeps track of all its controls and nested forms as well as the state of them,
 27380  * `FormController` keeps track of all its controls and nested forms as well as the state of them,
 26785  * such as being valid/invalid or dirty/pristine.
 27381  * such as being valid/invalid or dirty/pristine.
 26786  *
 27382  *
 26965    * in this form.
 27561    * in this form.
 26966    *
 27562    *
 26967    * Setting a form back to a pristine state is often useful when we want to 'reuse' a form after
 27563    * Setting a form back to a pristine state is often useful when we want to 'reuse' a form after
 26968    * saving or resetting it.
 27564    * saving or resetting it.
 26969    */
 27565    */
 26970   form.$setPristine = function () {
 27566   form.$setPristine = function() {
 26971     $animate.setClass(element, PRISTINE_CLASS, DIRTY_CLASS + ' ' + SUBMITTED_CLASS);
 27567     $animate.setClass(element, PRISTINE_CLASS, DIRTY_CLASS + ' ' + SUBMITTED_CLASS);
 26972     form.$dirty = false;
 27568     form.$dirty = false;
 26973     form.$pristine = true;
 27569     form.$pristine = true;
 26974     form.$submitted = false;
 27570     form.$submitted = false;
 26975     forEach(controls, function(control) {
 27571     forEach(controls, function(control) {
 26988    * untouched state (ng-untouched class).
 27584    * untouched state (ng-untouched class).
 26989    *
 27585    *
 26990    * Setting a form controls back to their untouched state is often useful when setting the form
 27586    * Setting a form controls back to their untouched state is often useful when setting the form
 26991    * back to its pristine state.
 27587    * back to its pristine state.
 26992    */
 27588    */
 26993   form.$setUntouched = function () {
 27589   form.$setUntouched = function() {
 26994     forEach(controls, function(control) {
 27590     forEach(controls, function(control) {
 26995       control.$setUntouched();
 27591       control.$setUntouched();
 26996     });
 27592     });
 26997   };
 27593   };
 26998 
 27594 
 27001    * @name form.FormController#$setSubmitted
 27597    * @name form.FormController#$setSubmitted
 27002    *
 27598    *
 27003    * @description
 27599    * @description
 27004    * Sets the form to its submitted state.
 27600    * Sets the form to its submitted state.
 27005    */
 27601    */
 27006   form.$setSubmitted = function () {
 27602   form.$setSubmitted = function() {
 27007     $animate.addClass(element, SUBMITTED_CLASS);
 27603     $animate.addClass(element, SUBMITTED_CLASS);
 27008     form.$submitted = true;
 27604     form.$submitted = true;
 27009     parentForm.$setSubmitted();
 27605     parentForm.$setSubmitted();
 27010   };
 27606   };
 27011 }
 27607 }
 27199                 scope.$apply(function() {
 27795                 scope.$apply(function() {
 27200                   controller.$commitViewValue();
 27796                   controller.$commitViewValue();
 27201                   controller.$setSubmitted();
 27797                   controller.$setSubmitted();
 27202                 });
 27798                 });
 27203 
 27799 
 27204                 event.preventDefault
 27800                 event.preventDefault();
 27205                   ? event.preventDefault()
       
 27206                   : event.returnValue = false; // IE
       
 27207               };
 27801               };
 27208 
 27802 
 27209               addEventListenerFn(formElement[0], 'submit', handleFormSubmission);
 27803               addEventListenerFn(formElement[0], 'submit', handleFormSubmission);
 27210 
 27804 
 27211               // unregister the preventDefault listener so that we don't not leak memory but in a
 27805               // unregister the preventDefault listener so that we don't not leak memory but in a
 27228                 alias = newValue;
 27822                 alias = newValue;
 27229                 setter(scope, alias, controller, alias);
 27823                 setter(scope, alias, controller, alias);
 27230                 parentFormCtrl.$$renameControl(controller, alias);
 27824                 parentFormCtrl.$$renameControl(controller, alias);
 27231               });
 27825               });
 27232             }
 27826             }
 27233             if (parentFormCtrl !== nullFormCtrl) {
 27827             formElement.on('$destroy', function() {
 27234               formElement.on('$destroy', function() {
 27828               parentFormCtrl.$removeControl(controller);
 27235                 parentFormCtrl.$removeControl(controller);
 27829               if (alias) {
 27236                 if (alias) {
 27830                 setter(scope, alias, undefined, alias);
 27237                   setter(scope, alias, undefined, alias);
 27831               }
 27238                 }
 27832               extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards
 27239                 extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards
 27833             });
 27240               });
       
 27241             }
       
 27242           }
 27834           }
 27243         };
 27835         };
 27244       }
 27836       }
 27245     };
 27837     };
 27246 
 27838 
 27280    * @name input[text]
 27872    * @name input[text]
 27281    *
 27873    *
 27282    * @description
 27874    * @description
 27283    * Standard HTML text input with angular data binding, inherited by most of the `input` elements.
 27875    * Standard HTML text input with angular data binding, inherited by most of the `input` elements.
 27284    *
 27876    *
 27285    * *NOTE* Not every feature offered is available for all input types.
       
 27286    *
 27877    *
 27287    * @param {string} ngModel Assignable angular expression to data-bind to.
 27878    * @param {string} ngModel Assignable angular expression to data-bind to.
 27288    * @param {string=} name Property name of the form under which the control is published.
 27879    * @param {string=} name Property name of the form under which the control is published.
 27289    * @param {string=} required Adds `required` validation error key if the value is not entered.
 27880    * @param {string=} required Adds `required` validation error key if the value is not entered.
 27290    * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
 27881    * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
 27291    *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
 27882    *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
 27292    *    `required` when you want to data-bind to the `required` attribute.
 27883    *    `required` when you want to data-bind to the `required` attribute.
 27293    * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
 27884    * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
 27294    *    minlength.
 27885    *    minlength.
 27295    * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
 27886    * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
 27296    *    maxlength.
 27887    *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of
 27297    * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
 27888    *    any length.
 27298    *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
 27889    * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
 27299    *    patterns defined as scope expressions.
 27890    *    that contains the regular expression body that will be converted to a regular expression
       
 27891    *    as in the ngPattern directive.
       
 27892    * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
       
 27893    *    a RegExp found by evaluating the Angular expression given in the attribute value.
       
 27894    *    If the expression evaluates to a RegExp object then this is used directly.
       
 27895    *    If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$`
       
 27896    *    characters. For instance, `"abc"` will be converted to `new RegExp('^abc$')`.
 27300    * @param {string=} ngChange Angular expression to be executed when input changes due to user
 27897    * @param {string=} ngChange Angular expression to be executed when input changes due to user
 27301    *    interaction with the input element.
 27898    *    interaction with the input element.
 27302    * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.
 27899    * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.
 27303    *    This parameter is ignored for input[type=password] controls, which will never trim the
 27900    *    This parameter is ignored for input[type=password] controls, which will never trim the
 27304    *    input.
 27901    *    input.
 27364      * @description
 27961      * @description
 27365      * Input with date validation and transformation. In browsers that do not yet support
 27962      * Input with date validation and transformation. In browsers that do not yet support
 27366      * the HTML5 date input, a text element will be used. In that case, text must be entered in a valid ISO-8601
 27963      * the HTML5 date input, a text element will be used. In that case, text must be entered in a valid ISO-8601
 27367      * date format (yyyy-MM-dd), for example: `2009-01-06`. Since many
 27964      * date format (yyyy-MM-dd), for example: `2009-01-06`. Since many
 27368      * modern browsers do not yet support this input type, it is important to provide cues to users on the
 27965      * modern browsers do not yet support this input type, it is important to provide cues to users on the
 27369      * expected input format via a placeholder or label. The model must always be a Date object.
 27966      * expected input format via a placeholder or label.
       
 27967      *
       
 27968      * The model must always be a Date object, otherwise Angular will throw an error.
       
 27969      * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
 27370      *
 27970      *
 27371      * The timezone to be used to read/write the `Date` instance in the model can be defined using
 27971      * The timezone to be used to read/write the `Date` instance in the model can be defined using
 27372      * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
 27972      * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
 27373      *
 27973      *
 27374      * @param {string} ngModel Assignable angular expression to data-bind to.
 27974      * @param {string} ngModel Assignable angular expression to data-bind to.
 27447          createDateParser(DATE_REGEXP, ['yyyy', 'MM', 'dd']),
 28047          createDateParser(DATE_REGEXP, ['yyyy', 'MM', 'dd']),
 27448          'yyyy-MM-dd'),
 28048          'yyyy-MM-dd'),
 27449 
 28049 
 27450    /**
 28050    /**
 27451     * @ngdoc input
 28051     * @ngdoc input
 27452     * @name input[dateTimeLocal]
 28052     * @name input[datetime-local]
 27453     *
 28053     *
 27454     * @description
 28054     * @description
 27455     * Input with datetime validation and transformation. In browsers that do not yet support
 28055     * Input with datetime validation and transformation. In browsers that do not yet support
 27456     * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
 28056     * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
 27457     * local datetime format (yyyy-MM-ddTHH:mm:ss), for example: `2010-12-28T14:57:00`. The model must be a Date object.
 28057     * local datetime format (yyyy-MM-ddTHH:mm:ss), for example: `2010-12-28T14:57:00`.
       
 28058     *
       
 28059     * The model must always be a Date object, otherwise Angular will throw an error.
       
 28060     * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
 27458     *
 28061     *
 27459     * The timezone to be used to read/write the `Date` instance in the model can be defined using
 28062     * The timezone to be used to read/write the `Date` instance in the model can be defined using
 27460     * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
 28063     * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
 27461     *
 28064     *
 27462     * @param {string} ngModel Assignable angular expression to data-bind to.
 28065     * @param {string} ngModel Assignable angular expression to data-bind to.
 27543    * Input with time validation and transformation. In browsers that do not yet support
 28146    * Input with time validation and transformation. In browsers that do not yet support
 27544    * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
 28147    * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
 27545    * local time format (HH:mm:ss), for example: `14:57:00`. Model must be a Date object. This binding will always output a
 28148    * local time format (HH:mm:ss), for example: `14:57:00`. Model must be a Date object. This binding will always output a
 27546    * Date object to the model of January 1, 1970, or local date `new Date(1970, 0, 1, HH, mm, ss)`.
 28149    * Date object to the model of January 1, 1970, or local date `new Date(1970, 0, 1, HH, mm, ss)`.
 27547    *
 28150    *
       
 28151    * The model must always be a Date object, otherwise Angular will throw an error.
       
 28152    * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
       
 28153    *
 27548    * The timezone to be used to read/write the `Date` instance in the model can be defined using
 28154    * The timezone to be used to read/write the `Date` instance in the model can be defined using
 27549    * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
 28155    * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
 27550    *
 28156    *
 27551    * @param {string} ngModel Assignable angular expression to data-bind to.
 28157    * @param {string} ngModel Assignable angular expression to data-bind to.
 27552    * @param {string=} name Property name of the form under which the control is published.
 28158    * @param {string=} name Property name of the form under which the control is published.
 27629     * @name input[week]
 28235     * @name input[week]
 27630     *
 28236     *
 27631     * @description
 28237     * @description
 27632     * Input with week-of-the-year validation and transformation to Date. In browsers that do not yet support
 28238     * Input with week-of-the-year validation and transformation to Date. In browsers that do not yet support
 27633     * the HTML5 week input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
 28239     * the HTML5 week input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
 27634     * week format (yyyy-W##), for example: `2013-W02`. The model must always be a Date object.
 28240     * week format (yyyy-W##), for example: `2013-W02`.
       
 28241     *
       
 28242     * The model must always be a Date object, otherwise Angular will throw an error.
       
 28243     * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
 27635     *
 28244     *
 27636     * The timezone to be used to read/write the `Date` instance in the model can be defined using
 28245     * The timezone to be used to read/write the `Date` instance in the model can be defined using
 27637     * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
 28246     * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
 27638     *
 28247     *
 27639     * @param {string} ngModel Assignable angular expression to data-bind to.
 28248     * @param {string} ngModel Assignable angular expression to data-bind to.
 27715    * @name input[month]
 28324    * @name input[month]
 27716    *
 28325    *
 27717    * @description
 28326    * @description
 27718    * Input with month validation and transformation. In browsers that do not yet support
 28327    * Input with month validation and transformation. In browsers that do not yet support
 27719    * the HTML5 month input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
 28328    * the HTML5 month input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
 27720    * month format (yyyy-MM), for example: `2009-01`. The model must always be a Date object. In the event the model is
 28329    * month format (yyyy-MM), for example: `2009-01`.
 27721    * not set to the first of the month, the first of that model's month is assumed.
 28330    *
       
 28331    * The model must always be a Date object, otherwise Angular will throw an error.
       
 28332    * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
       
 28333    * If the model is not set to the first of the month, the next view to model update will set it
       
 28334    * to the first of the month.
 27722    *
 28335    *
 27723    * The timezone to be used to read/write the `Date` instance in the model can be defined using
 28336    * The timezone to be used to read/write the `Date` instance in the model can be defined using
 27724    * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
 28337    * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
 27725    *
 28338    *
 27726    * @param {string} ngModel Assignable angular expression to data-bind to.
 28339    * @param {string} ngModel Assignable angular expression to data-bind to.
 27805    *
 28418    *
 27806    * @description
 28419    * @description
 27807    * Text input with number validation and transformation. Sets the `number` validation
 28420    * Text input with number validation and transformation. Sets the `number` validation
 27808    * error if not a valid number.
 28421    * error if not a valid number.
 27809    *
 28422    *
       
 28423    * The model must always be a number, otherwise Angular will throw an error.
       
 28424    *
 27810    * @param {string} ngModel Assignable angular expression to data-bind to.
 28425    * @param {string} ngModel Assignable angular expression to data-bind to.
 27811    * @param {string=} name Property name of the form under which the control is published.
 28426    * @param {string=} name Property name of the form under which the control is published.
 27812    * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
 28427    * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
 27813    * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
 28428    * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
 27814    * @param {string=} required Sets `required` validation error key if the value is not entered.
 28429    * @param {string=} required Sets `required` validation error key if the value is not entered.
 27816    *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
 28431    *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
 27817    *    `required` when you want to data-bind to the `required` attribute.
 28432    *    `required` when you want to data-bind to the `required` attribute.
 27818    * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
 28433    * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
 27819    *    minlength.
 28434    *    minlength.
 27820    * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
 28435    * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
 27821    *    maxlength.
 28436    *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of
 27822    * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
 28437    *    any length.
 27823    *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
 28438    * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
 27824    *    patterns defined as scope expressions.
 28439    *    that contains the regular expression body that will be converted to a regular expression
       
 28440    *    as in the ngPattern directive.
       
 28441    * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
       
 28442    *    a RegExp found by evaluating the Angular expression given in the attribute value.
       
 28443    *    If the expression evaluates to a RegExp object then this is used directly.
       
 28444    *    If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$`
       
 28445    *    characters. For instance, `"abc"` will be converted to `new RegExp('^abc$')`.
 27825    * @param {string=} ngChange Angular expression to be executed when input changes due to user
 28446    * @param {string=} ngChange Angular expression to be executed when input changes due to user
 27826    *    interaction with the input element.
 28447    *    interaction with the input element.
 27827    *
 28448    *
 27828    * @example
 28449    * @example
 27829       <example name="number-input-directive" module="numberExample">
 28450       <example name="number-input-directive" module="numberExample">
 27883    *
 28504    *
 27884    * @description
 28505    * @description
 27885    * Text input with URL validation. Sets the `url` validation error key if the content is not a
 28506    * Text input with URL validation. Sets the `url` validation error key if the content is not a
 27886    * valid URL.
 28507    * valid URL.
 27887    *
 28508    *
       
 28509    * <div class="alert alert-warning">
       
 28510    * **Note:** `input[url]` uses a regex to validate urls that is derived from the regex
       
 28511    * used in Chromium. If you need stricter validation, you can use `ng-pattern` or modify
       
 28512    * the built-in validators (see the {@link guide/forms Forms guide})
       
 28513    * </div>
       
 28514    *
 27888    * @param {string} ngModel Assignable angular expression to data-bind to.
 28515    * @param {string} ngModel Assignable angular expression to data-bind to.
 27889    * @param {string=} name Property name of the form under which the control is published.
 28516    * @param {string=} name Property name of the form under which the control is published.
 27890    * @param {string=} required Sets `required` validation error key if the value is not entered.
 28517    * @param {string=} required Sets `required` validation error key if the value is not entered.
 27891    * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
 28518    * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
 27892    *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
 28519    *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
 27893    *    `required` when you want to data-bind to the `required` attribute.
 28520    *    `required` when you want to data-bind to the `required` attribute.
 27894    * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
 28521    * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
 27895    *    minlength.
 28522    *    minlength.
 27896    * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
 28523    * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
 27897    *    maxlength.
 28524    *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of
 27898    * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
 28525    *    any length.
 27899    *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
 28526    * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
 27900    *    patterns defined as scope expressions.
 28527    *    that contains the regular expression body that will be converted to a regular expression
       
 28528    *    as in the ngPattern directive.
       
 28529    * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
       
 28530    *    a RegExp found by evaluating the Angular expression given in the attribute value.
       
 28531    *    If the expression evaluates to a RegExp object then this is used directly.
       
 28532    *    If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$`
       
 28533    *    characters. For instance, `"abc"` will be converted to `new RegExp('^abc$')`.
 27901    * @param {string=} ngChange Angular expression to be executed when input changes due to user
 28534    * @param {string=} ngChange Angular expression to be executed when input changes due to user
 27902    *    interaction with the input element.
 28535    *    interaction with the input element.
 27903    *
 28536    *
 27904    * @example
 28537    * @example
 27905       <example name="url-input-directive" module="urlExample">
 28538       <example name="url-input-directive" module="urlExample">
 27960    *
 28593    *
 27961    * @description
 28594    * @description
 27962    * Text input with email validation. Sets the `email` validation error key if not a valid email
 28595    * Text input with email validation. Sets the `email` validation error key if not a valid email
 27963    * address.
 28596    * address.
 27964    *
 28597    *
       
 28598    * <div class="alert alert-warning">
       
 28599    * **Note:** `input[email]` uses a regex to validate email addresses that is derived from the regex
       
 28600    * used in Chromium. If you need stricter validation (e.g. requiring a top-level domain), you can
       
 28601    * use `ng-pattern` or modify the built-in validators (see the {@link guide/forms Forms guide})
       
 28602    * </div>
       
 28603    *
 27965    * @param {string} ngModel Assignable angular expression to data-bind to.
 28604    * @param {string} ngModel Assignable angular expression to data-bind to.
 27966    * @param {string=} name Property name of the form under which the control is published.
 28605    * @param {string=} name Property name of the form under which the control is published.
 27967    * @param {string=} required Sets `required` validation error key if the value is not entered.
 28606    * @param {string=} required Sets `required` validation error key if the value is not entered.
 27968    * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
 28607    * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
 27969    *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
 28608    *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
 27970    *    `required` when you want to data-bind to the `required` attribute.
 28609    *    `required` when you want to data-bind to the `required` attribute.
 27971    * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
 28610    * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
 27972    *    minlength.
 28611    *    minlength.
 27973    * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
 28612    * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
 27974    *    maxlength.
 28613    *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of
 27975    * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
 28614    *    any length.
 27976    *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
 28615    * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
 27977    *    patterns defined as scope expressions.
 28616    *    that contains the regular expression body that will be converted to a regular expression
       
 28617    *    as in the ngPattern directive.
       
 28618    * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
       
 28619    *    a RegExp found by evaluating the Angular expression given in the attribute value.
       
 28620    *    If the expression evaluates to a RegExp object then this is used directly.
       
 28621    *    If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$`
       
 28622    *    characters. For instance, `"abc"` will be converted to `new RegExp('^abc$')`.
 27978    * @param {string=} ngChange Angular expression to be executed when input changes due to user
 28623    * @param {string=} ngChange Angular expression to be executed when input changes due to user
 27979    *    interaction with the input element.
 28624    *    interaction with the input element.
 27980    *
 28625    *
 27981    * @example
 28626    * @example
 27982       <example name="email-input-directive" module="emailExample">
 28627       <example name="email-input-directive" module="emailExample">
 28138   'submit': noop,
 28783   'submit': noop,
 28139   'reset': noop,
 28784   'reset': noop,
 28140   'file': noop
 28785   'file': noop
 28141 };
 28786 };
 28142 
 28787 
 28143 function testFlags(validity, flags) {
       
 28144   var i, flag;
       
 28145   if (flags) {
       
 28146     for (i=0; i<flags.length; ++i) {
       
 28147       flag = flags[i];
       
 28148       if (validity[flag]) {
       
 28149         return true;
       
 28150       }
       
 28151     }
       
 28152   }
       
 28153   return false;
       
 28154 }
       
 28155 
       
 28156 function stringBasedInputType(ctrl) {
 28788 function stringBasedInputType(ctrl) {
 28157   ctrl.$formatters.push(function(value) {
 28789   ctrl.$formatters.push(function(value) {
 28158     return ctrl.$isEmpty(value) ? value : value.toString();
 28790     return ctrl.$isEmpty(value) ? value : value.toString();
 28159   });
 28791   });
 28160 }
 28792 }
 28163   baseInputType(scope, element, attr, ctrl, $sniffer, $browser);
 28795   baseInputType(scope, element, attr, ctrl, $sniffer, $browser);
 28164   stringBasedInputType(ctrl);
 28796   stringBasedInputType(ctrl);
 28165 }
 28797 }
 28166 
 28798 
 28167 function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) {
 28799 function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) {
 28168   var validity = element.prop(VALIDITY_STATE_PROPERTY);
       
 28169   var placeholder = element[0].placeholder, noevent = {};
       
 28170   var type = lowercase(element[0].type);
 28800   var type = lowercase(element[0].type);
 28171 
 28801 
 28172   // In composition mode, users are still inputing intermediate text buffer,
 28802   // In composition mode, users are still inputing intermediate text buffer,
 28173   // hold the listener until composition is done.
 28803   // hold the listener until composition is done.
 28174   // More about composition events: https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent
 28804   // More about composition events: https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent
 28184       listener();
 28814       listener();
 28185     });
 28815     });
 28186   }
 28816   }
 28187 
 28817 
 28188   var listener = function(ev) {
 28818   var listener = function(ev) {
       
 28819     if (timeout) {
       
 28820       $browser.defer.cancel(timeout);
       
 28821       timeout = null;
       
 28822     }
 28189     if (composing) return;
 28823     if (composing) return;
 28190     var value = element.val(),
 28824     var value = element.val(),
 28191         event = ev && ev.type;
 28825         event = ev && ev.type;
 28192 
       
 28193     // IE (11 and under) seem to emit an 'input' event if the placeholder value changes.
       
 28194     // We don't want to dirty the value when this happens, so we abort here. Unfortunately,
       
 28195     // IE also sends input events for other non-input-related things, (such as focusing on a
       
 28196     // form control), so this change is not entirely enough to solve this.
       
 28197     if (msie && (ev || noevent).type === 'input' && element[0].placeholder !== placeholder) {
       
 28198       placeholder = element[0].placeholder;
       
 28199       return;
       
 28200     }
       
 28201 
 28826 
 28202     // By default we will trim the value
 28827     // By default we will trim the value
 28203     // If the attribute ng-trim exists we will avoid trimming
 28828     // If the attribute ng-trim exists we will avoid trimming
 28204     // If input type is 'password', the value is never trimmed
 28829     // If input type is 'password', the value is never trimmed
 28205     if (type !== 'password' && (!attr.ngTrim || attr.ngTrim !== 'false')) {
 28830     if (type !== 'password' && (!attr.ngTrim || attr.ngTrim !== 'false')) {
 28219   if ($sniffer.hasEvent('input')) {
 28844   if ($sniffer.hasEvent('input')) {
 28220     element.on('input', listener);
 28845     element.on('input', listener);
 28221   } else {
 28846   } else {
 28222     var timeout;
 28847     var timeout;
 28223 
 28848 
 28224     var deferListener = function(ev) {
 28849     var deferListener = function(ev, input, origValue) {
 28225       if (!timeout) {
 28850       if (!timeout) {
 28226         timeout = $browser.defer(function() {
 28851         timeout = $browser.defer(function() {
 28227           listener(ev);
       
 28228           timeout = null;
 28852           timeout = null;
       
 28853           if (!input || input.value !== origValue) {
       
 28854             listener(ev);
       
 28855           }
 28229         });
 28856         });
 28230       }
 28857       }
 28231     };
 28858     };
 28232 
 28859 
 28233     element.on('keydown', function(event) {
 28860     element.on('keydown', function(event) {
 28235 
 28862 
 28236       // ignore
 28863       // ignore
 28237       //    command            modifiers                   arrows
 28864       //    command            modifiers                   arrows
 28238       if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;
 28865       if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;
 28239 
 28866 
 28240       deferListener(event);
 28867       deferListener(event, this, this.value);
 28241     });
 28868     });
 28242 
 28869 
 28243     // if user modifies input value using context menu in IE, we need "paste" and "cut" events to catch it
 28870     // if user modifies input value using context menu in IE, we need "paste" and "cut" events to catch it
 28244     if ($sniffer.hasEvent('paste')) {
 28871     if ($sniffer.hasEvent('paste')) {
 28245       element.on('paste cut', deferListener);
 28872       element.on('paste cut', deferListener);
 28249   // if user paste into input using mouse on older browser
 28876   // if user paste into input using mouse on older browser
 28250   // or form autocomplete on newer browser, we need "change" event to catch it
 28877   // or form autocomplete on newer browser, we need "change" event to catch it
 28251   element.on('change', listener);
 28878   element.on('change', listener);
 28252 
 28879 
 28253   ctrl.$render = function() {
 28880   ctrl.$render = function() {
 28254     element.val(ctrl.$isEmpty(ctrl.$modelValue) ? '' : ctrl.$viewValue);
 28881     element.val(ctrl.$isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);
 28255   };
 28882   };
 28256 }
 28883 }
 28257 
 28884 
 28258 function weekParser(isoWeek, existingDate) {
 28885 function weekParser(isoWeek, existingDate) {
 28259   if (isDate(isoWeek)) {
 28886   if (isDate(isoWeek)) {
 28297 
 28924 
 28298     if (isString(iso)) {
 28925     if (isString(iso)) {
 28299       // When a date is JSON'ified to wraps itself inside of an extra
 28926       // When a date is JSON'ified to wraps itself inside of an extra
 28300       // set of double quotes. This makes the date parsing code unable
 28927       // set of double quotes. This makes the date parsing code unable
 28301       // to match the date string and parse it as a date.
 28928       // to match the date string and parse it as a date.
 28302       if (iso.charAt(0) == '"' && iso.charAt(iso.length-1) == '"') {
 28929       if (iso.charAt(0) == '"' && iso.charAt(iso.length - 1) == '"') {
 28303         iso = iso.substring(1, iso.length-1);
 28930         iso = iso.substring(1, iso.length - 1);
 28304       }
 28931       }
 28305       if (ISO_DATE_REGEXP.test(iso)) {
 28932       if (ISO_DATE_REGEXP.test(iso)) {
 28306         return new Date(iso);
 28933         return new Date(iso);
 28307       }
 28934       }
 28308       regexp.lastIndex = 0;
 28935       regexp.lastIndex = 0;
 28359       }
 28986       }
 28360       return undefined;
 28987       return undefined;
 28361     });
 28988     });
 28362 
 28989 
 28363     ctrl.$formatters.push(function(value) {
 28990     ctrl.$formatters.push(function(value) {
 28364       if (!ctrl.$isEmpty(value)) {
 28991       if (value && !isDate(value)) {
 28365         if (!isDate(value)) {
 28992         throw $ngModelMinErr('datefmt', 'Expected `{0}` to be a date', value);
 28366           throw $ngModelMinErr('datefmt', 'Expected `{0}` to be a date', value);
 28993       }
 28367         }
 28994       if (isValidDate(value)) {
 28368         previousDate = value;
 28995         previousDate = value;
 28369         if (previousDate && timezone === 'UTC') {
 28996         if (previousDate && timezone === 'UTC') {
 28370           var timezoneOffset = 60000 * previousDate.getTimezoneOffset();
 28997           var timezoneOffset = 60000 * previousDate.getTimezoneOffset();
 28371           previousDate = new Date(previousDate.getTime() + timezoneOffset);
 28998           previousDate = new Date(previousDate.getTime() + timezoneOffset);
 28372         }
 28999         }
 28373         return $filter('date')(value, format, timezone);
 29000         return $filter('date')(value, format, timezone);
 28374       } else {
 29001       } else {
 28375         previousDate = null;
 29002         previousDate = null;
       
 29003         return '';
 28376       }
 29004       }
 28377       return '';
       
 28378     });
 29005     });
 28379 
 29006 
 28380     if (isDefined(attr.min) || attr.ngMin) {
 29007     if (isDefined(attr.min) || attr.ngMin) {
 28381       var minVal;
 29008       var minVal;
 28382       ctrl.$validators.min = function(value) {
 29009       ctrl.$validators.min = function(value) {
 28383         return ctrl.$isEmpty(value) || isUndefined(minVal) || parseDate(value) >= minVal;
 29010         return !isValidDate(value) || isUndefined(minVal) || parseDate(value) >= minVal;
 28384       };
 29011       };
 28385       attr.$observe('min', function(val) {
 29012       attr.$observe('min', function(val) {
 28386         minVal = parseObservedDateValue(val);
 29013         minVal = parseObservedDateValue(val);
 28387         ctrl.$validate();
 29014         ctrl.$validate();
 28388       });
 29015       });
 28389     }
 29016     }
 28390 
 29017 
 28391     if (isDefined(attr.max) || attr.ngMax) {
 29018     if (isDefined(attr.max) || attr.ngMax) {
 28392       var maxVal;
 29019       var maxVal;
 28393       ctrl.$validators.max = function(value) {
 29020       ctrl.$validators.max = function(value) {
 28394         return ctrl.$isEmpty(value) || isUndefined(maxVal) || parseDate(value) <= maxVal;
 29021         return !isValidDate(value) || isUndefined(maxVal) || parseDate(value) <= maxVal;
 28395       };
 29022       };
 28396       attr.$observe('max', function(val) {
 29023       attr.$observe('max', function(val) {
 28397         maxVal = parseObservedDateValue(val);
 29024         maxVal = parseObservedDateValue(val);
 28398         ctrl.$validate();
 29025         ctrl.$validate();
 28399       });
 29026       });
 28400     }
 29027     }
 28401     // Override the standard $isEmpty to detect invalid dates as well
 29028 
 28402     ctrl.$isEmpty = function(value) {
 29029     function isValidDate(value) {
 28403       // Invalid Date: getTime() returns NaN
 29030       // Invalid Date: getTime() returns NaN
 28404       return !value || (value.getTime && value.getTime() !== value.getTime());
 29031       return value && !(value.getTime && value.getTime() !== value.getTime());
 28405     };
 29032     }
 28406 
 29033 
 28407     function parseObservedDateValue(val) {
 29034     function parseObservedDateValue(val) {
 28408       return isDefined(val) ? (isDate(val) ? val : parseDate(val)) : undefined;
 29035       return isDefined(val) ? (isDate(val) ? val : parseDate(val)) : undefined;
 28409     }
 29036     }
 28410   };
 29037   };
 28484   // in browsers, i.e. we can always read out input.value even if it is not valid!
 29111   // in browsers, i.e. we can always read out input.value even if it is not valid!
 28485   baseInputType(scope, element, attr, ctrl, $sniffer, $browser);
 29112   baseInputType(scope, element, attr, ctrl, $sniffer, $browser);
 28486   stringBasedInputType(ctrl);
 29113   stringBasedInputType(ctrl);
 28487 
 29114 
 28488   ctrl.$$parserName = 'url';
 29115   ctrl.$$parserName = 'url';
 28489   ctrl.$validators.url = function(value) {
 29116   ctrl.$validators.url = function(modelValue, viewValue) {
       
 29117     var value = modelValue || viewValue;
 28490     return ctrl.$isEmpty(value) || URL_REGEXP.test(value);
 29118     return ctrl.$isEmpty(value) || URL_REGEXP.test(value);
 28491   };
 29119   };
 28492 }
 29120 }
 28493 
 29121 
 28494 function emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {
 29122 function emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {
 28496   // in browsers, i.e. we can always read out input.value even if it is not valid!
 29124   // in browsers, i.e. we can always read out input.value even if it is not valid!
 28497   baseInputType(scope, element, attr, ctrl, $sniffer, $browser);
 29125   baseInputType(scope, element, attr, ctrl, $sniffer, $browser);
 28498   stringBasedInputType(ctrl);
 29126   stringBasedInputType(ctrl);
 28499 
 29127 
 28500   ctrl.$$parserName = 'email';
 29128   ctrl.$$parserName = 'email';
 28501   ctrl.$validators.email = function(value) {
 29129   ctrl.$validators.email = function(modelValue, viewValue) {
       
 29130     var value = modelValue || viewValue;
 28502     return ctrl.$isEmpty(value) || EMAIL_REGEXP.test(value);
 29131     return ctrl.$isEmpty(value) || EMAIL_REGEXP.test(value);
 28503   };
 29132   };
 28504 }
 29133 }
 28505 
 29134 
 28506 function radioInputType(scope, element, attr, ctrl) {
 29135 function radioInputType(scope, element, attr, ctrl) {
 28550 
 29179 
 28551   ctrl.$render = function() {
 29180   ctrl.$render = function() {
 28552     element[0].checked = ctrl.$viewValue;
 29181     element[0].checked = ctrl.$viewValue;
 28553   };
 29182   };
 28554 
 29183 
 28555   // Override the standard `$isEmpty` because an empty checkbox is never equal to the trueValue
 29184   // Override the standard `$isEmpty` because the $viewValue of an empty checkbox is always set to `false`
       
 29185   // This is because of the parser below, which compares the `$modelValue` with `trueValue` to convert
       
 29186   // it to a boolean.
 28556   ctrl.$isEmpty = function(value) {
 29187   ctrl.$isEmpty = function(value) {
 28557     return value !== trueValue;
 29188     return value === false;
 28558   };
 29189   };
 28559 
 29190 
 28560   ctrl.$formatters.push(function(value) {
 29191   ctrl.$formatters.push(function(value) {
 28561     return equals(value, trueValue);
 29192     return equals(value, trueValue);
 28562   });
 29193   });
 28584  *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
 29215  *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
 28585  *    `required` when you want to data-bind to the `required` attribute.
 29216  *    `required` when you want to data-bind to the `required` attribute.
 28586  * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
 29217  * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
 28587  *    minlength.
 29218  *    minlength.
 28588  * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
 29219  * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
 28589  *    maxlength.
 29220  *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any
       
 29221  *    length.
 28590  * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
 29222  * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
 28591  *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
 29223  *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
 28592  *    patterns defined as scope expressions.
 29224  *    patterns defined as scope expressions.
 28593  * @param {string=} ngChange Angular expression to be executed when input changes due to user
 29225  * @param {string=} ngChange Angular expression to be executed when input changes due to user
 28594  *    interaction with the input element.
 29226  *    interaction with the input element.
 28600  * @ngdoc directive
 29232  * @ngdoc directive
 28601  * @name input
 29233  * @name input
 28602  * @restrict E
 29234  * @restrict E
 28603  *
 29235  *
 28604  * @description
 29236  * @description
 28605  * HTML input element control with angular data-binding. Input control follows HTML5 input types
 29237  * HTML input element control. When used together with {@link ngModel `ngModel`}, it provides data-binding,
 28606  * and polyfills the HTML5 validation behavior for older browsers.
 29238  * input state control, and validation.
 28607  *
 29239  * Input control follows HTML5 input types and polyfills the HTML5 validation behavior for older browsers.
 28608  * *NOTE* Not every feature offered is available for all input types.
 29240  *
       
 29241  * <div class="alert alert-warning">
       
 29242  * **Note:** Not every feature offered is available for all input types.
       
 29243  * Specifically, data binding and event handling via `ng-model` is unsupported for `input[file]`.
       
 29244  * </div>
 28609  *
 29245  *
 28610  * @param {string} ngModel Assignable angular expression to data-bind to.
 29246  * @param {string} ngModel Assignable angular expression to data-bind to.
 28611  * @param {string=} name Property name of the form under which the control is published.
 29247  * @param {string=} name Property name of the form under which the control is published.
 28612  * @param {string=} required Sets `required` validation error key if the value is not entered.
 29248  * @param {string=} required Sets `required` validation error key if the value is not entered.
 28613  * @param {boolean=} ngRequired Sets `required` attribute if set to true
 29249  * @param {boolean=} ngRequired Sets `required` attribute if set to true
 28614  * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
 29250  * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
 28615  *    minlength.
 29251  *    minlength.
 28616  * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
 29252  * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
 28617  *    maxlength.
 29253  *    maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any
       
 29254  *    length.
 28618  * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
 29255  * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
 28619  *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
 29256  *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
 28620  *    patterns defined as scope expressions.
 29257  *    patterns defined as scope expressions.
 28621  * @param {string=} ngChange Angular expression to be executed when input changes due to user
 29258  * @param {string=} ngChange Angular expression to be executed when input changes due to user
 28622  *    interaction with the input element.
 29259  *    interaction with the input element.
 28739 /**
 29376 /**
 28740  * @ngdoc type
 29377  * @ngdoc type
 28741  * @name ngModel.NgModelController
 29378  * @name ngModel.NgModelController
 28742  *
 29379  *
 28743  * @property {string} $viewValue Actual string value in the view.
 29380  * @property {string} $viewValue Actual string value in the view.
 28744  * @property {*} $modelValue The value in the model, that the control is bound to.
 29381  * @property {*} $modelValue The value in the model that the control is bound to.
 28745  * @property {Array.<Function>} $parsers Array of functions to execute, as a pipeline, whenever
 29382  * @property {Array.<Function>} $parsers Array of functions to execute, as a pipeline, whenever
 28746        the control reads value from the DOM.  Each function is called, in turn, passing the value
 29383        the control reads value from the DOM. The functions are called in array order, each passing
 28747        through to the next. The last return value is used to populate the model.
 29384        its return value through to the next. The last return value is forwarded to the
 28748        Used to sanitize / convert the value as well as validation. For validation,
 29385        {@link ngModel.NgModelController#$validators `$validators`} collection.
 28749        the parsers should update the validity state using
 29386 
 28750        {@link ngModel.NgModelController#$setValidity $setValidity()},
 29387 Parsers are used to sanitize / convert the {@link ngModel.NgModelController#$viewValue
 28751        and return `undefined` for invalid values.
 29388 `$viewValue`}.
       
 29389 
       
 29390 Returning `undefined` from a parser means a parse error occurred. In that case,
       
 29391 no {@link ngModel.NgModelController#$validators `$validators`} will run and the `ngModel`
       
 29392 will be set to `undefined` unless {@link ngModelOptions `ngModelOptions.allowInvalid`}
       
 29393 is set to `true`. The parse error is stored in `ngModel.$error.parse`.
 28752 
 29394 
 28753  *
 29395  *
 28754  * @property {Array.<Function>} $formatters Array of functions to execute, as a pipeline, whenever
 29396  * @property {Array.<Function>} $formatters Array of functions to execute, as a pipeline, whenever
 28755        the model value changes. Each function is called, in turn, passing the value through to the
 29397        the model value changes. The functions are called in reverse array order, each passing the value through to the
 28756        next. Used to format / convert values for display in the control and validation.
 29398        next. The last return value is used as the actual DOM value.
       
 29399        Used to format / convert values for display in the control.
 28757  * ```js
 29400  * ```js
 28758  * function formatter(value) {
 29401  * function formatter(value) {
 28759  *   if (value) {
 29402  *   if (value) {
 28760  *     return value.toUpperCase();
 29403  *     return value.toUpperCase();
 28761  *   }
 29404  *   }
 28782  * @property {Object.<string, function>} $asyncValidators A collection of validations that are expected to
 29425  * @property {Object.<string, function>} $asyncValidators A collection of validations that are expected to
 28783  *      perform an asynchronous validation (e.g. a HTTP request). The validation function that is provided
 29426  *      perform an asynchronous validation (e.g. a HTTP request). The validation function that is provided
 28784  *      is expected to return a promise when it is run during the model validation process. Once the promise
 29427  *      is expected to return a promise when it is run during the model validation process. Once the promise
 28785  *      is delivered then the validation status will be set to true when fulfilled and false when rejected.
 29428  *      is delivered then the validation status will be set to true when fulfilled and false when rejected.
 28786  *      When the asynchronous validators are triggered, each of the validators will run in parallel and the model
 29429  *      When the asynchronous validators are triggered, each of the validators will run in parallel and the model
 28787  *      value will only be updated once all validators have been fulfilled. Also, keep in mind that all
 29430  *      value will only be updated once all validators have been fulfilled. As long as an asynchronous validator
 28788  *      asynchronous validators will only run once all synchronous validators have passed.
 29431  *      is unfulfilled, its key will be added to the controllers `$pending` property. Also, all asynchronous validators
       
 29432  *      will only run once all synchronous validators have passed.
 28789  *
 29433  *
 28790  * Please note that if $http is used then it is important that the server returns a success HTTP response code
 29434  * Please note that if $http is used then it is important that the server returns a success HTTP response code
 28791  * in order to fulfill the validation and a status level of `4xx` in order to reject the validation.
 29435  * in order to fulfill the validation and a status level of `4xx` in order to reject the validation.
 28792  *
 29436  *
 28793  * ```js
 29437  * ```js
 28804  *        return true;
 29448  *        return true;
 28805  *      });
 29449  *      });
 28806  * };
 29450  * };
 28807  * ```
 29451  * ```
 28808  *
 29452  *
 28809  * @param {string} name The name of the validator.
       
 28810  * @param {Function} validationFn The validation function that will be run.
       
 28811  *
       
 28812  * @property {Array.<Function>} $viewChangeListeners Array of functions to execute whenever the
 29453  * @property {Array.<Function>} $viewChangeListeners Array of functions to execute whenever the
 28813  *     view value has changed. It is called with no arguments, and its return value is ignored.
 29454  *     view value has changed. It is called with no arguments, and its return value is ignored.
 28814  *     This can be used in place of additional $watches against the model value.
 29455  *     This can be used in place of additional $watches against the model value.
 28815  *
 29456  *
 28816  * @property {Object} $error An object hash with all failing validator ids as keys.
 29457  * @property {Object} $error An object hash with all failing validator ids as keys.
 28820  * @property {boolean} $touched True if control has lost focus.
 29461  * @property {boolean} $touched True if control has lost focus.
 28821  * @property {boolean} $pristine True if user has not interacted with the control yet.
 29462  * @property {boolean} $pristine True if user has not interacted with the control yet.
 28822  * @property {boolean} $dirty True if user has already interacted with the control.
 29463  * @property {boolean} $dirty True if user has already interacted with the control.
 28823  * @property {boolean} $valid True if there is no error.
 29464  * @property {boolean} $valid True if there is no error.
 28824  * @property {boolean} $invalid True if at least one error on the control.
 29465  * @property {boolean} $invalid True if at least one error on the control.
       
 29466  * @property {string} $name The name attribute of the control.
 28825  *
 29467  *
 28826  * @description
 29468  * @description
 28827  *
 29469  *
 28828  * `NgModelController` provides API for the `ng-model` directive. The controller contains
 29470  * `NgModelController` provides API for the {@link ngModel `ngModel`} directive.
 28829  * services for data-binding, validation, CSS updates, and value formatting and parsing. It
 29471  * The controller contains services for data-binding, validation, CSS updates, and value formatting
 28830  * purposefully does not contain any logic which deals with DOM rendering or listening to
 29472  * and parsing. It purposefully does not contain any logic which deals with DOM rendering or
 28831  * DOM events. Such DOM related logic should be provided by other directives which make use of
 29473  * listening to DOM events.
 28832  * `NgModelController` for data-binding.
 29474  * Such DOM related logic should be provided by other directives which make use of
 28833  *
 29475  * `NgModelController` for data-binding to control elements.
 28834  * ## Custom Control Example
 29476  * Angular provides this DOM logic for most {@link input `input`} elements.
       
 29477  * At the end of this page you can find a {@link ngModel.NgModelController#custom-control-example
       
 29478  * custom control example} that uses `ngModelController` to bind to `contenteditable` elements.
       
 29479  *
       
 29480  * @example
       
 29481  * ### Custom Control Example
 28835  * This example shows how to use `NgModelController` with a custom control to achieve
 29482  * This example shows how to use `NgModelController` with a custom control to achieve
 28836  * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)
 29483  * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)
 28837  * collaborate together to achieve the desired result.
 29484  * collaborate together to achieve the desired result.
 28838  *
 29485  *
 28839  * Note that `contenteditable` is an HTML5 attribute, which tells the browser to let the element
 29486  * Note that `contenteditable` is an HTML5 attribute, which tells the browser to let the element
 28840  * contents be edited in place by the user.  This will not work on older browsers.
 29487  * contents be edited in place by the user.  This will not work on older browsers.
 28841  *
 29488  *
 28842  * We are using the {@link ng.service:$sce $sce} service here and include the {@link ngSanitize $sanitize}
 29489  * We are using the {@link ng.service:$sce $sce} service here and include the {@link ngSanitize $sanitize}
 28843  * module to automatically remove "bad" content like inline event listener (e.g. `<span onclick="...">`).
 29490  * module to automatically remove "bad" content like inline event listener (e.g. `<span onclick="...">`).
 28844  * However, as we are using `$sce` the model can still decide to to provide unsafe content if it marks
 29491  * However, as we are using `$sce` the model can still decide to provide unsafe content if it marks
 28845  * that content using the `$sce` service.
 29492  * that content using the `$sce` service.
 28846  *
 29493  *
 28847  * <example name="NgModelController" module="customControl" deps="angular-sanitize.js">
 29494  * <example name="NgModelController" module="customControl" deps="angular-sanitize.js">
 28848     <file name="style.css">
 29495     <file name="style.css">
 28849       [contenteditable] {
 29496       [contenteditable] {
 28871                 element.html($sce.getTrustedHtml(ngModel.$viewValue || ''));
 29518                 element.html($sce.getTrustedHtml(ngModel.$viewValue || ''));
 28872               };
 29519               };
 28873 
 29520 
 28874               // Listen for change events to enable binding
 29521               // Listen for change events to enable binding
 28875               element.on('blur keyup change', function() {
 29522               element.on('blur keyup change', function() {
 28876                 scope.$apply(read);
 29523                 scope.$evalAsync(read);
 28877               });
 29524               });
 28878               read(); // initialize
 29525               read(); // initialize
 28879 
 29526 
 28880               // Write data to the model
 29527               // Write data to the model
 28881               function read() {
 29528               function read() {
 28926  */
 29573  */
 28927 var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse', '$animate', '$timeout', '$rootScope', '$q', '$interpolate',
 29574 var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse', '$animate', '$timeout', '$rootScope', '$q', '$interpolate',
 28928     function($scope, $exceptionHandler, $attr, $element, $parse, $animate, $timeout, $rootScope, $q, $interpolate) {
 29575     function($scope, $exceptionHandler, $attr, $element, $parse, $animate, $timeout, $rootScope, $q, $interpolate) {
 28929   this.$viewValue = Number.NaN;
 29576   this.$viewValue = Number.NaN;
 28930   this.$modelValue = Number.NaN;
 29577   this.$modelValue = Number.NaN;
       
 29578   this.$$rawModelValue = undefined; // stores the parsed modelValue / model set from scope regardless of validity.
 28931   this.$validators = {};
 29579   this.$validators = {};
 28932   this.$asyncValidators = {};
 29580   this.$asyncValidators = {};
 28933   this.$parsers = [];
 29581   this.$parsers = [];
 28934   this.$formatters = [];
 29582   this.$formatters = [];
 28935   this.$viewChangeListeners = [];
 29583   this.$viewChangeListeners = [];
 28944   this.$pending = undefined; // keep pending keys here
 29592   this.$pending = undefined; // keep pending keys here
 28945   this.$name = $interpolate($attr.name || '', false)($scope);
 29593   this.$name = $interpolate($attr.name || '', false)($scope);
 28946 
 29594 
 28947 
 29595 
 28948   var parsedNgModel = $parse($attr.ngModel),
 29596   var parsedNgModel = $parse($attr.ngModel),
       
 29597       parsedNgModelAssign = parsedNgModel.assign,
       
 29598       ngModelGet = parsedNgModel,
       
 29599       ngModelSet = parsedNgModelAssign,
 28949       pendingDebounce = null,
 29600       pendingDebounce = null,
 28950       ctrl = this;
 29601       ctrl = this;
 28951 
 29602 
 28952   var ngModelGet = function ngModelGet() {
       
 28953     var modelValue = parsedNgModel($scope);
       
 28954     if (ctrl.$options && ctrl.$options.getterSetter && isFunction(modelValue)) {
       
 28955       modelValue = modelValue();
       
 28956     }
       
 28957     return modelValue;
       
 28958   };
       
 28959 
       
 28960   var ngModelSet = function ngModelSet(newValue) {
       
 28961     var getterSetter;
       
 28962     if (ctrl.$options && ctrl.$options.getterSetter &&
       
 28963         isFunction(getterSetter = parsedNgModel($scope))) {
       
 28964 
       
 28965       getterSetter(ctrl.$modelValue);
       
 28966     } else {
       
 28967       parsedNgModel.assign($scope, ctrl.$modelValue);
       
 28968     }
       
 28969   };
       
 28970 
       
 28971   this.$$setOptions = function(options) {
 29603   this.$$setOptions = function(options) {
 28972     ctrl.$options = options;
 29604     ctrl.$options = options;
 28973 
 29605     if (options && options.getterSetter) {
 28974     if (!parsedNgModel.assign && (!options || !options.getterSetter)) {
 29606       var invokeModelGetter = $parse($attr.ngModel + '()'),
       
 29607           invokeModelSetter = $parse($attr.ngModel + '($$$p)');
       
 29608 
       
 29609       ngModelGet = function($scope) {
       
 29610         var modelValue = parsedNgModel($scope);
       
 29611         if (isFunction(modelValue)) {
       
 29612           modelValue = invokeModelGetter($scope);
       
 29613         }
       
 29614         return modelValue;
       
 29615       };
       
 29616       ngModelSet = function($scope, newValue) {
       
 29617         if (isFunction(parsedNgModel($scope))) {
       
 29618           invokeModelSetter($scope, {$$$p: ctrl.$modelValue});
       
 29619         } else {
       
 29620           parsedNgModelAssign($scope, ctrl.$modelValue);
       
 29621         }
       
 29622       };
       
 29623     } else if (!parsedNgModel.assign) {
 28975       throw $ngModelMinErr('nonassign', "Expression '{0}' is non-assignable. Element: {1}",
 29624       throw $ngModelMinErr('nonassign', "Expression '{0}' is non-assignable. Element: {1}",
 28976           $attr.ngModel, startingTag($element));
 29625           $attr.ngModel, startingTag($element));
 28977     }
 29626     }
 28978   };
 29627   };
 28979 
 29628 
 29002   /**
 29651   /**
 29003    * @ngdoc method
 29652    * @ngdoc method
 29004    * @name ngModel.NgModelController#$isEmpty
 29653    * @name ngModel.NgModelController#$isEmpty
 29005    *
 29654    *
 29006    * @description
 29655    * @description
 29007    * This is called when we need to determine if the value of the input is empty.
 29656    * This is called when we need to determine if the value of an input is empty.
 29008    *
 29657    *
 29009    * For instance, the required directive does this to work out if the input has data or not.
 29658    * For instance, the required directive does this to work out if the input has data or not.
       
 29659    *
 29010    * The default `$isEmpty` function checks whether the value is `undefined`, `''`, `null` or `NaN`.
 29660    * The default `$isEmpty` function checks whether the value is `undefined`, `''`, `null` or `NaN`.
 29011    *
 29661    *
 29012    * You can override this for input directives whose concept of being empty is different to the
 29662    * You can override this for input directives whose concept of being empty is different to the
 29013    * default. The `checkboxInputType` directive does this because in its case a value of `false`
 29663    * default. The `checkboxInputType` directive does this because in its case a value of `false`
 29014    * implies empty.
 29664    * implies empty.
 29015    *
 29665    *
 29016    * @param {*} value Model value to check.
 29666    * @param {*} value The value of the input to check for emptiness.
 29017    * @returns {boolean} True if `value` is empty.
 29667    * @returns {boolean} True if `value` is "empty".
 29018    */
 29668    */
 29019   this.$isEmpty = function(value) {
 29669   this.$isEmpty = function(value) {
 29020     return isUndefined(value) || value === '' || value === null || value !== value;
 29670     return isUndefined(value) || value === '' || value === null || value !== value;
 29021   };
 29671   };
 29022 
 29672 
 29026   /**
 29676   /**
 29027    * @ngdoc method
 29677    * @ngdoc method
 29028    * @name ngModel.NgModelController#$setValidity
 29678    * @name ngModel.NgModelController#$setValidity
 29029    *
 29679    *
 29030    * @description
 29680    * @description
 29031    * Change the validity state, and notifies the form.
 29681    * Change the validity state, and notify the form.
 29032    *
 29682    *
 29033    * This method can be called within $parsers/$formatters. However, if possible, please use the
 29683    * This method can be called within $parsers/$formatters or a custom validation implementation.
 29034    *        `ngModel.$validators` pipeline which is designed to call this method automatically.
 29684    * However, in most cases it should be sufficient to use the `ngModel.$validators` and
       
 29685    * `ngModel.$asyncValidators` collections which will call `$setValidity` automatically.
 29035    *
 29686    *
 29036    * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign
 29687    * @param {string} validationErrorKey Name of the validator. The `validationErrorKey` will be assigned
 29037    *        to `$error[validationErrorKey]` and `$pending[validationErrorKey]`
 29688    *        to either `$error[validationErrorKey]` or `$pending[validationErrorKey]`
 29038    *        so that it is available for data-binding.
 29689    *        (for unfulfilled `$asyncValidators`), so that it is available for data-binding.
 29039    *        The `validationErrorKey` should be in camelCase and will get converted into dash-case
 29690    *        The `validationErrorKey` should be in camelCase and will get converted into dash-case
 29040    *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`
 29691    *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`
 29041    *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .
 29692    *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .
 29042    * @param {boolean} isValid Whether the current state is valid (true), invalid (false), pending (undefined),
 29693    * @param {boolean} isValid Whether the current state is valid (true), invalid (false), pending (undefined),
 29043    *                          or skipped (null).
 29694    *                          or skipped (null). Pending is used for unfulfilled `$asyncValidators`.
       
 29695    *                          Skipped is used by Angular when validators do not run because of parse errors and
       
 29696    *                          when `$asyncValidators` do not run because any of the `$validators` failed.
 29044    */
 29697    */
 29045   addSetValidityMethod({
 29698   addSetValidityMethod({
 29046     ctrl: this,
 29699     ctrl: this,
 29047     $element: $element,
 29700     $element: $element,
 29048     set: function(object, property) {
 29701     set: function(object, property) {
 29060    * @name ngModel.NgModelController#$setPristine
 29713    * @name ngModel.NgModelController#$setPristine
 29061    *
 29714    *
 29062    * @description
 29715    * @description
 29063    * Sets the control to its pristine state.
 29716    * Sets the control to its pristine state.
 29064    *
 29717    *
 29065    * This method can be called to remove the 'ng-dirty' class and set the control to its pristine
 29718    * This method can be called to remove the `ng-dirty` class and set the control to its pristine
 29066    * state (ng-pristine class). A model is considered to be pristine when the model has not been changed
 29719    * state (`ng-pristine` class). A model is considered to be pristine when the control
 29067    * from when first compiled within then form.
 29720    * has not been changed from when first compiled.
 29068    */
 29721    */
 29069   this.$setPristine = function () {
 29722   this.$setPristine = function() {
 29070     ctrl.$dirty = false;
 29723     ctrl.$dirty = false;
 29071     ctrl.$pristine = true;
 29724     ctrl.$pristine = true;
 29072     $animate.removeClass($element, DIRTY_CLASS);
 29725     $animate.removeClass($element, DIRTY_CLASS);
 29073     $animate.addClass($element, PRISTINE_CLASS);
 29726     $animate.addClass($element, PRISTINE_CLASS);
       
 29727   };
       
 29728 
       
 29729   /**
       
 29730    * @ngdoc method
       
 29731    * @name ngModel.NgModelController#$setDirty
       
 29732    *
       
 29733    * @description
       
 29734    * Sets the control to its dirty state.
       
 29735    *
       
 29736    * This method can be called to remove the `ng-pristine` class and set the control to its dirty
       
 29737    * state (`ng-dirty` class). A model is considered to be dirty when the control has been changed
       
 29738    * from when first compiled.
       
 29739    */
       
 29740   this.$setDirty = function() {
       
 29741     ctrl.$dirty = true;
       
 29742     ctrl.$pristine = false;
       
 29743     $animate.removeClass($element, PRISTINE_CLASS);
       
 29744     $animate.addClass($element, DIRTY_CLASS);
       
 29745     parentForm.$setDirty();
 29074   };
 29746   };
 29075 
 29747 
 29076   /**
 29748   /**
 29077    * @ngdoc method
 29749    * @ngdoc method
 29078    * @name ngModel.NgModelController#$setUntouched
 29750    * @name ngModel.NgModelController#$setUntouched
 29079    *
 29751    *
 29080    * @description
 29752    * @description
 29081    * Sets the control to its untouched state.
 29753    * Sets the control to its untouched state.
 29082    *
 29754    *
 29083    * This method can be called to remove the 'ng-touched' class and set the control to its
 29755    * This method can be called to remove the `ng-touched` class and set the control to its
 29084    * untouched state (ng-untouched class). Upon compilation, a model is set as untouched
 29756    * untouched state (`ng-untouched` class). Upon compilation, a model is set as untouched
 29085    * by default, however this function can be used to restore that state if the model has
 29757    * by default, however this function can be used to restore that state if the model has
 29086    * already been touched by the user.
 29758    * already been touched by the user.
 29087    */
 29759    */
 29088   this.$setUntouched = function() {
 29760   this.$setUntouched = function() {
 29089     ctrl.$touched = false;
 29761     ctrl.$touched = false;
 29096    * @name ngModel.NgModelController#$setTouched
 29768    * @name ngModel.NgModelController#$setTouched
 29097    *
 29769    *
 29098    * @description
 29770    * @description
 29099    * Sets the control to its touched state.
 29771    * Sets the control to its touched state.
 29100    *
 29772    *
 29101    * This method can be called to remove the 'ng-untouched' class and set the control to its
 29773    * This method can be called to remove the `ng-untouched` class and set the control to its
 29102    * touched state (ng-touched class). A model is considered to be touched when the user has
 29774    * touched state (`ng-touched` class). A model is considered to be touched when the user has
 29103    * first interacted (focussed) on the model input element and then shifted focus away (blurred)
 29775    * first focused the control element and then shifted focus away from the control (blur event).
 29104    * from the input element.
       
 29105    */
 29776    */
 29106   this.$setTouched = function() {
 29777   this.$setTouched = function() {
 29107     ctrl.$touched = true;
 29778     ctrl.$touched = true;
 29108     ctrl.$untouched = false;
 29779     ctrl.$untouched = false;
 29109     $animate.setClass($element, TOUCHED_CLASS, UNTOUCHED_CLASS);
 29780     $animate.setClass($element, TOUCHED_CLASS, UNTOUCHED_CLASS);
 29133    * <example name="ng-model-cancel-update" module="cancel-update-example">
 29804    * <example name="ng-model-cancel-update" module="cancel-update-example">
 29134    *   <file name="app.js">
 29805    *   <file name="app.js">
 29135    *     angular.module('cancel-update-example', [])
 29806    *     angular.module('cancel-update-example', [])
 29136    *
 29807    *
 29137    *     .controller('CancelUpdateController', ['$scope', function($scope) {
 29808    *     .controller('CancelUpdateController', ['$scope', function($scope) {
 29138    *       $scope.resetWithCancel = function (e) {
 29809    *       $scope.resetWithCancel = function(e) {
 29139    *         if (e.keyCode == 27) {
 29810    *         if (e.keyCode == 27) {
 29140    *           $scope.myForm.myInput1.$rollbackViewValue();
 29811    *           $scope.myForm.myInput1.$rollbackViewValue();
 29141    *           $scope.myValue = '';
 29812    *           $scope.myValue = '';
 29142    *         }
 29813    *         }
 29143    *       };
 29814    *       };
 29144    *       $scope.resetWithoutCancel = function (e) {
 29815    *       $scope.resetWithoutCancel = function(e) {
 29145    *         if (e.keyCode == 27) {
 29816    *         if (e.keyCode == 27) {
 29146    *           $scope.myValue = '';
 29817    *           $scope.myValue = '';
 29147    *         }
 29818    *         }
 29148    *       };
 29819    *       };
 29149    *     }]);
 29820    *     }]);
 29177   /**
 29848   /**
 29178    * @ngdoc method
 29849    * @ngdoc method
 29179    * @name ngModel.NgModelController#$validate
 29850    * @name ngModel.NgModelController#$validate
 29180    *
 29851    *
 29181    * @description
 29852    * @description
 29182    * Runs each of the registered validators (first synchronous validators and then asynchronous validators).
 29853    * Runs each of the registered validators (first synchronous validators and then
       
 29854    * asynchronous validators).
       
 29855    * If the validity changes to invalid, the model will be set to `undefined`,
       
 29856    * unless {@link ngModelOptions `ngModelOptions.allowInvalid`} is `true`.
       
 29857    * If the validity changes to valid, it will set the model to the last available valid
       
 29858    * modelValue, i.e. either the last parsed value or the last value set from the scope.
 29183    */
 29859    */
 29184   this.$validate = function() {
 29860   this.$validate = function() {
 29185     // ignore $validate before model is initialized
 29861     // ignore $validate before model is initialized
 29186     if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) {
 29862     if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) {
 29187       return;
 29863       return;
 29188     }
 29864     }
 29189     this.$$parseAndValidate();
 29865 
       
 29866     var viewValue = ctrl.$$lastCommittedViewValue;
       
 29867     // Note: we use the $$rawModelValue as $modelValue might have been
       
 29868     // set to undefined during a view -> model update that found validation
       
 29869     // errors. We can't parse the view here, since that could change
       
 29870     // the model although neither viewValue nor the model on the scope changed
       
 29871     var modelValue = ctrl.$$rawModelValue;
       
 29872 
       
 29873     // Check if the there's a parse error, so we don't unset it accidentially
       
 29874     var parserName = ctrl.$$parserName || 'parse';
       
 29875     var parserValid = ctrl.$error[parserName] ? false : undefined;
       
 29876 
       
 29877     var prevValid = ctrl.$valid;
       
 29878     var prevModelValue = ctrl.$modelValue;
       
 29879 
       
 29880     var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid;
       
 29881 
       
 29882     ctrl.$$runValidators(parserValid, modelValue, viewValue, function(allValid) {
       
 29883       // If there was no change in validity, don't update the model
       
 29884       // This prevents changing an invalid modelValue to undefined
       
 29885       if (!allowInvalid && prevValid !== allValid) {
       
 29886         // Note: Don't check ctrl.$valid here, as we could have
       
 29887         // external validators (e.g. calculated on the server),
       
 29888         // that just call $setValidity and need the model value
       
 29889         // to calculate their validity.
       
 29890         ctrl.$modelValue = allValid ? modelValue : undefined;
       
 29891 
       
 29892         if (ctrl.$modelValue !== prevModelValue) {
       
 29893           ctrl.$$writeModelToScope();
       
 29894         }
       
 29895       }
       
 29896     });
       
 29897 
 29190   };
 29898   };
 29191 
 29899 
 29192   this.$$runValidators = function(parseValid, modelValue, viewValue, doneCallback) {
 29900   this.$$runValidators = function(parseValid, modelValue, viewValue, doneCallback) {
 29193     currentValidationRunId++;
 29901     currentValidationRunId++;
 29194     var localValidationRunId = currentValidationRunId;
 29902     var localValidationRunId = currentValidationRunId;
 29303     }
 30011     }
 29304     ctrl.$$lastCommittedViewValue = viewValue;
 30012     ctrl.$$lastCommittedViewValue = viewValue;
 29305 
 30013 
 29306     // change to dirty
 30014     // change to dirty
 29307     if (ctrl.$pristine) {
 30015     if (ctrl.$pristine) {
 29308       ctrl.$dirty = true;
 30016       this.$setDirty();
 29309       ctrl.$pristine = false;
       
 29310       $animate.removeClass($element, PRISTINE_CLASS);
       
 29311       $animate.addClass($element, DIRTY_CLASS);
       
 29312       parentForm.$setDirty();
       
 29313     }
 30017     }
 29314     this.$$parseAndValidate();
 30018     this.$$parseAndValidate();
 29315   };
 30019   };
 29316 
 30020 
 29317   this.$$parseAndValidate = function() {
 30021   this.$$parseAndValidate = function() {
 29318     var viewValue = ctrl.$$lastCommittedViewValue;
 30022     var viewValue = ctrl.$$lastCommittedViewValue;
 29319     var modelValue = viewValue;
 30023     var modelValue = viewValue;
 29320     var parserValid = isUndefined(modelValue) ? undefined : true;
 30024     var parserValid = isUndefined(modelValue) ? undefined : true;
 29321 
 30025 
 29322     if (parserValid) {
 30026     if (parserValid) {
 29323       for(var i = 0; i < ctrl.$parsers.length; i++) {
 30027       for (var i = 0; i < ctrl.$parsers.length; i++) {
 29324         modelValue = ctrl.$parsers[i](modelValue);
 30028         modelValue = ctrl.$parsers[i](modelValue);
 29325         if (isUndefined(modelValue)) {
 30029         if (isUndefined(modelValue)) {
 29326           parserValid = false;
 30030           parserValid = false;
 29327           break;
 30031           break;
 29328         }
 30032         }
 29329       }
 30033       }
 29330     }
 30034     }
 29331     if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) {
 30035     if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) {
 29332       // ctrl.$modelValue has not been touched yet...
 30036       // ctrl.$modelValue has not been touched yet...
 29333       ctrl.$modelValue = ngModelGet();
 30037       ctrl.$modelValue = ngModelGet($scope);
 29334     }
 30038     }
 29335     var prevModelValue = ctrl.$modelValue;
 30039     var prevModelValue = ctrl.$modelValue;
 29336     var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid;
 30040     var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid;
       
 30041     ctrl.$$rawModelValue = modelValue;
       
 30042 
 29337     if (allowInvalid) {
 30043     if (allowInvalid) {
 29338       ctrl.$modelValue = modelValue;
 30044       ctrl.$modelValue = modelValue;
 29339       writeToModelIfNeeded();
 30045       writeToModelIfNeeded();
 29340     }
 30046     }
 29341     ctrl.$$runValidators(parserValid, modelValue, viewValue, function(allValid) {
 30047 
       
 30048     // Pass the $$lastCommittedViewValue here, because the cached viewValue might be out of date.
       
 30049     // This can happen if e.g. $setViewValue is called from inside a parser
       
 30050     ctrl.$$runValidators(parserValid, modelValue, ctrl.$$lastCommittedViewValue, function(allValid) {
 29342       if (!allowInvalid) {
 30051       if (!allowInvalid) {
 29343         // Note: Don't check ctrl.$valid here, as we could have
 30052         // Note: Don't check ctrl.$valid here, as we could have
 29344         // external validators (e.g. calculated on the server),
 30053         // external validators (e.g. calculated on the server),
 29345         // that just call $setValidity and need the model value
 30054         // that just call $setValidity and need the model value
 29346         // to calculate their validity.
 30055         // to calculate their validity.
 29355       }
 30064       }
 29356     }
 30065     }
 29357   };
 30066   };
 29358 
 30067 
 29359   this.$$writeModelToScope = function() {
 30068   this.$$writeModelToScope = function() {
 29360     ngModelSet(ctrl.$modelValue);
 30069     ngModelSet($scope, ctrl.$modelValue);
 29361     forEach(ctrl.$viewChangeListeners, function(listener) {
 30070     forEach(ctrl.$viewChangeListeners, function(listener) {
 29362       try {
 30071       try {
 29363         listener();
 30072         listener();
 29364       } catch(e) {
 30073       } catch (e) {
 29365         $exceptionHandler(e);
 30074         $exceptionHandler(e);
 29366       }
 30075       }
 29367     });
 30076     });
 29368   };
 30077   };
 29369 
 30078 
 29451   // 3. ng-change kicks in and reverts scope value to 'a'
 30160   // 3. ng-change kicks in and reverts scope value to 'a'
 29452   //    -> scope value did not change since the last digest as
 30161   //    -> scope value did not change since the last digest as
 29453   //       ng-change executes in apply phase
 30162   //       ng-change executes in apply phase
 29454   // 4. view should be changed back to 'a'
 30163   // 4. view should be changed back to 'a'
 29455   $scope.$watch(function ngModelWatch() {
 30164   $scope.$watch(function ngModelWatch() {
 29456     var modelValue = ngModelGet();
 30165     var modelValue = ngModelGet($scope);
 29457 
 30166 
 29458     // if scope model value and ngModel value are out of sync
 30167     // if scope model value and ngModel value are out of sync
 29459     // TODO(perf): why not move this to the action fn?
 30168     // TODO(perf): why not move this to the action fn?
 29460     if (modelValue !== ctrl.$modelValue) {
 30169     if (modelValue !== ctrl.$modelValue) {
 29461       ctrl.$modelValue = modelValue;
 30170       ctrl.$modelValue = ctrl.$$rawModelValue = modelValue;
 29462 
 30171 
 29463       var formatters = ctrl.$formatters,
 30172       var formatters = ctrl.$formatters,
 29464           idx = formatters.length;
 30173           idx = formatters.length;
 29465 
 30174 
 29466       var viewValue = modelValue;
 30175       var viewValue = modelValue;
 29467       while(idx--) {
 30176       while (idx--) {
 29468         viewValue = formatters[idx](viewValue);
 30177         viewValue = formatters[idx](viewValue);
 29469       }
 30178       }
 29470       if (ctrl.$viewValue !== viewValue) {
 30179       if (ctrl.$viewValue !== viewValue) {
 29471         ctrl.$viewValue = ctrl.$$lastCommittedViewValue = viewValue;
 30180         ctrl.$viewValue = ctrl.$$lastCommittedViewValue = viewValue;
 29472         ctrl.$render();
 30181         ctrl.$render();
 29483 /**
 30192 /**
 29484  * @ngdoc directive
 30193  * @ngdoc directive
 29485  * @name ngModel
 30194  * @name ngModel
 29486  *
 30195  *
 29487  * @element input
 30196  * @element input
       
 30197  * @priority 1
 29488  *
 30198  *
 29489  * @description
 30199  * @description
 29490  * The `ngModel` directive binds an `input`,`select`, `textarea` (or custom form control) to a
 30200  * The `ngModel` directive binds an `input`,`select`, `textarea` (or custom form control) to a
 29491  * property on the scope using {@link ngModel.NgModelController NgModelController},
 30201  * property on the scope using {@link ngModel.NgModelController NgModelController},
 29492  * which is created and exposed by this directive.
 30202  * which is created and exposed by this directive.
 29504  * current scope. If the property doesn't already exist on this scope, it will be created
 30214  * current scope. If the property doesn't already exist on this scope, it will be created
 29505  * implicitly and added to the scope.
 30215  * implicitly and added to the scope.
 29506  *
 30216  *
 29507  * For best practices on using `ngModel`, see:
 30217  * For best practices on using `ngModel`, see:
 29508  *
 30218  *
 29509  *  - [https://github.com/angular/angular.js/wiki/Understanding-Scopes]
 30219  *  - [Understanding Scopes](https://github.com/angular/angular.js/wiki/Understanding-Scopes)
 29510  *
 30220  *
 29511  * For basic examples, how to use `ngModel`, see:
 30221  * For basic examples, how to use `ngModel`, see:
 29512  *
 30222  *
 29513  *  - {@link ng.directive:input input}
 30223  *  - {@link ng.directive:input input}
 29514  *    - {@link input[text] text}
 30224  *    - {@link input[text] text}
 29516  *    - {@link input[radio] radio}
 30226  *    - {@link input[radio] radio}
 29517  *    - {@link input[number] number}
 30227  *    - {@link input[number] number}
 29518  *    - {@link input[email] email}
 30228  *    - {@link input[email] email}
 29519  *    - {@link input[url] url}
 30229  *    - {@link input[url] url}
 29520  *    - {@link input[date] date}
 30230  *    - {@link input[date] date}
 29521  *    - {@link input[dateTimeLocal] dateTimeLocal}
 30231  *    - {@link input[datetime-local] datetime-local}
 29522  *    - {@link input[time] time}
 30232  *    - {@link input[time] time}
 29523  *    - {@link input[month] month}
 30233  *    - {@link input[month] month}
 29524  *    - {@link input[week] week}
 30234  *    - {@link input[week] week}
 29525  *  - {@link ng.directive:select select}
 30235  *  - {@link ng.directive:select select}
 29526  *  - {@link ng.directive:textarea textarea}
 30236  *  - {@link ng.directive:textarea textarea}
 29527  *
 30237  *
 29528  * # CSS classes
 30238  * # CSS classes
 29529  * The following CSS classes are added and removed on the associated input/select/textarea element
 30239  * The following CSS classes are added and removed on the associated input/select/textarea element
 29530  * depending on the validity of the model.
 30240  * depending on the validity of the model.
 29531  *
 30241  *
 29532  *  - `ng-valid` is set if the model is valid.
 30242  *  - `ng-valid`: the model is valid
 29533  *  - `ng-invalid` is set if the model is invalid.
 30243  *  - `ng-invalid`: the model is invalid
 29534  *  - `ng-pristine` is set if the model is pristine.
 30244  *  - `ng-valid-[key]`: for each valid key added by `$setValidity`
 29535  *  - `ng-dirty` is set if the model is dirty.
 30245  *  - `ng-invalid-[key]`: for each invalid key added by `$setValidity`
       
 30246  *  - `ng-pristine`: the control hasn't been interacted with yet
       
 30247  *  - `ng-dirty`: the control has been interacted with
       
 30248  *  - `ng-touched`: the control has been blurred
       
 30249  *  - `ng-untouched`: the control hasn't been blurred
       
 30250  *  - `ng-pending`: any `$asyncValidators` are unfulfilled
 29536  *
 30251  *
 29537  * Keep in mind that ngAnimate can detect each of these classes when added and removed.
 30252  * Keep in mind that ngAnimate can detect each of these classes when added and removed.
 29538  *
 30253  *
 29539  * ## Animation Hooks
 30254  * ## Animation Hooks
 29540  *
 30255  *
 29624      <file name="app.js">
 30339      <file name="app.js">
 29625        angular.module('getterSetterExample', [])
 30340        angular.module('getterSetterExample', [])
 29626          .controller('ExampleController', ['$scope', function($scope) {
 30341          .controller('ExampleController', ['$scope', function($scope) {
 29627            var _name = 'Brian';
 30342            var _name = 'Brian';
 29628            $scope.user = {
 30343            $scope.user = {
 29629              name: function (newName) {
 30344              name: function(newName) {
 29630                if (angular.isDefined(newName)) {
 30345                if (angular.isDefined(newName)) {
 29631                  _name = newName;
 30346                  _name = newName;
 29632                }
 30347                }
 29633                return _name;
 30348                return _name;
 29634              }
 30349              }
 29635            };
 30350            };
 29636          }]);
 30351          }]);
 29637      </file>
 30352      </file>
 29638  * </example>
 30353  * </example>
 29639  */
 30354  */
 29640 var ngModelDirective = function() {
 30355 var ngModelDirective = ['$rootScope', function($rootScope) {
 29641   return {
 30356   return {
 29642     restrict: 'A',
 30357     restrict: 'A',
 29643     require: ['ngModel', '^?form', '^?ngModelOptions'],
 30358     require: ['ngModel', '^?form', '^?ngModelOptions'],
 29644     controller: NgModelController,
 30359     controller: NgModelController,
 29645     // Prelink needs to run before any input directive
 30360     // Prelink needs to run before any input directive
 29679           }
 30394           }
 29680 
 30395 
 29681           element.on('blur', function(ev) {
 30396           element.on('blur', function(ev) {
 29682             if (modelCtrl.$touched) return;
 30397             if (modelCtrl.$touched) return;
 29683 
 30398 
 29684             scope.$apply(function() {
 30399             if ($rootScope.$$phase) {
 29685               modelCtrl.$setTouched();
 30400               scope.$evalAsync(modelCtrl.$setTouched);
 29686             });
 30401             } else {
       
 30402               scope.$apply(modelCtrl.$setTouched);
       
 30403             }
 29687           });
 30404           });
 29688         }
 30405         }
 29689       };
 30406       };
 29690     }
 30407     }
 29691   };
 30408   };
 29692 };
 30409 }];
 29693 
 30410 
 29694 
 30411 
 29695 /**
 30412 /**
 29696  * @ngdoc directive
 30413  * @ngdoc directive
 29697  * @name ngChange
 30414  * @name ngChange
 29776     require: '?ngModel',
 30493     require: '?ngModel',
 29777     link: function(scope, elm, attr, ctrl) {
 30494     link: function(scope, elm, attr, ctrl) {
 29778       if (!ctrl) return;
 30495       if (!ctrl) return;
 29779       attr.required = true; // force truthy in case we are on non input element
 30496       attr.required = true; // force truthy in case we are on non input element
 29780 
 30497 
 29781       ctrl.$validators.required = function(value) {
 30498       ctrl.$validators.required = function(modelValue, viewValue) {
 29782         return !attr.required || !ctrl.$isEmpty(value);
 30499         return !attr.required || !ctrl.$isEmpty(viewValue);
 29783       };
 30500       };
 29784 
 30501 
 29785       attr.$observe('required', function() {
 30502       attr.$observe('required', function() {
 29786         ctrl.$validate();
 30503         ctrl.$validate();
 29787       });
 30504       });
 29798       if (!ctrl) return;
 30515       if (!ctrl) return;
 29799 
 30516 
 29800       var regexp, patternExp = attr.ngPattern || attr.pattern;
 30517       var regexp, patternExp = attr.ngPattern || attr.pattern;
 29801       attr.$observe('pattern', function(regex) {
 30518       attr.$observe('pattern', function(regex) {
 29802         if (isString(regex) && regex.length > 0) {
 30519         if (isString(regex) && regex.length > 0) {
 29803           regex = new RegExp(regex);
 30520           regex = new RegExp('^' + regex + '$');
 29804         }
 30521         }
 29805 
 30522 
 29806         if (regex && !regex.test) {
 30523         if (regex && !regex.test) {
 29807           throw minErr('ngPattern')('noregexp',
 30524           throw minErr('ngPattern')('noregexp',
 29808             'Expected {0} to be a RegExp but was {1}. Element: {2}', patternExp,
 30525             'Expected {0} to be a RegExp but was {1}. Element: {2}', patternExp,
 29826     restrict: 'A',
 30543     restrict: 'A',
 29827     require: '?ngModel',
 30544     require: '?ngModel',
 29828     link: function(scope, elm, attr, ctrl) {
 30545     link: function(scope, elm, attr, ctrl) {
 29829       if (!ctrl) return;
 30546       if (!ctrl) return;
 29830 
 30547 
 29831       var maxlength = 0;
 30548       var maxlength = -1;
 29832       attr.$observe('maxlength', function(value) {
 30549       attr.$observe('maxlength', function(value) {
 29833         maxlength = int(value) || 0;
 30550         var intVal = int(value);
       
 30551         maxlength = isNaN(intVal) ? -1 : intVal;
 29834         ctrl.$validate();
 30552         ctrl.$validate();
 29835       });
 30553       });
 29836       ctrl.$validators.maxlength = function(modelValue, viewValue) {
 30554       ctrl.$validators.maxlength = function(modelValue, viewValue) {
 29837         return ctrl.$isEmpty(modelValue) || viewValue.length <= maxlength;
 30555         return (maxlength < 0) || ctrl.$isEmpty(modelValue) || (viewValue.length <= maxlength);
 29838       };
 30556       };
 29839     }
 30557     }
 29840   };
 30558   };
 29841 };
 30559 };
 29842 
 30560 
 29851       attr.$observe('minlength', function(value) {
 30569       attr.$observe('minlength', function(value) {
 29852         minlength = int(value) || 0;
 30570         minlength = int(value) || 0;
 29853         ctrl.$validate();
 30571         ctrl.$validate();
 29854       });
 30572       });
 29855       ctrl.$validators.minlength = function(modelValue, viewValue) {
 30573       ctrl.$validators.minlength = function(modelValue, viewValue) {
 29856         return ctrl.$isEmpty(modelValue) || viewValue.length >= minlength;
 30574         return ctrl.$isEmpty(viewValue) || viewValue.length >= minlength;
 29857       };
 30575       };
 29858     }
 30576     }
 29859   };
 30577   };
 29860 };
 30578 };
 29861 
 30579 
 29991 /**
 30709 /**
 29992  * @ngdoc directive
 30710  * @ngdoc directive
 29993  * @name ngValue
 30711  * @name ngValue
 29994  *
 30712  *
 29995  * @description
 30713  * @description
 29996  * Binds the given expression to the value of `input[select]` or `input[radio]`, so
 30714  * Binds the given expression to the value of `<option>` or {@link input[radio] `input[radio]`},
 29997  * that when the element is selected, the `ngModel` of that element is set to the
 30715  * so that when the element is selected, the {@link ngModel `ngModel`} of that element is set to
 29998  * bound value.
 30716  * the bound value.
 29999  *
 30717  *
 30000  * `ngValue` is useful when dynamically generating lists of radio buttons using `ng-repeat`, as
 30718  * `ngValue` is useful when dynamically generating lists of radio buttons using
 30001  * shown below.
 30719  * {@link ngRepeat `ngRepeat`}, as shown below.
       
 30720  *
       
 30721  * Likewise, `ngValue` can be used to generate `<option>` elements for
       
 30722  * the {@link select `select`} element. In that case however, only strings are supported
       
 30723  * for the `value `attribute, so the resulting `ngModel` will always be a string.
       
 30724  * Support for `select` models with non-string values is available via `ngOptions`.
 30002  *
 30725  *
 30003  * @element input
 30726  * @element input
 30004  * @param {string=} ngValue angular expression, whose value will be bound to the `value` attribute
 30727  * @param {string=} ngValue angular expression, whose value will be bound to the `value` attribute
 30005  *   of the `input` element
 30728  *   of the `input` element
 30006  *
 30729  *
 30084  * to have access to the updated model.
 30807  * to have access to the updated model.
 30085  *
 30808  *
 30086  * `ngModelOptions` has an effect on the element it's declared on and its descendants.
 30809  * `ngModelOptions` has an effect on the element it's declared on and its descendants.
 30087  *
 30810  *
 30088  * @param {Object} ngModelOptions options to apply to the current model. Valid keys are:
 30811  * @param {Object} ngModelOptions options to apply to the current model. Valid keys are:
 30089  *   - `updateOn`: string specifying which event should be the input bound to. You can set several
 30812  *   - `updateOn`: string specifying which event should the input be bound to. You can set several
 30090  *     events using an space delimited list. There is a special event called `default` that
 30813  *     events using an space delimited list. There is a special event called `default` that
 30091  *     matches the default events belonging of the control.
 30814  *     matches the default events belonging of the control.
 30092  *   - `debounce`: integer value which contains the debounce model update value in milliseconds. A
 30815  *   - `debounce`: integer value which contains the debounce model update value in milliseconds. A
 30093  *     value of 0 triggers an immediate update. If an object is supplied instead, you can specify a
 30816  *     value of 0 triggers an immediate update. If an object is supplied instead, you can specify a
 30094  *     custom value for each event. For example:
 30817  *     custom value for each event. For example:
 30126     <file name="app.js">
 30849     <file name="app.js">
 30127       angular.module('optionsExample', [])
 30850       angular.module('optionsExample', [])
 30128         .controller('ExampleController', ['$scope', function($scope) {
 30851         .controller('ExampleController', ['$scope', function($scope) {
 30129           $scope.user = { name: 'say', data: '' };
 30852           $scope.user = { name: 'say', data: '' };
 30130 
 30853 
 30131           $scope.cancel = function (e) {
 30854           $scope.cancel = function(e) {
 30132             if (e.keyCode == 27) {
 30855             if (e.keyCode == 27) {
 30133               $scope.userForm.userName.$rollbackViewValue();
 30856               $scope.userForm.userName.$rollbackViewValue();
 30134             }
 30857             }
 30135           };
 30858           };
 30136         }]);
 30859         }]);
 30200     <file name="app.js">
 30923     <file name="app.js">
 30201       angular.module('getterSetterExample', [])
 30924       angular.module('getterSetterExample', [])
 30202         .controller('ExampleController', ['$scope', function($scope) {
 30925         .controller('ExampleController', ['$scope', function($scope) {
 30203           var _name = 'Brian';
 30926           var _name = 'Brian';
 30204           $scope.user = {
 30927           $scope.user = {
 30205             name: function (newName) {
 30928             name: function(newName) {
 30206               return angular.isDefined(newName) ? (_name = newName) : _name;
 30929               return angular.isDefined(newName) ? (_name = newName) : _name;
 30207             }
 30930             }
 30208           };
 30931           };
 30209         }]);
 30932         }]);
 30210     </file>
 30933     </file>
 30423  * Try it here: enter text in text box and watch the greeting change.
 31146  * Try it here: enter text in text box and watch the greeting change.
 30424    <example module="bindExample">
 31147    <example module="bindExample">
 30425      <file name="index.html">
 31148      <file name="index.html">
 30426        <script>
 31149        <script>
 30427          angular.module('bindExample', [])
 31150          angular.module('bindExample', [])
 30428            .controller('ExampleController', ['$scope', function ($scope) {
 31151            .controller('ExampleController', ['$scope', function($scope) {
 30429              $scope.salutation = 'Hello';
 31152              $scope.salutation = 'Hello';
 30430              $scope.name = 'World';
 31153              $scope.name = 'World';
 30431            }]);
 31154            }]);
 30432        </script>
 31155        </script>
 30433        <div ng-controller="ExampleController">
 31156        <div ng-controller="ExampleController">
 30474 /**
 31197 /**
 30475  * @ngdoc directive
 31198  * @ngdoc directive
 30476  * @name ngBindHtml
 31199  * @name ngBindHtml
 30477  *
 31200  *
 30478  * @description
 31201  * @description
 30479  * Creates a binding that will innerHTML the result of evaluating the `expression` into the current
 31202  * Evaluates the expression and inserts the resulting HTML into the element in a secure way. By default,
 30480  * element in a secure way.  By default, the innerHTML-ed content will be sanitized using the {@link
 31203  * the resulting HTML content will be sanitized using the {@link ngSanitize.$sanitize $sanitize} service.
 30481  * ngSanitize.$sanitize $sanitize} service.  To utilize this functionality, ensure that `$sanitize`
 31204  * To utilize this functionality, ensure that `$sanitize` is available, for example, by including {@link
 30482  * is available, for example, by including {@link ngSanitize} in your module's dependencies (not in
 31205  * ngSanitize} in your module's dependencies (not in core Angular). In order to use {@link ngSanitize}
 30483  * core Angular). In order to use {@link ngSanitize} in your module's dependencies, you need to
 31206  * in your module's dependencies, you need to include "angular-sanitize.js" in your application.
 30484  * include "angular-sanitize.js" in your application.
       
 30485  *
 31207  *
 30486  * You may also bypass sanitization for values you know are safe. To do so, bind to
 31208  * You may also bypass sanitization for values you know are safe. To do so, bind to
 30487  * an explicitly trusted value via {@link ng.$sce#trustAsHtml $sce.trustAsHtml}.  See the example
 31209  * an explicitly trusted value via {@link ng.$sce#trustAsHtml $sce.trustAsHtml}.  See the example
 30488  * under {@link ng.$sce#Example Strict Contextual Escaping (SCE)}.
 31210  * under {@link ng.$sce#show-me-an-example-using-sce- Strict Contextual Escaping (SCE)}.
 30489  *
 31211  *
 30490  * Note: If a `$sanitize` service is unavailable and the bound value isn't explicitly trusted, you
 31212  * Note: If a `$sanitize` service is unavailable and the bound value isn't explicitly trusted, you
 30491  * will have an exception (instead of an exploit.)
 31213  * will have an exception (instead of an exploit.)
 30492  *
 31214  *
 30493  * @element ANY
 31215  * @element ANY
 30578         function removeClasses(classes) {
 31300         function removeClasses(classes) {
 30579           var newClasses = digestClassCounts(classes, -1);
 31301           var newClasses = digestClassCounts(classes, -1);
 30580           attr.$removeClass(newClasses);
 31302           attr.$removeClass(newClasses);
 30581         }
 31303         }
 30582 
 31304 
 30583         function digestClassCounts (classes, count) {
 31305         function digestClassCounts(classes, count) {
 30584           var classCounts = element.data('$classCounts') || {};
 31306           var classCounts = element.data('$classCounts') || {};
 30585           var classesToUpdate = [];
 31307           var classesToUpdate = [];
 30586           forEach(classes, function (className) {
 31308           forEach(classes, function(className) {
 30587             if (count > 0 || classCounts[className]) {
 31309             if (count > 0 || classCounts[className]) {
 30588               classCounts[className] = (classCounts[className] || 0) + count;
 31310               classCounts[className] = (classCounts[className] || 0) + count;
 30589               if (classCounts[className] === +(count > 0)) {
 31311               if (classCounts[className] === +(count > 0)) {
 30590                 classesToUpdate.push(className);
 31312                 classesToUpdate.push(className);
 30591               }
 31313               }
 30593           });
 31315           });
 30594           element.data('$classCounts', classCounts);
 31316           element.data('$classCounts', classCounts);
 30595           return classesToUpdate.join(' ');
 31317           return classesToUpdate.join(' ');
 30596         }
 31318         }
 30597 
 31319 
 30598         function updateClasses (oldClasses, newClasses) {
 31320         function updateClasses(oldClasses, newClasses) {
 30599           var toAdd = arrayDifference(newClasses, oldClasses);
 31321           var toAdd = arrayDifference(newClasses, oldClasses);
 30600           var toRemove = arrayDifference(oldClasses, newClasses);
 31322           var toRemove = arrayDifference(oldClasses, newClasses);
 30601           toAdd = digestClassCounts(toAdd, 1);
 31323           toAdd = digestClassCounts(toAdd, 1);
 30602           toRemove = digestClassCounts(toRemove, -1);
 31324           toRemove = digestClassCounts(toRemove, -1);
 30603           if (toAdd && toAdd.length) {
 31325           if (toAdd && toAdd.length) {
 30625 
 31347 
 30626     function arrayDifference(tokens1, tokens2) {
 31348     function arrayDifference(tokens1, tokens2) {
 30627       var values = [];
 31349       var values = [];
 30628 
 31350 
 30629       outer:
 31351       outer:
 30630       for(var i = 0; i < tokens1.length; i++) {
 31352       for (var i = 0; i < tokens1.length; i++) {
 30631         var token = tokens1[i];
 31353         var token = tokens1[i];
 30632         for(var j = 0; j < tokens2.length; j++) {
 31354         for (var j = 0; j < tokens2.length; j++) {
 30633           if(token == tokens2[j]) continue outer;
 31355           if (token == tokens2[j]) continue outer;
 30634         }
 31356         }
 30635         values.push(token);
 31357         values.push(token);
 30636       }
 31358       }
 30637       return values;
 31359       return values;
 30638     }
 31360     }
 30639 
 31361 
 30640     function arrayClasses (classVal) {
 31362     function arrayClasses(classVal) {
 30641       if (isArray(classVal)) {
 31363       if (isArray(classVal)) {
 30642         return classVal;
 31364         return classVal;
 30643       } else if (isString(classVal)) {
 31365       } else if (isString(classVal)) {
 30644         return classVal.split(' ');
 31366         return classVal.split(' ');
 30645       } else if (isObject(classVal)) {
 31367       } else if (isObject(classVal)) {
 30646         var classes = [], i = 0;
 31368         var classes = [];
 30647         forEach(classVal, function(v, k) {
 31369         forEach(classVal, function(v, k) {
 30648           if (v) {
 31370           if (v) {
 30649             classes = classes.concat(k.split(' '));
 31371             classes = classes.concat(k.split(' '));
 30650           }
 31372           }
 30651         });
 31373         });
 30795 
 31517 
 30796    ## ngClass and pre-existing CSS3 Transitions/Animations
 31518    ## ngClass and pre-existing CSS3 Transitions/Animations
 30797    The ngClass directive still supports CSS3 Transitions/Animations even if they do not follow the ngAnimate CSS naming structure.
 31519    The ngClass directive still supports CSS3 Transitions/Animations even if they do not follow the ngAnimate CSS naming structure.
 30798    Upon animation ngAnimate will apply supplementary CSS classes to track the start and end of an animation, but this will not hinder
 31520    Upon animation ngAnimate will apply supplementary CSS classes to track the start and end of an animation, but this will not hinder
 30799    any pre-existing CSS transitions already on the element. To get an idea of what happens during a class-based animation, be sure
 31521    any pre-existing CSS transitions already on the element. To get an idea of what happens during a class-based animation, be sure
 30800    to view the step by step details of {@link ngAnimate.$animate#addclass $animate.addClass} and
 31522    to view the step by step details of {@link ng.$animate#addClass $animate.addClass} and
 30801    {@link ngAnimate.$animate#removeclass $animate.removeClass}.
 31523    {@link ng.$animate#removeClass $animate.removeClass}.
 30802  */
 31524  */
 30803 var ngClassDirective = classDirective('', true);
 31525 var ngClassDirective = classDirective('', true);
 30804 
 31526 
 30805 /**
 31527 /**
 30806  * @ngdoc directive
 31528  * @ngdoc directive
 31202  *
 31924  *
 31203  * @element html
 31925  * @element html
 31204  * @description
 31926  * @description
 31205  * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.
 31927  * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.
 31206  *
 31928  *
 31207  * This is necessary when developing things like Google Chrome Extensions.
 31929  * This is necessary when developing things like Google Chrome Extensions or Universal Windows Apps.
 31208  *
 31930  *
 31209  * CSP forbids apps to use `eval` or `Function(string)` generated functions (among other things).
 31931  * CSP forbids apps to use `eval` or `Function(string)` generated functions (among other things).
 31210  * For Angular to be CSP compatible there are only two things that we need to do differently:
 31932  * For Angular to be CSP compatible there are only two things that we need to do differently:
 31211  *
 31933  *
 31212  * - don't use `Function` constructor to generate optimized value getters
 31934  * - don't use `Function` constructor to generate optimized value getters
 31400        });
 32122        });
 31401      </file>
 32123      </file>
 31402    </example>
 32124    </example>
 31403  */
 32125  */
 31404 /*
 32126 /*
 31405  * A directive that allows creation of custom onclick handlers that are defined as angular
 32127  * A collection of directives that allows creation of custom event handlers that are defined as
 31406  * expressions and are compiled and executed within the current scope.
 32128  * angular expressions and are compiled and executed within the current scope.
 31407  *
       
 31408  * Events that are handled via these handler are always configured not to propagate further.
       
 31409  */
 32129  */
 31410 var ngEventDirectives = {};
 32130 var ngEventDirectives = {};
 31411 
 32131 
 31412 // For events that might fire synchronously during DOM manipulation
 32132 // For events that might fire synchronously during DOM manipulation
 31413 // we need to execute their event handlers asynchronously using $evalAsync,
 32133 // we need to execute their event handlers asynchronously using $evalAsync,
 31422     var directiveName = directiveNormalize('ng-' + eventName);
 32142     var directiveName = directiveNormalize('ng-' + eventName);
 31423     ngEventDirectives[directiveName] = ['$parse', '$rootScope', function($parse, $rootScope) {
 32143     ngEventDirectives[directiveName] = ['$parse', '$rootScope', function($parse, $rootScope) {
 31424       return {
 32144       return {
 31425         restrict: 'A',
 32145         restrict: 'A',
 31426         compile: function($element, attr) {
 32146         compile: function($element, attr) {
 31427           var fn = $parse(attr[directiveName]);
 32147           // We expose the powerful $event object on the scope that provides access to the Window,
       
 32148           // etc. that isn't protected by the fast paths in $parse.  We explicitly request better
       
 32149           // checks at the cost of speed since event handler expressions are not executed as
       
 32150           // frequently as regular change detection.
       
 32151           var fn = $parse(attr[directiveName], /* interceptorFn */ null, /* expensiveChecks */ true);
 31428           return function ngEventHandler(scope, element) {
 32152           return function ngEventHandler(scope, element) {
 31429             element.on(eventName, function(event) {
 32153             element.on(eventName, function(event) {
 31430               var callback = function() {
 32154               var callback = function() {
 31431                 fn(scope, {$event:event});
 32155                 fn(scope, {$event:event});
 31432               };
 32156               };
 31898   <example module="ngAnimate" deps="angular-animate.js" animations="true">
 32622   <example module="ngAnimate" deps="angular-animate.js" animations="true">
 31899     <file name="index.html">
 32623     <file name="index.html">
 31900       Click me: <input type="checkbox" ng-model="checked" ng-init="checked=true" /><br/>
 32624       Click me: <input type="checkbox" ng-model="checked" ng-init="checked=true" /><br/>
 31901       Show when checked:
 32625       Show when checked:
 31902       <span ng-if="checked" class="animate-if">
 32626       <span ng-if="checked" class="animate-if">
 31903         I'm removed when the checkbox is unchecked.
 32627         This is removed when the checkbox is unchecked.
 31904       </span>
 32628       </span>
 31905     </file>
 32629     </file>
 31906     <file name="animations.css">
 32630     <file name="animations.css">
 31907       .animate-if {
 32631       .animate-if {
 31908         background:white;
 32632         background:white;
 31933     transclude: 'element',
 32657     transclude: 'element',
 31934     priority: 600,
 32658     priority: 600,
 31935     terminal: true,
 32659     terminal: true,
 31936     restrict: 'A',
 32660     restrict: 'A',
 31937     $$tlb: true,
 32661     $$tlb: true,
 31938     link: function ($scope, $element, $attr, ctrl, $transclude) {
 32662     link: function($scope, $element, $attr, ctrl, $transclude) {
 31939         var block, childScope, previousElements;
 32663         var block, childScope, previousElements;
 31940         $scope.$watch($attr.ngIf, function ngIfWatchAction(value) {
 32664         $scope.$watch($attr.ngIf, function ngIfWatchAction(value) {
 31941 
 32665 
 31942           if (value) {
 32666           if (value) {
 31943             if (!childScope) {
 32667             if (!childScope) {
 31944               $transclude(function (clone, newScope) {
 32668               $transclude(function(clone, newScope) {
 31945                 childScope = newScope;
 32669                 childScope = newScope;
 31946                 clone[clone.length++] = document.createComment(' end ngIf: ' + $attr.ngIf + ' ');
 32670                 clone[clone.length++] = document.createComment(' end ngIf: ' + $attr.ngIf + ' ');
 31947                 // Note: We only need the first/last node of the cloned nodes.
 32671                 // Note: We only need the first/last node of the cloned nodes.
 31948                 // However, we need to keep the reference to the jqlite wrapper as it might be changed later
 32672                 // However, we need to keep the reference to the jqlite wrapper as it might be changed later
 31949                 // by a directive with templateUrl when its template arrives.
 32673                 // by a directive with templateUrl when its template arrives.
 31952                 };
 32676                 };
 31953                 $animate.enter(clone, $element.parent(), $element);
 32677                 $animate.enter(clone, $element.parent(), $element);
 31954               });
 32678               });
 31955             }
 32679             }
 31956           } else {
 32680           } else {
 31957             if(previousElements) {
 32681             if (previousElements) {
 31958               previousElements.remove();
 32682               previousElements.remove();
 31959               previousElements = null;
 32683               previousElements = null;
 31960             }
 32684             }
 31961             if(childScope) {
 32685             if (childScope) {
 31962               childScope.$destroy();
 32686               childScope.$destroy();
 31963               childScope = null;
 32687               childScope = null;
 31964             }
 32688             }
 31965             if(block) {
 32689             if (block) {
 31966               previousElements = getBlockNodes(block.clone);
 32690               previousElements = getBlockNodes(block.clone);
 31967               $animate.leave(previousElements).then(function() {
 32691               $animate.leave(previousElements).then(function() {
 31968                 previousElements = null;
 32692                 previousElements = null;
 31969               });
 32693               });
 31970               block = null;
 32694               block = null;
 31982  *
 32706  *
 31983  * @description
 32707  * @description
 31984  * Fetches, compiles and includes an external HTML fragment.
 32708  * Fetches, compiles and includes an external HTML fragment.
 31985  *
 32709  *
 31986  * By default, the template URL is restricted to the same domain and protocol as the
 32710  * By default, the template URL is restricted to the same domain and protocol as the
 31987  * application document. This is done by calling {@link ng.$sce#getTrustedResourceUrl
 32711  * application document. This is done by calling {@link $sce#getTrustedResourceUrl
 31988  * $sce.getTrustedResourceUrl} on it. To load templates from other domains or protocols
 32712  * $sce.getTrustedResourceUrl} on it. To load templates from other domains or protocols
 31989  * you may either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist them} or
 32713  * you may either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist them} or
 31990  * [wrap them](ng.$sce#trustAsResourceUrl) as trusted values. Refer to Angular's {@link
 32714  * {@link $sce#trustAsResourceUrl wrap them} as trusted values. Refer to Angular's {@link
 31991  * ng.$sce Strict Contextual Escaping}.
 32715  * ng.$sce Strict Contextual Escaping}.
 31992  *
 32716  *
 31993  * In addition, the browser's
 32717  * In addition, the browser's
 31994  * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest)
 32718  * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest)
 31995  * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/)
 32719  * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/)
 32171             currentScope,
 32895             currentScope,
 32172             previousElement,
 32896             previousElement,
 32173             currentElement;
 32897             currentElement;
 32174 
 32898 
 32175         var cleanupLastIncludeContent = function() {
 32899         var cleanupLastIncludeContent = function() {
 32176           if(previousElement) {
 32900           if (previousElement) {
 32177             previousElement.remove();
 32901             previousElement.remove();
 32178             previousElement = null;
 32902             previousElement = null;
 32179           }
 32903           }
 32180           if(currentScope) {
 32904           if (currentScope) {
 32181             currentScope.$destroy();
 32905             currentScope.$destroy();
 32182             currentScope = null;
 32906             currentScope = null;
 32183           }
 32907           }
 32184           if(currentElement) {
 32908           if (currentElement) {
 32185             $animate.leave(currentElement).then(function() {
 32909             $animate.leave(currentElement).then(function() {
 32186               previousElement = null;
 32910               previousElement = null;
 32187             });
 32911             });
 32188             previousElement = currentElement;
 32912             previousElement = currentElement;
 32189             currentElement = null;
 32913             currentElement = null;
 32257           // specially.
 32981           // specially.
 32258           $element.empty();
 32982           $element.empty();
 32259           $compile(jqLiteBuildFragment(ctrl.template, document).childNodes)(scope,
 32983           $compile(jqLiteBuildFragment(ctrl.template, document).childNodes)(scope,
 32260               function namespaceAdaptedClone(clone) {
 32984               function namespaceAdaptedClone(clone) {
 32261             $element.append(clone);
 32985             $element.append(clone);
 32262           }, undefined, undefined, $element);
 32986           }, {futureParentElement: $element});
 32263           return;
 32987           return;
 32264         }
 32988         }
 32265 
 32989 
 32266         $element.html(ctrl.template);
 32990         $element.html(ctrl.template);
 32267         $compile($element.contents())(scope);
 32991         $compile($element.contents())(scope);
 32541         });
 33265         });
 32542       </file>
 33266       </file>
 32543     </example>
 33267     </example>
 32544  */
 33268  */
 32545 var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {
 33269 var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {
 32546   var BRACE = /{}/g;
 33270   var BRACE = /{}/g,
       
 33271       IS_WHEN = /^when(Minus)?(.+)$/;
       
 33272 
 32547   return {
 33273   return {
 32548     restrict: 'EA',
 33274     restrict: 'EA',
 32549     link: function(scope, element, attr) {
 33275     link: function(scope, element, attr) {
 32550       var numberExp = attr.count,
 33276       var numberExp = attr.count,
 32551           whenExp = attr.$attr.when && element.attr(attr.$attr.when), // we have {{}} in attrs
 33277           whenExp = attr.$attr.when && element.attr(attr.$attr.when), // we have {{}} in attrs
 32552           offset = attr.offset || 0,
 33278           offset = attr.offset || 0,
 32553           whens = scope.$eval(whenExp) || {},
 33279           whens = scope.$eval(whenExp) || {},
 32554           whensExpFns = {},
 33280           whensExpFns = {},
 32555           startSymbol = $interpolate.startSymbol(),
 33281           startSymbol = $interpolate.startSymbol(),
 32556           endSymbol = $interpolate.endSymbol(),
 33282           endSymbol = $interpolate.endSymbol(),
 32557           isWhen = /^when(Minus)?(.+)$/;
 33283           braceReplacement = startSymbol + numberExp + '-' + offset + endSymbol,
       
 33284           watchRemover = angular.noop,
       
 33285           lastCount;
 32558 
 33286 
 32559       forEach(attr, function(expression, attributeName) {
 33287       forEach(attr, function(expression, attributeName) {
 32560         if (isWhen.test(attributeName)) {
 33288         var tmpMatch = IS_WHEN.exec(attributeName);
 32561           whens[lowercase(attributeName.replace('when', '').replace('Minus', '-'))] =
 33289         if (tmpMatch) {
 32562             element.attr(attr.$attr[attributeName]);
 33290           var whenKey = (tmpMatch[1] ? '-' : '') + lowercase(tmpMatch[2]);
       
 33291           whens[whenKey] = element.attr(attr.$attr[attributeName]);
 32563         }
 33292         }
 32564       });
 33293       });
 32565       forEach(whens, function(expression, key) {
 33294       forEach(whens, function(expression, key) {
 32566         whensExpFns[key] =
 33295         whensExpFns[key] = $interpolate(expression.replace(BRACE, braceReplacement));
 32567           $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +
 33296 
 32568             offset + endSymbol));
       
 32569       });
 33297       });
 32570 
 33298 
 32571       scope.$watch(function ngPluralizeWatch() {
 33299       scope.$watch(numberExp, function ngPluralizeWatchAction(newVal) {
 32572         var value = parseFloat(scope.$eval(numberExp));
 33300         var count = parseFloat(newVal);
 32573 
 33301         var countIsNaN = isNaN(count);
 32574         if (!isNaN(value)) {
 33302 
 32575           //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,
 33303         if (!countIsNaN && !(count in whens)) {
 32576           //check it against pluralization rules in $locale service
 33304           // If an explicit number rule such as 1, 2, 3... is defined, just use it.
 32577           if (!(value in whens)) value = $locale.pluralCat(value - offset);
 33305           // Otherwise, check it against pluralization rules in $locale service.
 32578            return whensExpFns[value](scope);
 33306           count = $locale.pluralCat(count - offset);
 32579         } else {
       
 32580           return '';
       
 32581         }
 33307         }
 32582       }, function ngPluralizeWatchAction(newVal) {
 33308 
 32583         element.text(newVal);
 33309         // If both `count` and `lastCount` are NaN, we don't need to re-register a watch.
       
 33310         // In JS `NaN !== NaN`, so we have to exlicitly check.
       
 33311         if ((count !== lastCount) && !(countIsNaN && isNaN(lastCount))) {
       
 33312           watchRemover();
       
 33313           watchRemover = scope.$watch(whensExpFns[count], updateElementText);
       
 33314           lastCount = count;
       
 33315         }
 32584       });
 33316       });
       
 33317 
       
 33318       function updateElementText(newText) {
       
 33319         element.text(newText || '');
       
 33320       }
 32585     }
 33321     }
 32586   };
 33322   };
 32587 }];
 33323 }];
 32588 
 33324 
 32589 /**
 33325 /**
 32684  *     before specifying a tracking expression.
 33420  *     before specifying a tracking expression.
 32685  *
 33421  *
 32686  *     For example: `item in items` is equivalent to `item in items track by $id(item)`. This implies that the DOM elements
 33422  *     For example: `item in items` is equivalent to `item in items track by $id(item)`. This implies that the DOM elements
 32687  *     will be associated by item identity in the array.
 33423  *     will be associated by item identity in the array.
 32688  *
 33424  *
 32689  *   * `variable in expression as alias_expression` – You can also provide an optional alias expression which will then store the
       
 32690  *     intermediate results of the repeater after the filters have been applied. Typically this is used to render a special message
       
 32691  *     when a filter is active on the repeater, but the filtered result set is empty.
       
 32692  *
       
 32693  *     For example: `item in items | filter:x as results` will store the fragment of the repeated items as `results`, but only after
       
 32694  *     the items have been processed through the filter.
       
 32695  *
       
 32696  *     For example: `item in items track by $id(item)`. A built in `$id()` function can be used to assign a unique
 33425  *     For example: `item in items track by $id(item)`. A built in `$id()` function can be used to assign a unique
 32697  *     `$$hashKey` property to each item in the array. This property is then used as a key to associated DOM elements
 33426  *     `$$hashKey` property to each item in the array. This property is then used as a key to associated DOM elements
 32698  *     with the corresponding item in the array by identity. Moving the same object in array would move the DOM
 33427  *     with the corresponding item in the array by identity. Moving the same object in array would move the DOM
 32699  *     element in the same way in the DOM.
 33428  *     element in the same way in the DOM.
 32700  *
 33429  *
 32702  *     case the object identity does not matter. Two objects are considered equivalent as long as their `id`
 33431  *     case the object identity does not matter. Two objects are considered equivalent as long as their `id`
 32703  *     property is same.
 33432  *     property is same.
 32704  *
 33433  *
 32705  *     For example: `item in items | filter:searchText track by item.id` is a pattern that might be used to apply a filter
 33434  *     For example: `item in items | filter:searchText track by item.id` is a pattern that might be used to apply a filter
 32706  *     to items in conjunction with a tracking expression.
 33435  *     to items in conjunction with a tracking expression.
       
 33436  *
       
 33437  *   * `variable in expression as alias_expression` – You can also provide an optional alias expression which will then store the
       
 33438  *     intermediate results of the repeater after the filters have been applied. Typically this is used to render a special message
       
 33439  *     when a filter is active on the repeater, but the filtered result set is empty.
       
 33440  *
       
 33441  *     For example: `item in items | filter:x as results` will store the fragment of the repeated items as `results`, but only after
       
 33442  *     the items have been processed through the filter.
 32707  *
 33443  *
 32708  * @example
 33444  * @example
 32709  * This example initializes the scope to a list of names and
 33445  * This example initializes the scope to a list of names and
 32710  * then uses `ngRepeat` to display every person:
 33446  * then uses `ngRepeat` to display every person:
 32711   <example module="ngAnimate" deps="angular-animate.js" animations="true">
 33447   <example module="ngAnimate" deps="angular-animate.js" animations="true">
 32841       var lhs = match[1];
 33577       var lhs = match[1];
 32842       var rhs = match[2];
 33578       var rhs = match[2];
 32843       var aliasAs = match[3];
 33579       var aliasAs = match[3];
 32844       var trackByExp = match[4];
 33580       var trackByExp = match[4];
 32845 
 33581 
 32846       match = lhs.match(/^(?:([\$\w]+)|\(([\$\w]+)\s*,\s*([\$\w]+)\))$/);
 33582       match = lhs.match(/^(?:(\s*[\$\w]+)|\(\s*([\$\w]+)\s*,\s*([\$\w]+)\s*\))$/);
 32847 
 33583 
 32848       if (!match) {
 33584       if (!match) {
 32849         throw ngRepeatMinErr('iidexp', "'_item_' in '_item_ in _collection_' should be an identifier or '(_key_, _value_)' expression, but got '{0}'.",
 33585         throw ngRepeatMinErr('iidexp', "'_item_' in '_item_ in _collection_' should be an identifier or '(_key_, _value_)' expression, but got '{0}'.",
 32850             lhs);
 33586             lhs);
 32851       }
 33587       }
 32862       var hashFnLocals = {$id: hashKey};
 33598       var hashFnLocals = {$id: hashKey};
 32863 
 33599 
 32864       if (trackByExp) {
 33600       if (trackByExp) {
 32865         trackByExpGetter = $parse(trackByExp);
 33601         trackByExpGetter = $parse(trackByExp);
 32866       } else {
 33602       } else {
 32867         trackByIdArrayFn = function (key, value) {
 33603         trackByIdArrayFn = function(key, value) {
 32868           return hashKey(value);
 33604           return hashKey(value);
 32869         };
 33605         };
 32870         trackByIdObjFn = function (key) {
 33606         trackByIdObjFn = function(key) {
 32871           return key;
 33607           return key;
 32872         };
 33608         };
 32873       }
 33609       }
 32874 
 33610 
 32875       return function ngRepeatLink($scope, $element, $attr, ctrl, $transclude) {
 33611       return function ngRepeatLink($scope, $element, $attr, ctrl, $transclude) {
 32945               delete lastBlockMap[trackById];
 33681               delete lastBlockMap[trackById];
 32946               nextBlockMap[trackById] = block;
 33682               nextBlockMap[trackById] = block;
 32947               nextBlockOrder[index] = block;
 33683               nextBlockOrder[index] = block;
 32948             } else if (nextBlockMap[trackById]) {
 33684             } else if (nextBlockMap[trackById]) {
 32949               // if collision detected. restore lastBlockMap and throw an error
 33685               // if collision detected. restore lastBlockMap and throw an error
 32950               forEach(nextBlockOrder, function (block) {
 33686               forEach(nextBlockOrder, function(block) {
 32951                 if (block && block.scope) lastBlockMap[block.id] = block;
 33687                 if (block && block.scope) lastBlockMap[block.id] = block;
 32952               });
 33688               });
 32953               throw ngRepeatMinErr('dupes',
 33689               throw ngRepeatMinErr('dupes',
 32954                   "Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}, Duplicate value: {2}",
 33690                   "Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}, Duplicate value: {2}",
 32955                   expression, trackById, toJson(value));
 33691                   expression, trackById, value);
 32956             } else {
 33692             } else {
 32957               // new never before seen block
 33693               // new never before seen block
 32958               nextBlockOrder[index] = {id: trackById, scope: undefined, clone: undefined};
 33694               nextBlockOrder[index] = {id: trackById, scope: undefined, clone: undefined};
 32959               nextBlockMap[trackById] = true;
 33695               nextBlockMap[trackById] = true;
 32960             }
 33696             }
 33061  * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the
 33797  * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the
 33062  * styling to change how to hide an element then it is just a matter of using !important in their own CSS code.
 33798  * styling to change how to hide an element then it is just a matter of using !important in their own CSS code.
 33063  *
 33799  *
 33064  * ### Overriding `.ng-hide`
 33800  * ### Overriding `.ng-hide`
 33065  *
 33801  *
 33066  * By default, the `.ng-hide` class will style the element with `display:none!important`. If you wish to change
 33802  * By default, the `.ng-hide` class will style the element with `display: none!important`. If you wish to change
 33067  * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`
 33803  * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`
 33068  * class in CSS:
 33804  * class in CSS:
 33069  *
 33805  *
 33070  * ```css
 33806  * ```css
 33071  * .ng-hide {
 33807  * .ng-hide {
 33072  *   /&#42; this is just another form of hiding an element &#42;/
 33808  *   /&#42; this is just another form of hiding an element &#42;/
 33073  *   display:block!important;
 33809  *   display: block!important;
 33074  *   position:absolute;
 33810  *   position: absolute;
 33075  *   top:-9999px;
 33811  *   top: -9999px;
 33076  *   left:-9999px;
 33812  *   left: -9999px;
 33077  * }
 33813  * }
 33078  * ```
 33814  * ```
 33079  *
 33815  *
 33080  * By default you don't need to override in CSS anything and the animations will work around the display style.
 33816  * By default you don't need to override in CSS anything and the animations will work around the display style.
 33081  *
 33817  *
 33091  * //a working example can be found at the bottom of this page
 33827  * //a working example can be found at the bottom of this page
 33092  * //
 33828  * //
 33093  * .my-element.ng-hide-add, .my-element.ng-hide-remove {
 33829  * .my-element.ng-hide-add, .my-element.ng-hide-remove {
 33094  *   /&#42; this is required as of 1.3x to properly
 33830  *   /&#42; this is required as of 1.3x to properly
 33095  *      apply all styling in a show/hide animation &#42;/
 33831  *      apply all styling in a show/hide animation &#42;/
 33096  *   transition:0s linear all;
 33832  *   transition: 0s linear all;
 33097  * }
 33833  * }
 33098  *
 33834  *
 33099  * .my-element.ng-hide-add-active,
 33835  * .my-element.ng-hide-add-active,
 33100  * .my-element.ng-hide-remove-active {
 33836  * .my-element.ng-hide-remove-active {
 33101  *   /&#42; the transition is defined in the active class &#42;/
 33837  *   /&#42; the transition is defined in the active class &#42;/
 33102  *   transition:1s linear all;
 33838  *   transition: 1s linear all;
 33103  * }
 33839  * }
 33104  *
 33840  *
 33105  * .my-element.ng-hide-add { ... }
 33841  * .my-element.ng-hide-add { ... }
 33106  * .my-element.ng-hide-add.ng-hide-add-active { ... }
 33842  * .my-element.ng-hide-add.ng-hide-add-active { ... }
 33107  * .my-element.ng-hide-remove { ... }
 33843  * .my-element.ng-hide-remove { ... }
 33135           <span class="glyphicon glyphicon-thumbs-down"></span> I hide when your checkbox is checked.
 33871           <span class="glyphicon glyphicon-thumbs-down"></span> I hide when your checkbox is checked.
 33136         </div>
 33872         </div>
 33137       </div>
 33873       </div>
 33138     </file>
 33874     </file>
 33139     <file name="glyphicons.css">
 33875     <file name="glyphicons.css">
 33140       @import url(//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap-glyphicons.css);
 33876       @import url(../../components/bootstrap-3.1.1/css/bootstrap.css);
 33141     </file>
 33877     </file>
 33142     <file name="animations.css">
 33878     <file name="animations.css">
 33143       .animate-show {
 33879       .animate-show {
 33144         line-height:20px;
 33880         line-height: 20px;
 33145         opacity:1;
 33881         opacity: 1;
 33146         padding:10px;
 33882         padding: 10px;
 33147         border:1px solid black;
 33883         border: 1px solid black;
 33148         background:white;
 33884         background: white;
 33149       }
 33885       }
 33150 
 33886 
 33151       .animate-show.ng-hide-add.ng-hide-add-active,
 33887       .animate-show.ng-hide-add.ng-hide-add-active,
 33152       .animate-show.ng-hide-remove.ng-hide-remove-active {
 33888       .animate-show.ng-hide-remove.ng-hide-remove-active {
 33153         -webkit-transition:all linear 0.5s;
 33889         -webkit-transition: all linear 0.5s;
 33154         transition:all linear 0.5s;
 33890         transition: all linear 0.5s;
 33155       }
 33891       }
 33156 
 33892 
 33157       .animate-show.ng-hide {
 33893       .animate-show.ng-hide {
 33158         line-height:0;
 33894         line-height: 0;
 33159         opacity:0;
 33895         opacity: 0;
 33160         padding:0 10px;
 33896         padding: 0 10px;
 33161       }
 33897       }
 33162 
 33898 
 33163       .check-element {
 33899       .check-element {
 33164         padding:10px;
 33900         padding: 10px;
 33165         border:1px solid black;
 33901         border: 1px solid black;
 33166         background:white;
 33902         background: white;
 33167       }
 33903       }
 33168     </file>
 33904     </file>
 33169     <file name="protractor.js" type="protractor">
 33905     <file name="protractor.js" type="protractor">
 33170       var thumbsUp = element(by.css('span.glyphicon-thumbs-up'));
 33906       var thumbsUp = element(by.css('span.glyphicon-thumbs-up'));
 33171       var thumbsDown = element(by.css('span.glyphicon-thumbs-down'));
 33907       var thumbsDown = element(by.css('span.glyphicon-thumbs-down'));
 33185 var ngShowDirective = ['$animate', function($animate) {
 33921 var ngShowDirective = ['$animate', function($animate) {
 33186   return {
 33922   return {
 33187     restrict: 'A',
 33923     restrict: 'A',
 33188     multiElement: true,
 33924     multiElement: true,
 33189     link: function(scope, element, attr) {
 33925     link: function(scope, element, attr) {
 33190       scope.$watch(attr.ngShow, function ngShowWatchAction(value){
 33926       scope.$watch(attr.ngShow, function ngShowWatchAction(value) {
 33191         // we're adding a temporary, animation-specific class for ng-hide since this way
 33927         // we're adding a temporary, animation-specific class for ng-hide since this way
 33192         // we can control when the element is actually displayed on screen without having
 33928         // we can control when the element is actually displayed on screen without having
 33193         // to have a global/greedy CSS selector that breaks when other animations are run.
 33929         // to have a global/greedy CSS selector that breaks when other animations are run.
 33194         // Read: https://github.com/angular/angular.js/issues/9103#issuecomment-58335845
 33930         // Read: https://github.com/angular/angular.js/issues/9103#issuecomment-58335845
 33195         $animate[value ? 'removeClass' : 'addClass'](element, NG_HIDE_CLASS, NG_HIDE_IN_PROGRESS_CLASS);
 33931         $animate[value ? 'removeClass' : 'addClass'](element, NG_HIDE_CLASS, {
       
 33932           tempClasses: NG_HIDE_IN_PROGRESS_CLASS
       
 33933         });
 33196       });
 33934       });
 33197     }
 33935     }
 33198   };
 33936   };
 33199 }];
 33937 }];
 33200 
 33938 
 33233  * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the
 33971  * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the
 33234  * styling to change how to hide an element then it is just a matter of using !important in their own CSS code.
 33972  * styling to change how to hide an element then it is just a matter of using !important in their own CSS code.
 33235  *
 33973  *
 33236  * ### Overriding `.ng-hide`
 33974  * ### Overriding `.ng-hide`
 33237  *
 33975  *
 33238  * By default, the `.ng-hide` class will style the element with `display:none!important`. If you wish to change
 33976  * By default, the `.ng-hide` class will style the element with `display: none!important`. If you wish to change
 33239  * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`
 33977  * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`
 33240  * class in CSS:
 33978  * class in CSS:
 33241  *
 33979  *
 33242  * ```css
 33980  * ```css
 33243  * .ng-hide {
 33981  * .ng-hide {
 33244  *   /&#42; this is just another form of hiding an element &#42;/
 33982  *   /&#42; this is just another form of hiding an element &#42;/
 33245  *   display:block!important;
 33983  *   display: block!important;
 33246  *   position:absolute;
 33984  *   position: absolute;
 33247  *   top:-9999px;
 33985  *   top: -9999px;
 33248  *   left:-9999px;
 33986  *   left: -9999px;
 33249  * }
 33987  * }
 33250  * ```
 33988  * ```
 33251  *
 33989  *
 33252  * By default you don't need to override in CSS anything and the animations will work around the display style.
 33990  * By default you don't need to override in CSS anything and the animations will work around the display style.
 33253  *
 33991  *
 33260  * ```css
 33998  * ```css
 33261  * //
 33999  * //
 33262  * //a working example can be found at the bottom of this page
 34000  * //a working example can be found at the bottom of this page
 33263  * //
 34001  * //
 33264  * .my-element.ng-hide-add, .my-element.ng-hide-remove {
 34002  * .my-element.ng-hide-add, .my-element.ng-hide-remove {
 33265  *   transition:0.5s linear all;
 34003  *   transition: 0.5s linear all;
 33266  * }
 34004  * }
 33267  *
 34005  *
 33268  * .my-element.ng-hide-add { ... }
 34006  * .my-element.ng-hide-add { ... }
 33269  * .my-element.ng-hide-add.ng-hide-add-active { ... }
 34007  * .my-element.ng-hide-add.ng-hide-add-active { ... }
 33270  * .my-element.ng-hide-remove { ... }
 34008  * .my-element.ng-hide-remove { ... }
 33298           <span class="glyphicon glyphicon-thumbs-down"></span> I hide when your checkbox is checked.
 34036           <span class="glyphicon glyphicon-thumbs-down"></span> I hide when your checkbox is checked.
 33299         </div>
 34037         </div>
 33300       </div>
 34038       </div>
 33301     </file>
 34039     </file>
 33302     <file name="glyphicons.css">
 34040     <file name="glyphicons.css">
 33303       @import url(//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap-glyphicons.css);
 34041       @import url(../../components/bootstrap-3.1.1/css/bootstrap.css);
 33304     </file>
 34042     </file>
 33305     <file name="animations.css">
 34043     <file name="animations.css">
 33306       .animate-hide {
 34044       .animate-hide {
 33307         -webkit-transition:all linear 0.5s;
 34045         -webkit-transition: all linear 0.5s;
 33308         transition:all linear 0.5s;
 34046         transition: all linear 0.5s;
 33309         line-height:20px;
 34047         line-height: 20px;
 33310         opacity:1;
 34048         opacity: 1;
 33311         padding:10px;
 34049         padding: 10px;
 33312         border:1px solid black;
 34050         border: 1px solid black;
 33313         background:white;
 34051         background: white;
 33314       }
 34052       }
 33315 
 34053 
 33316       .animate-hide.ng-hide {
 34054       .animate-hide.ng-hide {
 33317         line-height:0;
 34055         line-height: 0;
 33318         opacity:0;
 34056         opacity: 0;
 33319         padding:0 10px;
 34057         padding: 0 10px;
 33320       }
 34058       }
 33321 
 34059 
 33322       .check-element {
 34060       .check-element {
 33323         padding:10px;
 34061         padding: 10px;
 33324         border:1px solid black;
 34062         border: 1px solid black;
 33325         background:white;
 34063         background: white;
 33326       }
 34064       }
 33327     </file>
 34065     </file>
 33328     <file name="protractor.js" type="protractor">
 34066     <file name="protractor.js" type="protractor">
 33329       var thumbsUp = element(by.css('span.glyphicon-thumbs-up'));
 34067       var thumbsUp = element(by.css('span.glyphicon-thumbs-up'));
 33330       var thumbsDown = element(by.css('span.glyphicon-thumbs-down'));
 34068       var thumbsDown = element(by.css('span.glyphicon-thumbs-down'));
 33344 var ngHideDirective = ['$animate', function($animate) {
 34082 var ngHideDirective = ['$animate', function($animate) {
 33345   return {
 34083   return {
 33346     restrict: 'A',
 34084     restrict: 'A',
 33347     multiElement: true,
 34085     multiElement: true,
 33348     link: function(scope, element, attr) {
 34086     link: function(scope, element, attr) {
 33349       scope.$watch(attr.ngHide, function ngHideWatchAction(value){
 34087       scope.$watch(attr.ngHide, function ngHideWatchAction(value) {
 33350         // The comment inside of the ngShowDirective explains why we add and
 34088         // The comment inside of the ngShowDirective explains why we add and
 33351         // remove a temporary class for the show/hide animation
 34089         // remove a temporary class for the show/hide animation
 33352         $animate[value ? 'addClass' : 'removeClass'](element,NG_HIDE_CLASS, NG_HIDE_IN_PROGRESS_CLASS);
 34090         $animate[value ? 'addClass' : 'removeClass'](element,NG_HIDE_CLASS, {
       
 34091           tempClasses: NG_HIDE_IN_PROGRESS_CLASS
       
 34092         });
 33353       });
 34093       });
 33354     }
 34094     }
 33355   };
 34095   };
 33356 }];
 34096 }];
 33357 
 34097 
 33647            $scope.title = 'Lorem Ipsum';
 34387            $scope.title = 'Lorem Ipsum';
 33648            $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';
 34388            $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';
 33649          }]);
 34389          }]);
 33650        </script>
 34390        </script>
 33651        <div ng-controller="ExampleController">
 34391        <div ng-controller="ExampleController">
 33652          <input ng-model="title"><br>
 34392          <input ng-model="title"> <br/>
 33653          <textarea ng-model="text"></textarea> <br/>
 34393          <textarea ng-model="text"></textarea> <br/>
 33654          <pane title="{{title}}">{{text}}</pane>
 34394          <pane title="{{title}}">{{text}}</pane>
 33655        </div>
 34395        </div>
 33656      </file>
 34396      </file>
 33657      <file name="protractor.js" type="protractor">
 34397      <file name="protractor.js" type="protractor">
 33725     restrict: 'E',
 34465     restrict: 'E',
 33726     terminal: true,
 34466     terminal: true,
 33727     compile: function(element, attr) {
 34467     compile: function(element, attr) {
 33728       if (attr.type == 'text/ng-template') {
 34468       if (attr.type == 'text/ng-template') {
 33729         var templateUrl = attr.id,
 34469         var templateUrl = attr.id,
 33730             // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent
       
 33731             text = element[0].text;
 34470             text = element[0].text;
 33732 
 34471 
 33733         $templateCache.put(templateUrl, text);
 34472         $templateCache.put(templateUrl, text);
 33734       }
 34473       }
 33735     }
 34474     }
 33747  *
 34486  *
 33748  * # `ngOptions`
 34487  * # `ngOptions`
 33749  *
 34488  *
 33750  * The `ngOptions` attribute can be used to dynamically generate a list of `<option>`
 34489  * The `ngOptions` attribute can be used to dynamically generate a list of `<option>`
 33751  * elements for the `<select>` element using the array or object obtained by evaluating the
 34490  * elements for the `<select>` element using the array or object obtained by evaluating the
 33752  * `ngOptions` comprehension_expression.
 34491  * `ngOptions` comprehension expression.
       
 34492  *
       
 34493  * In many cases, `ngRepeat` can be used on `<option>` elements instead of `ngOptions` to achieve a
       
 34494  * similar result. However, `ngOptions` provides some benefits such as reducing memory and
       
 34495  * increasing speed by not creating a new scope for each repeated instance, as well as providing
       
 34496  * more flexibility in how the `<select>`'s model is assigned via the `select` **`as`** part of the
       
 34497  * comprehension expression. `ngOptions` should be used when the `<select>` model needs to be bound
       
 34498  *  to a non-string value. This is because an option element can only be bound to string values at
       
 34499  * present.
 33753  *
 34500  *
 33754  * When an item in the `<select>` menu is selected, the array element or object property
 34501  * When an item in the `<select>` menu is selected, the array element or object property
 33755  * represented by the selected option will be bound to the model identified by the `ngModel`
 34502  * represented by the selected option will be bound to the model identified by the `ngModel`
 33756  * directive.
 34503  * directive.
       
 34504  *
       
 34505  * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can
       
 34506  * be nested into the `<select>` element. This element will then represent the `null` or "not selected"
       
 34507  * option. See example below for demonstration.
 33757  *
 34508  *
 33758  * <div class="alert alert-warning">
 34509  * <div class="alert alert-warning">
 33759  * **Note:** `ngModel` compares by reference, not value. This is important when binding to an
 34510  * **Note:** `ngModel` compares by reference, not value. This is important when binding to an
 33760  * array of objects. See an example [in this jsfiddle](http://jsfiddle.net/qWzTb/).
 34511  * array of objects. See an example [in this jsfiddle](http://jsfiddle.net/qWzTb/).
 33761  * </div>
 34512  * </div>
 33762  *
 34513  *
 33763  * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can
 34514  * ## `select` **`as`**
 33764  * be nested into the `<select>` element. This element will then represent the `null` or "not selected"
 34515  *
 33765  * option. See example below for demonstration.
 34516  * Using `select` **`as`** will bind the result of the `select` expression to the model, but
       
 34517  * the value of the `<select>` and `<option>` html elements will be either the index (for array data sources)
       
 34518  * or property name (for object data sources) of the value within the collection. If a **`track by`** expression
       
 34519  * is used, the result of that expression will be set as the value of the `option` and `select` elements.
       
 34520  *
       
 34521  *
       
 34522  * ### `select` **`as`** and **`track by`**
 33766  *
 34523  *
 33767  * <div class="alert alert-warning">
 34524  * <div class="alert alert-warning">
 33768  * **Note:** `ngOptions` provides an iterator facility for the `<option>` element which should be used instead
 34525  * Do not use `select` **`as`** and **`track by`** in the same expression. They are not designed to work together.
 33769  * of {@link ng.directive:ngRepeat ngRepeat} when you want the
       
 33770  * `select` model to be bound to a non-string value. This is because an option element can only
       
 33771  * be bound to string values at present.
       
 33772  * </div>
 34526  * </div>
 33773  *
 34527  *
 33774  * <div class="alert alert-info">
 34528  * Consider the following example:
 33775  * **Note:** Using `select as` will bind the result of the `select as` expression to the model, but
 34529  *
 33776  * the value of the `<select>` and `<option>` html elements will be either the index (for array data sources)
 34530  * ```html
 33777  * or property name (for object data sources) of the value  within the collection.
 34531  * <select ng-options="item.subItem as item.label for item in values track by item.id" ng-model="selected">
 33778  * </div>
 34532  * ```
       
 34533  *
       
 34534  * ```js
       
 34535  * $scope.values = [{
       
 34536  *   id: 1,
       
 34537  *   label: 'aLabel',
       
 34538  *   subItem: { name: 'aSubItem' }
       
 34539  * }, {
       
 34540  *   id: 2,
       
 34541  *   label: 'bLabel',
       
 34542  *   subItem: { name: 'bSubItem' }
       
 34543  * }];
       
 34544  *
       
 34545  * $scope.selected = { name: 'aSubItem' };
       
 34546  * ```
       
 34547  *
       
 34548  * With the purpose of preserving the selection, the **`track by`** expression is always applied to the element
       
 34549  * of the data source (to `item` in this example). To calculate whether an element is selected, we do the
       
 34550  * following:
       
 34551  *
       
 34552  * 1. Apply **`track by`** to the elements in the array. In the example: `[1, 2]`
       
 34553  * 2. Apply **`track by`** to the already selected value in `ngModel`.
       
 34554  *    In the example: this is not possible as **`track by`** refers to `item.id`, but the selected
       
 34555  *    value from `ngModel` is `{name: 'aSubItem'}`, so the **`track by`** expression is applied to
       
 34556  *    a wrong object, the selected element can't be found, `<select>` is always reset to the "not
       
 34557  *    selected" option.
       
 34558  *
 33779  *
 34559  *
 33780  * @param {string} ngModel Assignable angular expression to data-bind to.
 34560  * @param {string} ngModel Assignable angular expression to data-bind to.
 33781  * @param {string=} name Property name of the form under which the control is published.
 34561  * @param {string=} name Property name of the form under which the control is published.
 33782  * @param {string=} required The control is considered valid only if value is entered.
 34562  * @param {string=} required The control is considered valid only if value is entered.
 33783  * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
 34563  * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
 33786  * @param {comprehension_expression=} ngOptions in one of the following forms:
 34566  * @param {comprehension_expression=} ngOptions in one of the following forms:
 33787  *
 34567  *
 33788  *   * for array data sources:
 34568  *   * for array data sources:
 33789  *     * `label` **`for`** `value` **`in`** `array`
 34569  *     * `label` **`for`** `value` **`in`** `array`
 33790  *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`
 34570  *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`
 33791  *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`
 34571  *     * `label` **`group by`** `group` **`for`** `value` **`in`** `array`
 33792  *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array` **`track by`** `trackexpr`
 34572  *     * `label` **`group by`** `group` **`for`** `value` **`in`** `array` **`track by`** `trackexpr`
       
 34573  *     * `label` **`for`** `value` **`in`** `array` | orderBy:`orderexpr` **`track by`** `trackexpr`
       
 34574  *        (for including a filter with `track by`)
 33793  *   * for object data sources:
 34575  *   * for object data sources:
 33794  *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`
 34576  *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`
 33795  *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`
 34577  *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`
 33796  *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`
 34578  *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`
 33797  *     * `select` **`as`** `label` **`group by`** `group`
 34579  *     * `select` **`as`** `label` **`group by`** `group`
 33811  *      DOM element.
 34593  *      DOM element.
 33812  *   * `trackexpr`: Used when working with an array of objects. The result of this expression will be
 34594  *   * `trackexpr`: Used when working with an array of objects. The result of this expression will be
 33813  *      used to identify the objects in the array. The `trackexpr` will most likely refer to the
 34595  *      used to identify the objects in the array. The `trackexpr` will most likely refer to the
 33814  *     `value` variable (e.g. `value.propertyName`). With this the selection is preserved
 34596  *     `value` variable (e.g. `value.propertyName`). With this the selection is preserved
 33815  *      even when the options are recreated (e.g. reloaded from the server).
 34597  *      even when the options are recreated (e.g. reloaded from the server).
 33816 
       
 33817  * <div class="alert alert-info">
       
 33818  * **Note:** Using `select as` together with `trackexpr` is not possible (and will throw).
       
 33819  * Reasoning:
       
 33820  * - Example: <select ng-options="item.subItem as item.label for item in values track by item.id" ng-model="selected">
       
 33821  *   values: [{id: 1, label: 'aLabel', subItem: {name: 'aSubItem'}}, {id: 2, label: 'bLabel', subItem: {name: 'bSubItemß'}}],
       
 33822  *   $scope.selected = {name: 'aSubItem'};
       
 33823  * - track by is always applied to `value`, with purpose to preserve the selection,
       
 33824  *   (to `item` in this case)
       
 33825  * - to calculate whether an item is selected we do the following:
       
 33826  *   1. apply `track by` to the values in the array, e.g.
       
 33827  *      In the example: [1,2]
       
 33828  *   2. apply `track by` to the already selected value in `ngModel`:
       
 33829  *      In the example: this is not possible, as `track by` refers to `item.id`, but the selected
       
 33830  *      value from `ngModel` is `{name: aSubItem}`.
       
 33831  *
       
 33832  * </div>
       
 33833  *
 34598  *
 33834  * @example
 34599  * @example
 33835     <example module="selectExample">
 34600     <example module="selectExample">
 33836       <file name="index.html">
 34601       <file name="index.html">
 33837         <script>
 34602         <script>
 33937           if (unknownOption.parent()) unknownOption.remove();
 34702           if (unknownOption.parent()) unknownOption.remove();
 33938         }
 34703         }
 33939         // Workaround for https://code.google.com/p/chromium/issues/detail?id=381459
 34704         // Workaround for https://code.google.com/p/chromium/issues/detail?id=381459
 33940         // Adding an <option selected="selected"> element to a <select required="required"> should
 34705         // Adding an <option selected="selected"> element to a <select required="required"> should
 33941         // automatically select the new element
 34706         // automatically select the new element
 33942         if (element[0].hasAttribute('selected')) {
 34707         if (element && element[0].hasAttribute('selected')) {
 33943           element[0].selected = true;
 34708           element[0].selected = true;
 33944         }
 34709         }
 33945       };
 34710       };
 33946 
 34711 
 33947 
 34712 
 33948       self.removeOption = function(value) {
 34713       self.removeOption = function(value) {
 33949         if (this.hasOption(value)) {
 34714         if (this.hasOption(value)) {
 33950           delete optionsMap[value];
 34715           delete optionsMap[value];
 33951           if (ngModelCtrl.$viewValue == value) {
 34716           if (ngModelCtrl.$viewValue === value) {
 33952             this.renderUnknownOption(value);
 34717             this.renderUnknownOption(value);
 33953           }
 34718           }
 33954         }
 34719         }
 33955       };
 34720       };
 33956 
 34721 
 33990           optionTemplate = jqLite(document.createElement('option')),
 34755           optionTemplate = jqLite(document.createElement('option')),
 33991           optGroupTemplate =jqLite(document.createElement('optgroup')),
 34756           optGroupTemplate =jqLite(document.createElement('optgroup')),
 33992           unknownOption = optionTemplate.clone();
 34757           unknownOption = optionTemplate.clone();
 33993 
 34758 
 33994       // find "null" option
 34759       // find "null" option
 33995       for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {
 34760       for (var i = 0, children = element.children(), ii = children.length; i < ii; i++) {
 33996         if (children[i].value === '') {
 34761         if (children[i].value === '') {
 33997           emptyOption = nullOption = children.eq(i);
 34762           emptyOption = nullOption = children.eq(i);
 33998           break;
 34763           break;
 33999         }
 34764         }
 34000       }
 34765       }
 34092             groupByFn = $parse(match[3] || ''),
 34857             groupByFn = $parse(match[3] || ''),
 34093             valueFn = $parse(match[2] ? match[1] : valueName),
 34858             valueFn = $parse(match[2] ? match[1] : valueName),
 34094             valuesFn = $parse(match[7]),
 34859             valuesFn = $parse(match[7]),
 34095             track = match[8],
 34860             track = match[8],
 34096             trackFn = track ? $parse(match[8]) : null,
 34861             trackFn = track ? $parse(match[8]) : null,
       
 34862             trackKeysCache = {},
 34097             // This is an array of array of existing option groups in DOM.
 34863             // This is an array of array of existing option groups in DOM.
 34098             // We try to reuse these if possible
 34864             // We try to reuse these if possible
 34099             // - optionGroupsCache[0] is the options with no option group
 34865             // - optionGroupsCache[0] is the options with no option group
 34100             // - optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element
 34866             // - optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element
 34101             optionGroupsCache = [[{element: selectElement, label:''}]],
 34867             optionGroupsCache = [[{element: selectElement, label:''}]],
 34102             //re-usable object to represent option's locals
 34868             //re-usable object to represent option's locals
 34103             locals = {};
 34869             locals = {};
 34104 
 34870 
 34105         if (trackFn && selectAsFn) {
       
 34106           throw ngOptionsMinErr('trkslct',
       
 34107             "Comprehension expression cannot contain both selectAs '{0}' " +
       
 34108             "and trackBy '{1}' expressions.",
       
 34109             selectAs, track);
       
 34110         }
       
 34111 
       
 34112         if (nullOption) {
 34871         if (nullOption) {
 34113           // compile the element since there might be bindings in it
 34872           // compile the element since there might be bindings in it
 34114           $compile(nullOption)(scope);
 34873           $compile(nullOption)(scope);
 34115 
 34874 
 34116           // remove the class, which is added automatically because we recompile the element and it
 34875           // remove the class, which is added automatically because we recompile the element and it
 34144           return exprFn(scope, locals);
 34903           return exprFn(scope, locals);
 34145         }
 34904         }
 34146 
 34905 
 34147         function selectionChanged() {
 34906         function selectionChanged() {
 34148           scope.$apply(function() {
 34907           scope.$apply(function() {
 34149             var optionGroup,
 34908             var collection = valuesFn(scope) || [];
 34150                 collection = valuesFn(scope) || [],
       
 34151                 key, value, optionElement, index, groupIndex, length, groupLength, trackIndex;
       
 34152             var viewValue;
 34909             var viewValue;
 34153             if (multiple) {
 34910             if (multiple) {
 34154               viewValue = [];
 34911               viewValue = [];
 34155               forEach(selectElement.val(), function(selectedKey) {
 34912               forEach(selectElement.val(), function(selectedKey) {
       
 34913                   selectedKey = trackFn ? trackKeysCache[selectedKey] : selectedKey;
 34156                 viewValue.push(getViewValue(selectedKey, collection[selectedKey]));
 34914                 viewValue.push(getViewValue(selectedKey, collection[selectedKey]));
 34157               });
 34915               });
 34158             } else {
 34916             } else {
 34159               var selectedKey = selectElement.val();
 34917               var selectedKey = trackFn ? trackKeysCache[selectElement.val()] : selectElement.val();
 34160               viewValue = getViewValue(selectedKey, collection[selectedKey]);
 34918               viewValue = getViewValue(selectedKey, collection[selectedKey]);
 34161             }
 34919             }
 34162             ctrl.$setViewValue(viewValue);
 34920             ctrl.$setViewValue(viewValue);
 34163             render();
 34921             render();
 34164           });
 34922           });
 34197         }
 34955         }
 34198 
 34956 
 34199         function createIsSelectedFn(viewValue) {
 34957         function createIsSelectedFn(viewValue) {
 34200           var selectedSet;
 34958           var selectedSet;
 34201           if (multiple) {
 34959           if (multiple) {
 34202             if (!selectAs && trackFn && isArray(viewValue)) {
 34960             if (trackFn && isArray(viewValue)) {
 34203 
 34961 
 34204               selectedSet = new HashMap([]);
 34962               selectedSet = new HashMap([]);
 34205               for (var trackIndex = 0; trackIndex < viewValue.length; trackIndex++) {
 34963               for (var trackIndex = 0; trackIndex < viewValue.length; trackIndex++) {
 34206                 // tracking by key
 34964                 // tracking by key
 34207                 selectedSet.put(callExpression(trackFn, null, viewValue[trackIndex]), true);
 34965                 selectedSet.put(callExpression(trackFn, null, viewValue[trackIndex]), true);
 34208               }
 34966               }
 34209             } else {
 34967             } else {
 34210               selectedSet = new HashMap(viewValue);
 34968               selectedSet = new HashMap(viewValue);
 34211             }
 34969             }
 34212           } else if (!selectAsFn && trackFn) {
 34970           } else if (trackFn) {
 34213             viewValue = callExpression(trackFn, null, viewValue);
 34971             viewValue = callExpression(trackFn, null, viewValue);
 34214           }
 34972           }
       
 34973 
 34215           return function isSelected(key, value) {
 34974           return function isSelected(key, value) {
 34216             var compareValueFn;
 34975             var compareValueFn;
 34217             if (selectAsFn) {
 34976             if (trackFn) {
       
 34977               compareValueFn = trackFn;
       
 34978             } else if (selectAsFn) {
 34218               compareValueFn = selectAsFn;
 34979               compareValueFn = selectAsFn;
 34219             } else if (trackFn) {
       
 34220               compareValueFn = trackFn;
       
 34221             } else {
 34980             } else {
 34222               compareValueFn = valueFn;
 34981               compareValueFn = valueFn;
 34223             }
 34982             }
 34224 
 34983 
 34225             if (multiple) {
 34984             if (multiple) {
 34226               return isDefined(selectedSet.remove(callExpression(compareValueFn, key, value)));
 34985               return isDefined(selectedSet.remove(callExpression(compareValueFn, key, value)));
 34227             } else {
 34986             } else {
 34228               return viewValue == callExpression(compareValueFn, key, value);
 34987               return viewValue === callExpression(compareValueFn, key, value);
 34229             }
 34988             }
 34230           };
 34989           };
 34231         }
 34990         }
 34232 
 34991 
 34233         function scheduleRendering() {
 34992         function scheduleRendering() {
 34234           if (!renderScheduled) {
 34993           if (!renderScheduled) {
 34235             scope.$$postDigest(render);
 34994             scope.$$postDigest(render);
 34236             renderScheduled = true;
 34995             renderScheduled = true;
 34237           }
 34996           }
       
 34997         }
       
 34998 
       
 34999         /**
       
 35000          * A new labelMap is created with each render.
       
 35001          * This function is called for each existing option with added=false,
       
 35002          * and each new option with added=true.
       
 35003          * - Labels that are passed to this method twice,
       
 35004          * (once with added=true and once with added=false) will end up with a value of 0, and
       
 35005          * will cause no change to happen to the corresponding option.
       
 35006          * - Labels that are passed to this method only once with added=false will end up with a
       
 35007          * value of -1 and will eventually be passed to selectCtrl.removeOption()
       
 35008          * - Labels that are passed to this method only once with added=true will end up with a
       
 35009          * value of 1 and will eventually be passed to selectCtrl.addOption()
       
 35010         */
       
 35011         function updateLabelMap(labelMap, label, added) {
       
 35012           labelMap[label] = labelMap[label] || 0;
       
 35013           labelMap[label] += (added ? 1 : -1);
 34238         }
 35014         }
 34239 
 35015 
 34240         function render() {
 35016         function render() {
 34241           renderScheduled = false;
 35017           renderScheduled = false;
 34242 
 35018 
 34252               keys = keyName ? sortedKeys(values) : values,
 35028               keys = keyName ? sortedKeys(values) : values,
 34253               key,
 35029               key,
 34254               value,
 35030               value,
 34255               groupLength, length,
 35031               groupLength, length,
 34256               groupIndex, index,
 35032               groupIndex, index,
       
 35033               labelMap = {},
 34257               selected,
 35034               selected,
 34258               isSelected = createIsSelectedFn(viewValue),
 35035               isSelected = createIsSelectedFn(viewValue),
 34259               anySelected = false,
 35036               anySelected = false,
 34260               lastElement,
 35037               lastElement,
 34261               element,
 35038               element,
 34262               label;
 35039               label,
       
 35040               optionId;
       
 35041 
       
 35042           trackKeysCache = {};
 34263 
 35043 
 34264           // We now build up the list of options we need (we merge later)
 35044           // We now build up the list of options we need (we merge later)
 34265           for (index = 0; length = keys.length, index < length; index++) {
 35045           for (index = 0; length = keys.length, index < length; index++) {
 34266             key = index;
 35046             key = index;
 34267             if (keyName) {
 35047             if (keyName) {
 34268               key = keys[index];
 35048               key = keys[index];
 34269               if ( key.charAt(0) === '$' ) continue;
 35049               if (key.charAt(0) === '$') continue;
 34270             }
 35050             }
 34271             value = values[key];
 35051             value = values[key];
 34272 
 35052 
 34273             optionGroupName = callExpression(groupByFn, key, value) || '';
 35053             optionGroupName = callExpression(groupByFn, key, value) || '';
 34274             if (!(optionGroup = optionGroups[optionGroupName])) {
 35054             if (!(optionGroup = optionGroups[optionGroupName])) {
 34281 
 35061 
 34282             label = callExpression(displayFn, key, value); // what will be seen by the user
 35062             label = callExpression(displayFn, key, value); // what will be seen by the user
 34283 
 35063 
 34284             // doing displayFn(scope, locals) || '' overwrites zero values
 35064             // doing displayFn(scope, locals) || '' overwrites zero values
 34285             label = isDefined(label) ? label : '';
 35065             label = isDefined(label) ? label : '';
       
 35066             optionId = trackFn ? trackFn(scope, locals) : (keyName ? keys[index] : index);
       
 35067             if (trackFn) {
       
 35068               trackKeysCache[optionId] = key;
       
 35069             }
       
 35070 
 34286             optionGroup.push({
 35071             optionGroup.push({
 34287               // either the index into array or key from object
 35072               // either the index into array or key from object
 34288               id: (keyName ? keys[index] : index),
 35073               id: optionId,
 34289               label: label,
 35074               label: label,
 34290               selected: selected                   // determine if we should be selected
 35075               selected: selected                   // determine if we should be selected
 34291             });
 35076             });
 34292           }
 35077           }
 34293           if (!multiple) {
 35078           if (!multiple) {
 34328                 existingParent.element.attr('label', existingParent.label = optionGroupName);
 35113                 existingParent.element.attr('label', existingParent.label = optionGroupName);
 34329               }
 35114               }
 34330             }
 35115             }
 34331 
 35116 
 34332             lastElement = null;  // start at the beginning
 35117             lastElement = null;  // start at the beginning
 34333             for(index = 0, length = optionGroup.length; index < length; index++) {
 35118             for (index = 0, length = optionGroup.length; index < length; index++) {
 34334               option = optionGroup[index];
 35119               option = optionGroup[index];
 34335               if ((existingOption = existingOptions[index+1])) {
 35120               if ((existingOption = existingOptions[index + 1])) {
 34336                 // reuse elements
 35121                 // reuse elements
 34337                 lastElement = existingOption.element;
 35122                 lastElement = existingOption.element;
 34338                 if (existingOption.label !== option.label) {
 35123                 if (existingOption.label !== option.label) {
       
 35124                   updateLabelMap(labelMap, existingOption.label, false);
       
 35125                   updateLabelMap(labelMap, option.label, true);
 34339                   lastElement.text(existingOption.label = option.label);
 35126                   lastElement.text(existingOption.label = option.label);
       
 35127                   lastElement.prop('label', existingOption.label);
 34340                 }
 35128                 }
 34341                 if (existingOption.id !== option.id) {
 35129                 if (existingOption.id !== option.id) {
 34342                   lastElement.val(existingOption.id = option.id);
 35130                   lastElement.val(existingOption.id = option.id);
 34343                 }
 35131                 }
 34344                 // lastElement.prop('selected') provided by jQuery has side-effects
 35132                 // lastElement.prop('selected') provided by jQuery has side-effects
 34364                   // rather then the element.
 35152                   // rather then the element.
 34365                   (element = optionTemplate.clone())
 35153                   (element = optionTemplate.clone())
 34366                       .val(option.id)
 35154                       .val(option.id)
 34367                       .prop('selected', option.selected)
 35155                       .prop('selected', option.selected)
 34368                       .attr('selected', option.selected)
 35156                       .attr('selected', option.selected)
       
 35157                       .prop('label', option.label)
 34369                       .text(option.label);
 35158                       .text(option.label);
 34370                 }
 35159                 }
 34371 
 35160 
 34372                 existingOptions.push(existingOption = {
 35161                 existingOptions.push(existingOption = {
 34373                     element: element,
 35162                     element: element,
 34374                     label: option.label,
 35163                     label: option.label,
 34375                     id: option.id,
 35164                     id: option.id,
 34376                     selected: option.selected
 35165                     selected: option.selected
 34377                 });
 35166                 });
 34378                 selectCtrl.addOption(option.label, element);
 35167                 updateLabelMap(labelMap, option.label, true);
 34379                 if (lastElement) {
 35168                 if (lastElement) {
 34380                   lastElement.after(element);
 35169                   lastElement.after(element);
 34381                 } else {
 35170                 } else {
 34382                   existingParent.element.append(element);
 35171                   existingParent.element.append(element);
 34383                 }
 35172                 }
 34384                 lastElement = element;
 35173                 lastElement = element;
 34385               }
 35174               }
 34386             }
 35175             }
 34387             // remove any excessive OPTIONs in a group
 35176             // remove any excessive OPTIONs in a group
 34388             index++; // increment since the existingOptions[0] is parent element not OPTION
 35177             index++; // increment since the existingOptions[0] is parent element not OPTION
 34389             while(existingOptions.length > index) {
 35178             while (existingOptions.length > index) {
 34390               option = existingOptions.pop();
 35179               option = existingOptions.pop();
 34391               selectCtrl.removeOption(option.label);
 35180               updateLabelMap(labelMap, option.label, false);
 34392               option.element.remove();
 35181               option.element.remove();
 34393             }
 35182             }
 34394           }
 35183           }
 34395           // remove any excessive OPTGROUPs from select
 35184           // remove any excessive OPTGROUPs from select
 34396           while(optionGroupsCache.length > groupIndex) {
 35185           while (optionGroupsCache.length > groupIndex) {
 34397             optionGroupsCache.pop()[0].element.remove();
 35186             // remove all the labels in the option group
       
 35187             optionGroup = optionGroupsCache.pop();
       
 35188             for (index = 1; index < optionGroup.length; ++index) {
       
 35189               updateLabelMap(labelMap, optionGroup[index].label, false);
       
 35190             }
       
 35191             optionGroup[0].element.remove();
 34398           }
 35192           }
       
 35193           forEach(labelMap, function(count, label) {
       
 35194             if (count > 0) {
       
 35195               selectCtrl.addOption(label);
       
 35196             } else if (count < 0) {
       
 35197               selectCtrl.removeOption(label);
       
 35198             }
       
 35199           });
 34399         }
 35200         }
 34400       }
 35201       }
 34401     }
 35202     }
 34402   };
 35203   };
 34403 }];
 35204 }];
 34417         if (!interpolateFn) {
 35218         if (!interpolateFn) {
 34418           attr.$set('value', element.text());
 35219           attr.$set('value', element.text());
 34419         }
 35220         }
 34420       }
 35221       }
 34421 
 35222 
 34422       return function (scope, element, attr) {
 35223       return function(scope, element, attr) {
 34423         var selectCtrlName = '$selectController',
 35224         var selectCtrlName = '$selectController',
 34424             parent = element.parent(),
 35225             parent = element.parent(),
 34425             selectCtrl = parent.data(selectCtrlName) ||
 35226             selectCtrl = parent.data(selectCtrlName) ||
 34426               parent.parent().data(selectCtrlName); // in case we are in optgroup
 35227               parent.parent().data(selectCtrlName); // in case we are in optgroup
 34427 
 35228 
 38640     "</ul>\n" +
 39441     "</ul>\n" +
 38641     "");
 39442     "");
 38642 }]);
 39443 }]);
 38643 
 39444 
 38644 /**
 39445 /**
 38645  * @license AngularJS v1.3.0-rc.5
 39446  * @license AngularJS v1.3.8
 38646  * (c) 2010-2014 Google, Inc. http://angularjs.org
 39447  * (c) 2010-2014 Google, Inc. http://angularjs.org
 38647  * License: MIT
 39448  * License: MIT
 38648  */
 39449  */
 38649 (function(window, angular, undefined) {'use strict';
 39450 (function(window, angular, undefined) {'use strict';
 38650 
 39451 
 38676  * Create a shallow copy of an object and clear other fields from the destination
 39477  * Create a shallow copy of an object and clear other fields from the destination
 38677  */
 39478  */
 38678 function shallowClearAndCopy(src, dst) {
 39479 function shallowClearAndCopy(src, dst) {
 38679   dst = dst || {};
 39480   dst = dst || {};
 38680 
 39481 
 38681   angular.forEach(dst, function(value, key){
 39482   angular.forEach(dst, function(value, key) {
 38682     delete dst[key];
 39483     delete dst[key];
 38683   });
 39484   });
 38684 
 39485 
 38685   for (var key in src) {
 39486   for (var key in src) {
 38686     if (src.hasOwnProperty(key) && !(key.charAt(0) === '$' && key.charAt(1) === '$')) {
 39487     if (src.hasOwnProperty(key) && !(key.charAt(0) === '$' && key.charAt(1) === '$')) {
 38725  * which can pose problems with server backends that do not expect that
 39526  * which can pose problems with server backends that do not expect that
 38726  * behavior.  This can be disabled by configuring the `$resourceProvider` like
 39527  * behavior.  This can be disabled by configuring the `$resourceProvider` like
 38727  * this:
 39528  * this:
 38728  *
 39529  *
 38729  * ```js
 39530  * ```js
 38730      app.config(['$resourceProvider', function ($resourceProvider) {
 39531      app.config(['$resourceProvider', function($resourceProvider) {
 38731        // Don't strip trailing slashes from calculated URLs
 39532        // Don't strip trailing slashes from calculated URLs
 38732        $resourceProvider.defaults.stripTrailingSlashes = false;
 39533        $resourceProvider.defaults.stripTrailingSlashes = false;
 38733      }]);
 39534      }]);
 38734  * ```
 39535  * ```
 38735  *
 39536  *
 38757  *   If the parameter value is prefixed with `@` then the value for that parameter will be extracted
 39558  *   If the parameter value is prefixed with `@` then the value for that parameter will be extracted
 38758  *   from the corresponding property on the `data` object (provided when calling an action method).  For
 39559  *   from the corresponding property on the `data` object (provided when calling an action method).  For
 38759  *   example, if the `defaultParam` object is `{someParam: '@someProp'}` then the value of `someParam`
 39560  *   example, if the `defaultParam` object is `{someParam: '@someProp'}` then the value of `someParam`
 38760  *   will be `data.someProp`.
 39561  *   will be `data.someProp`.
 38761  *
 39562  *
 38762  * @param {Object.<Object>=} actions Hash with declaration of custom action that should extend
 39563  * @param {Object.<Object>=} actions Hash with declaration of custom actions that should extend
 38763  *   the default set of resource actions. The declaration should be created in the format of {@link
 39564  *   the default set of resource actions. The declaration should be created in the format of {@link
 38764  *   ng.$http#usage_parameters $http.config}:
 39565  *   ng.$http#usage $http.config}:
 38765  *
 39566  *
 38766  *       {action1: {method:?, params:?, isArray:?, headers:?, ...},
 39567  *       {action1: {method:?, params:?, isArray:?, headers:?, ...},
 38767  *        action2: {method:?, params:?, isArray:?, headers:?, ...},
 39568  *        action2: {method:?, params:?, isArray:?, headers:?, ...},
 38768  *        ...}
 39569  *        ...}
 38769  *
 39570  *
 38991  *    // This will PUT /notes/ID with the note object in the request payload
 39792  *    // This will PUT /notes/ID with the note object in the request payload
 38992  *    }]);
 39793  *    }]);
 38993  * ```
 39794  * ```
 38994  */
 39795  */
 38995 angular.module('ngResource', ['ng']).
 39796 angular.module('ngResource', ['ng']).
 38996   provider('$resource', function () {
 39797   provider('$resource', function() {
 38997     var provider = this;
 39798     var provider = this;
 38998 
 39799 
 38999     this.defaults = {
 39800     this.defaults = {
 39000       // Strip slashes by default
 39801       // Strip slashes by default
 39001       stripTrailingSlashes: true,
 39802       stripTrailingSlashes: true,
 39008         'remove': {method: 'DELETE'},
 39809         'remove': {method: 'DELETE'},
 39009         'delete': {method: 'DELETE'}
 39810         'delete': {method: 'DELETE'}
 39010       }
 39811       }
 39011     };
 39812     };
 39012 
 39813 
 39013     this.$get = ['$http', '$q', function ($http, $q) {
 39814     this.$get = ['$http', '$q', function($http, $q) {
 39014 
 39815 
 39015       var noop = angular.noop,
 39816       var noop = angular.noop,
 39016         forEach = angular.forEach,
 39817         forEach = angular.forEach,
 39017         extend = angular.extend,
 39818         extend = angular.extend,
 39018         copy = angular.copy,
 39819         copy = angular.copy,
 39062         this.defaults = extend({}, provider.defaults, defaults);
 39863         this.defaults = extend({}, provider.defaults, defaults);
 39063         this.urlParams = {};
 39864         this.urlParams = {};
 39064       }
 39865       }
 39065 
 39866 
 39066       Route.prototype = {
 39867       Route.prototype = {
 39067         setUrlParams: function (config, params, actionUrl) {
 39868         setUrlParams: function(config, params, actionUrl) {
 39068           var self = this,
 39869           var self = this,
 39069             url = actionUrl || self.template,
 39870             url = actionUrl || self.template,
 39070             val,
 39871             val,
 39071             encodedVal;
 39872             encodedVal;
 39072 
 39873 
 39073           var urlParams = self.urlParams = {};
 39874           var urlParams = self.urlParams = {};
 39074           forEach(url.split(/\W/), function (param) {
 39875           forEach(url.split(/\W/), function(param) {
 39075             if (param === 'hasOwnProperty') {
 39876             if (param === 'hasOwnProperty') {
 39076               throw $resourceMinErr('badname', "hasOwnProperty is not a valid parameter name.");
 39877               throw $resourceMinErr('badname', "hasOwnProperty is not a valid parameter name.");
 39077             }
 39878             }
 39078             if (!(new RegExp("^\\d+$").test(param)) && param &&
 39879             if (!(new RegExp("^\\d+$").test(param)) && param &&
 39079               (new RegExp("(^|[^\\\\]):" + param + "(\\W|$)").test(url))) {
 39880               (new RegExp("(^|[^\\\\]):" + param + "(\\W|$)").test(url))) {
 39081             }
 39882             }
 39082           });
 39883           });
 39083           url = url.replace(/\\:/g, ':');
 39884           url = url.replace(/\\:/g, ':');
 39084 
 39885 
 39085           params = params || {};
 39886           params = params || {};
 39086           forEach(self.urlParams, function (_, urlParam) {
 39887           forEach(self.urlParams, function(_, urlParam) {
 39087             val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam];
 39888             val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam];
 39088             if (angular.isDefined(val) && val !== null) {
 39889             if (angular.isDefined(val) && val !== null) {
 39089               encodedVal = encodeUriSegment(val);
 39890               encodedVal = encodeUriSegment(val);
 39090               url = url.replace(new RegExp(":" + urlParam + "(\\W|$)", "g"), function (match, p1) {
 39891               url = url.replace(new RegExp(":" + urlParam + "(\\W|$)", "g"), function(match, p1) {
 39091                 return encodedVal + p1;
 39892                 return encodedVal + p1;
 39092               });
 39893               });
 39093             } else {
 39894             } else {
 39094               url = url.replace(new RegExp("(\/?):" + urlParam + "(\\W|$)", "g"), function (match,
 39895               url = url.replace(new RegExp("(\/?):" + urlParam + "(\\W|$)", "g"), function(match,
 39095                   leadingSlashes, tail) {
 39896                   leadingSlashes, tail) {
 39096                 if (tail.charAt(0) == '/') {
 39897                 if (tail.charAt(0) == '/') {
 39097                   return tail;
 39898                   return tail;
 39098                 } else {
 39899                 } else {
 39099                   return leadingSlashes + tail;
 39900                   return leadingSlashes + tail;
 39113           // replace escaped `/\.` with `/.`
 39914           // replace escaped `/\.` with `/.`
 39114           config.url = url.replace(/\/\\\./, '/.');
 39915           config.url = url.replace(/\/\\\./, '/.');
 39115 
 39916 
 39116 
 39917 
 39117           // set params - delegate param encoding to $http
 39918           // set params - delegate param encoding to $http
 39118           forEach(params, function (value, key) {
 39919           forEach(params, function(value, key) {
 39119             if (!self.urlParams[key]) {
 39920             if (!self.urlParams[key]) {
 39120               config.params = config.params || {};
 39921               config.params = config.params || {};
 39121               config.params[key] = value;
 39922               config.params[key] = value;
 39122             }
 39923             }
 39123           });
 39924           });
 39131         actions = extend({}, provider.defaults.actions, actions);
 39932         actions = extend({}, provider.defaults.actions, actions);
 39132 
 39933 
 39133         function extractParams(data, actionParams) {
 39934         function extractParams(data, actionParams) {
 39134           var ids = {};
 39935           var ids = {};
 39135           actionParams = extend({}, paramDefaults, actionParams);
 39936           actionParams = extend({}, paramDefaults, actionParams);
 39136           forEach(actionParams, function (value, key) {
 39937           forEach(actionParams, function(value, key) {
 39137             if (isFunction(value)) { value = value(); }
 39938             if (isFunction(value)) { value = value(); }
 39138             ids[key] = value && value.charAt && value.charAt(0) == '@' ?
 39939             ids[key] = value && value.charAt && value.charAt(0) == '@' ?
 39139               lookupDottedPath(data, value.substr(1)) : value;
 39940               lookupDottedPath(data, value.substr(1)) : value;
 39140           });
 39941           });
 39141           return ids;
 39942           return ids;
 39147 
 39948 
 39148         function Resource(value) {
 39949         function Resource(value) {
 39149           shallowClearAndCopy(value || {}, this);
 39950           shallowClearAndCopy(value || {}, this);
 39150         }
 39951         }
 39151 
 39952 
 39152         Resource.prototype.toJSON = function () {
 39953         Resource.prototype.toJSON = function() {
 39153           var data = extend({}, this);
 39954           var data = extend({}, this);
 39154           delete data.$promise;
 39955           delete data.$promise;
 39155           delete data.$resolved;
 39956           delete data.$resolved;
 39156           return data;
 39957           return data;
 39157         };
 39958         };
 39158 
 39959 
 39159         forEach(actions, function (action, name) {
 39960         forEach(actions, function(action, name) {
 39160           var hasBody = /^(POST|PUT|PATCH)$/i.test(action.method);
 39961           var hasBody = /^(POST|PUT|PATCH)$/i.test(action.method);
 39161 
 39962 
 39162           Resource[name] = function (a1, a2, a3, a4) {
 39963           Resource[name] = function(a1, a2, a3, a4) {
 39163             var params = {}, data, success, error;
 39964             var params = {}, data, success, error;
 39164 
 39965 
 39165             /* jshint -W086 */ /* (purposefully fall through case statements) */
 39966             /* jshint -W086 */ /* (purposefully fall through case statements) */
 39166             switch (arguments.length) {
 39967             switch (arguments.length) {
 39167               case 4:
 39968               case 4:
 39205             var responseInterceptor = action.interceptor && action.interceptor.response ||
 40006             var responseInterceptor = action.interceptor && action.interceptor.response ||
 39206               defaultResponseInterceptor;
 40007               defaultResponseInterceptor;
 39207             var responseErrorInterceptor = action.interceptor && action.interceptor.responseError ||
 40008             var responseErrorInterceptor = action.interceptor && action.interceptor.responseError ||
 39208               undefined;
 40009               undefined;
 39209 
 40010 
 39210             forEach(action, function (value, key) {
 40011             forEach(action, function(value, key) {
 39211               if (key != 'params' && key != 'isArray' && key != 'interceptor') {
 40012               if (key != 'params' && key != 'isArray' && key != 'interceptor') {
 39212                 httpConfig[key] = copy(value);
 40013                 httpConfig[key] = copy(value);
 39213               }
 40014               }
 39214             });
 40015             });
 39215 
 40016 
 39216             if (hasBody) httpConfig.data = data;
 40017             if (hasBody) httpConfig.data = data;
 39217             route.setUrlParams(httpConfig,
 40018             route.setUrlParams(httpConfig,
 39218               extend({}, extractParams(data, action.params || {}), params),
 40019               extend({}, extractParams(data, action.params || {}), params),
 39219               action.url);
 40020               action.url);
 39220 
 40021 
 39221             var promise = $http(httpConfig).then(function (response) {
 40022             var promise = $http(httpConfig).then(function(response) {
 39222               var data = response.data,
 40023               var data = response.data,
 39223                 promise = value.$promise;
 40024                 promise = value.$promise;
 39224 
 40025 
 39225               if (data) {
 40026               if (data) {
 39226                 // Need to convert action.isArray to boolean in case it is undefined
 40027                 // Need to convert action.isArray to boolean in case it is undefined
 39232                     angular.isArray(data) ? 'array' : 'object');
 40033                     angular.isArray(data) ? 'array' : 'object');
 39233                 }
 40034                 }
 39234                 // jshint +W018
 40035                 // jshint +W018
 39235                 if (action.isArray) {
 40036                 if (action.isArray) {
 39236                   value.length = 0;
 40037                   value.length = 0;
 39237                   forEach(data, function (item) {
 40038                   forEach(data, function(item) {
 39238                     if (typeof item === "object") {
 40039                     if (typeof item === "object") {
 39239                       value.push(new Resource(item));
 40040                       value.push(new Resource(item));
 39240                     } else {
 40041                     } else {
 39241                       // Valid JSON values may be string literals, and these should not be converted
 40042                       // Valid JSON values may be string literals, and these should not be converted
 39242                       // into objects. These items will not have access to the Resource prototype
 40043                       // into objects. These items will not have access to the Resource prototype
 39253               value.$resolved = true;
 40054               value.$resolved = true;
 39254 
 40055 
 39255               response.resource = value;
 40056               response.resource = value;
 39256 
 40057 
 39257               return response;
 40058               return response;
 39258             }, function (response) {
 40059             }, function(response) {
 39259               value.$resolved = true;
 40060               value.$resolved = true;
 39260 
 40061 
 39261               (error || noop)(response);
 40062               (error || noop)(response);
 39262 
 40063 
 39263               return $q.reject(response);
 40064               return $q.reject(response);
 39264             });
 40065             });
 39265 
 40066 
 39266             promise = promise.then(
 40067             promise = promise.then(
 39267               function (response) {
 40068               function(response) {
 39268                 var value = responseInterceptor(response);
 40069                 var value = responseInterceptor(response);
 39269                 (success || noop)(value, response.headers);
 40070                 (success || noop)(value, response.headers);
 39270                 return value;
 40071                 return value;
 39271               },
 40072               },
 39272               responseErrorInterceptor);
 40073               responseErrorInterceptor);
 39284             // instance call
 40085             // instance call
 39285             return promise;
 40086             return promise;
 39286           };
 40087           };
 39287 
 40088 
 39288 
 40089 
 39289           Resource.prototype['$' + name] = function (params, success, error) {
 40090           Resource.prototype['$' + name] = function(params, success, error) {
 39290             if (isFunction(params)) {
 40091             if (isFunction(params)) {
 39291               error = success; success = params; params = {};
 40092               error = success; success = params; params = {};
 39292             }
 40093             }
 39293             var result = Resource[name].call(this, params, this, success, error);
 40094             var result = Resource[name].call(this, params, this, success, error);
 39294             return result.$promise || result;
 40095             return result.$promise || result;
 39295           };
 40096           };
 39296         });
 40097         });
 39297 
 40098 
 39298         Resource.bind = function (additionalParamDefaults) {
 40099         Resource.bind = function(additionalParamDefaults) {
 39299           return resourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions);
 40100           return resourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions);
 39300         };
 40101         };
 39301 
 40102 
 39302         return Resource;
 40103         return Resource;
 39303       }
 40104       }
 39308 
 40109 
 39309 
 40110 
 39310 })(window, window.angular);
 40111 })(window, window.angular);
 39311 
 40112 
 39312 /**
 40113 /**
 39313  * @license AngularJS v1.3.0-rc.5
 40114  * @license AngularJS v1.3.8
 39314  * (c) 2010-2014 Google, Inc. http://angularjs.org
 40115  * (c) 2010-2014 Google, Inc. http://angularjs.org
 39315  * License: MIT
 40116  * License: MIT
 39316  */
 40117  */
 39317 (function(window, angular, undefined) {'use strict';
 40118 (function(window, angular, undefined) {'use strict';
 39318 
 40119 
 39348  * See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`.
 40149  * See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`.
 39349  *
 40150  *
 39350  * ## Dependencies
 40151  * ## Dependencies
 39351  * Requires the {@link ngRoute `ngRoute`} module to be installed.
 40152  * Requires the {@link ngRoute `ngRoute`} module to be installed.
 39352  */
 40153  */
 39353 function $RouteProvider(){
 40154 function $RouteProvider() {
 39354   function inherit(parent, extra) {
 40155   function inherit(parent, extra) {
 39355     return angular.extend(new (angular.extend(function() {}, {prototype:parent}))(), extra);
 40156     return angular.extend(Object.create(parent), extra);
 39356   }
 40157   }
 39357 
 40158 
 39358   var routes = {};
 40159   var routes = {};
 39359 
 40160 
 39360   /**
 40161   /**
 39455    *
 40256    *
 39456    * @description
 40257    * @description
 39457    * Adds a new route definition to the `$route` service.
 40258    * Adds a new route definition to the `$route` service.
 39458    */
 40259    */
 39459   this.when = function(path, route) {
 40260   this.when = function(path, route) {
       
 40261     //copy original route object to preserve params inherited from proto chain
       
 40262     var routeCopy = angular.copy(route);
       
 40263     if (angular.isUndefined(routeCopy.reloadOnSearch)) {
       
 40264       routeCopy.reloadOnSearch = true;
       
 40265     }
       
 40266     if (angular.isUndefined(routeCopy.caseInsensitiveMatch)) {
       
 40267       routeCopy.caseInsensitiveMatch = this.caseInsensitiveMatch;
       
 40268     }
 39460     routes[path] = angular.extend(
 40269     routes[path] = angular.extend(
 39461       {reloadOnSearch: true},
 40270       routeCopy,
 39462       route,
 40271       path && pathRegExp(path, routeCopy)
 39463       path && pathRegExp(path, route)
       
 39464     );
 40272     );
 39465 
 40273 
 39466     // create redirection for trailing slashes
 40274     // create redirection for trailing slashes
 39467     if (path) {
 40275     if (path) {
 39468       var redirectPath = (path[path.length-1] == '/')
 40276       var redirectPath = (path[path.length - 1] == '/')
 39469             ? path.substr(0, path.length-1)
 40277             ? path.substr(0, path.length - 1)
 39470             : path +'/';
 40278             : path + '/';
 39471 
 40279 
 39472       routes[redirectPath] = angular.extend(
 40280       routes[redirectPath] = angular.extend(
 39473         {redirectTo: path},
 40281         {redirectTo: path},
 39474         pathRegExp(redirectPath, route)
 40282         pathRegExp(redirectPath, routeCopy)
 39475       );
 40283       );
 39476     }
 40284     }
 39477 
 40285 
 39478     return this;
 40286     return this;
 39479   };
 40287   };
       
 40288 
       
 40289   /**
       
 40290    * @ngdoc property
       
 40291    * @name $routeProvider#caseInsensitiveMatch
       
 40292    * @description
       
 40293    *
       
 40294    * A boolean property indicating if routes defined
       
 40295    * using this provider should be matched using a case insensitive
       
 40296    * algorithm. Defaults to `false`.
       
 40297    */
       
 40298   this.caseInsensitiveMatch = false;
 39480 
 40299 
 39481    /**
 40300    /**
 39482     * @param path {string} path
 40301     * @param path {string} path
 39483     * @param opts {Object} options
 40302     * @param opts {Object} options
 39484     * @return {?Object}
 40303     * @return {?Object}
 39497         },
 40316         },
 39498         keys = ret.keys = [];
 40317         keys = ret.keys = [];
 39499 
 40318 
 39500     path = path
 40319     path = path
 39501       .replace(/([().])/g, '\\$1')
 40320       .replace(/([().])/g, '\\$1')
 39502       .replace(/(\/)?:(\w+)([\?\*])?/g, function(_, slash, key, option){
 40321       .replace(/(\/)?:(\w+)([\?\*])?/g, function(_, slash, key, option) {
 39503         var optional = option === '?' ? option : null;
 40322         var optional = option === '?' ? option : null;
 39504         var star = option === '*' ? option : null;
 40323         var star = option === '*' ? option : null;
 39505         keys.push({ name: key, optional: !!optional });
 40324         keys.push({ name: key, optional: !!optional });
 39506         slash = slash || '';
 40325         slash = slash || '';
 39507         return ''
 40326         return ''
 39751            * @description
 40570            * @description
 39752            * Causes `$route` service to reload the current route even if
 40571            * Causes `$route` service to reload the current route even if
 39753            * {@link ng.$location $location} hasn't changed.
 40572            * {@link ng.$location $location} hasn't changed.
 39754            *
 40573            *
 39755            * As a result of that, {@link ngRoute.directive:ngView ngView}
 40574            * As a result of that, {@link ngRoute.directive:ngView ngView}
 39756            * creates new scope, reinstantiates the controller.
 40575            * creates new scope and reinstantiates the controller.
 39757            */
 40576            */
 39758           reload: function() {
 40577           reload: function() {
 39759             forceReload = true;
 40578             forceReload = true;
 39760             $rootScope.$evalAsync(function() {
 40579             $rootScope.$evalAsync(function() {
 39761               // Don't support cancellation of a reload for now...
 40580               // Don't support cancellation of a reload for now...
 39944     /**
 40763     /**
 39945      * @returns {string} interpolation of the redirect path with the parameters
 40764      * @returns {string} interpolation of the redirect path with the parameters
 39946      */
 40765      */
 39947     function interpolate(string, params) {
 40766     function interpolate(string, params) {
 39948       var result = [];
 40767       var result = [];
 39949       angular.forEach((string||'').split(':'), function(segment, i) {
 40768       angular.forEach((string || '').split(':'), function(segment, i) {
 39950         if (i === 0) {
 40769         if (i === 0) {
 39951           result.push(segment);
 40770           result.push(segment);
 39952         } else {
 40771         } else {
 39953           var segmentMatch = segment.match(/(\w+)(.*)/);
 40772           var segmentMatch = segment.match(/(\w+)(?:[?*])?(.*)/);
 39954           var key = segmentMatch[1];
 40773           var key = segmentMatch[1];
 39955           result.push(params[key]);
 40774           result.push(params[key]);
 39956           result.push(segmentMatch[2] || '');
 40775           result.push(segmentMatch[2] || '');
 39957           delete params[key];
 40776           delete params[key];
 39958         }
 40777         }
 40079 
 40898 
 40080       <file name="animations.css">
 40899       <file name="animations.css">
 40081         .view-animate-container {
 40900         .view-animate-container {
 40082           position:relative;
 40901           position:relative;
 40083           height:100px!important;
 40902           height:100px!important;
 40084           position:relative;
       
 40085           background:white;
 40903           background:white;
 40086           border:1px solid black;
 40904           border:1px solid black;
 40087           height:40px;
 40905           height:40px;
 40088           overflow:hidden;
 40906           overflow:hidden;
 40089         }
 40907         }
 40179  * @eventType emit on the current ngView scope
 40997  * @eventType emit on the current ngView scope
 40180  * @description
 40998  * @description
 40181  * Emitted every time the ngView content is reloaded.
 40999  * Emitted every time the ngView content is reloaded.
 40182  */
 41000  */
 40183 ngViewFactory.$inject = ['$route', '$anchorScroll', '$animate'];
 41001 ngViewFactory.$inject = ['$route', '$anchorScroll', '$animate'];
 40184 function ngViewFactory(   $route,   $anchorScroll,   $animate) {
 41002 function ngViewFactory($route, $anchorScroll, $animate) {
 40185   return {
 41003   return {
 40186     restrict: 'ECA',
 41004     restrict: 'ECA',
 40187     terminal: true,
 41005     terminal: true,
 40188     priority: 400,
 41006     priority: 400,
 40189     transclude: 'element',
 41007     transclude: 'element',
 40196 
 41014 
 40197         scope.$on('$routeChangeSuccess', update);
 41015         scope.$on('$routeChangeSuccess', update);
 40198         update();
 41016         update();
 40199 
 41017 
 40200         function cleanupLastView() {
 41018         function cleanupLastView() {
 40201           if(previousLeaveAnimation) {
 41019           if (previousLeaveAnimation) {
 40202             $animate.cancel(previousLeaveAnimation);
 41020             $animate.cancel(previousLeaveAnimation);
 40203             previousLeaveAnimation = null;
 41021             previousLeaveAnimation = null;
 40204           }
 41022           }
 40205 
 41023 
 40206           if(currentScope) {
 41024           if (currentScope) {
 40207             currentScope.$destroy();
 41025             currentScope.$destroy();
 40208             currentScope = null;
 41026             currentScope = null;
 40209           }
 41027           }
 40210           if(currentElement) {
 41028           if (currentElement) {
 40211             previousLeaveAnimation = $animate.leave(currentElement);
 41029             previousLeaveAnimation = $animate.leave(currentElement);
 40212             previousLeaveAnimation.then(function() {
 41030             previousLeaveAnimation.then(function() {
 40213               previousLeaveAnimation = null;
 41031               previousLeaveAnimation = null;
 40214             });
 41032             });
 40215             currentElement = null;
 41033             currentElement = null;
 40229             // However, using ng-view on an element with additional content does not make sense...
 41047             // However, using ng-view on an element with additional content does not make sense...
 40230             // Note: We can't remove them in the cloneAttchFn of $transclude as that
 41048             // Note: We can't remove them in the cloneAttchFn of $transclude as that
 40231             // function is called before linking the content, which would apply child
 41049             // function is called before linking the content, which would apply child
 40232             // directives to non existing elements.
 41050             // directives to non existing elements.
 40233             var clone = $transclude(newScope, function(clone) {
 41051             var clone = $transclude(newScope, function(clone) {
 40234               $animate.enter(clone, null, currentElement || $element).then(function onNgViewEnter () {
 41052               $animate.enter(clone, null, currentElement || $element).then(function onNgViewEnter() {
 40235                 if (angular.isDefined(autoScrollExp)
 41053                 if (angular.isDefined(autoScrollExp)
 40236                   && (!autoScrollExp || scope.$eval(autoScrollExp))) {
 41054                   && (!autoScrollExp || scope.$eval(autoScrollExp))) {
 40237                   $anchorScroll();
 41055                   $anchorScroll();
 40238                 }
 41056                 }
 40239               });
 41057               });
 40359     },
 41177     },
 40360     controller: ['$scope', function($scope){
 41178     controller: ['$scope', function($scope){
 40361       // the index of the suggestions that's currently selected
 41179       // the index of the suggestions that's currently selected
 40362       $scope.selectedIndex = -1;
 41180       $scope.selectedIndex = -1;
 40363 
 41181 
       
 41182       $scope.initLock = true;
       
 41183 
 40364       // set new index
 41184       // set new index
 40365       $scope.setIndex = function(i){
 41185       $scope.setIndex = function(i){
 40366         $scope.selectedIndex = parseInt(i);
 41186         $scope.selectedIndex = parseInt(i);
 40367       };
 41187       };
 40368 
 41188 
 40382       $scope.completing = false;
 41202       $scope.completing = false;
 40383 
 41203 
 40384       // starts autocompleting on typing in something
 41204       // starts autocompleting on typing in something
 40385       $scope.$watch('searchParam', function(newValue, oldValue){
 41205       $scope.$watch('searchParam', function(newValue, oldValue){
 40386 
 41206 
 40387         if (oldValue === newValue || !oldValue) {
 41207         if (oldValue === newValue || (!oldValue && $scope.initLock)) {
 40388           return;
 41208           return;
 40389         }
 41209         }
 40390 
 41210 
 40391         if(watching && typeof $scope.searchParam !== 'undefined' && $scope.searchParam !== null) {
 41211         if(watching && typeof $scope.searchParam !== 'undefined' && $scope.searchParam !== null) {
 40392           $scope.completing = true;
 41212           $scope.completing = true;
 40437 
 41257 
 40438 
 41258 
 40439     }],
 41259     }],
 40440     link: function(scope, element, attrs){
 41260     link: function(scope, element, attrs){
 40441 
 41261 
       
 41262       setTimeout(function() {
       
 41263         scope.initLock = false;
       
 41264         scope.$apply();
       
 41265       }, 250);
       
 41266 
 40442       var attr = '';
 41267       var attr = '';
 40443 
 41268 
 40444       // Default atts
 41269       // Default atts
 40445       scope.attrs = {
 41270       scope.attrs = {
 40446         "placeholder": "start typing...",
 41271         "placeholder": "start typing...",
 40460       }
 41285       }
 40461 
 41286 
 40462       if (attrs.clickActivation) {
 41287       if (attrs.clickActivation) {
 40463         element[0].onclick = function(e){
 41288         element[0].onclick = function(e){
 40464           if(!scope.searchParam){
 41289           if(!scope.searchParam){
 40465             scope.completing = true;
 41290             setTimeout(function() {
 40466             scope.$apply();
 41291               scope.completing = true;
       
 41292               scope.$apply();
       
 41293             }, 200);
 40467           }
 41294           }
 40468         };
 41295         };
 40469       }
 41296       }
 40470 
 41297 
 40471       var key = {left: 37, up: 38, right: 39, down: 40 , enter: 13, esc: 27, tab: 9};
 41298       var key = {left: 37, up: 38, right: 39, down: 40 , enter: 13, esc: 27, tab: 9};
 40488         // we do a timeout to prevent hiding it before a click event is registered
 41315         // we do a timeout to prevent hiding it before a click event is registered
 40489         setTimeout(function() {
 41316         setTimeout(function() {
 40490           scope.select();
 41317           scope.select();
 40491           scope.setIndex(-1);
 41318           scope.setIndex(-1);
 40492           scope.$apply();
 41319           scope.$apply();
 40493         }, 200);
 41320         }, 150);
 40494       }, true);
 41321       }, true);
 40495 
 41322 
 40496       element[0].addEventListener("keydown",function (e){
 41323       element[0].addEventListener("keydown",function (e){
 40497         var keycode = e.keyCode || e.which;
 41324         var keycode = e.keyCode || e.which;
 40498 
 41325 
 40499         var l = angular.element(this).find('li').length;
 41326         var l = angular.element(this).find('li').length;
       
 41327 
       
 41328         // this allows submitting forms by pressing Enter in the autocompleted field
       
 41329         if(!scope.completing || l == 0) return;
 40500 
 41330 
 40501         // implementation of the up and down movement in the list of suggestions
 41331         // implementation of the up and down movement in the list of suggestions
 40502         switch (keycode){
 41332         switch (keycode){
 40503           case key.up:
 41333           case key.up:
 40504 
 41334 
 40632 */
 41462 */
 40633 
 41463 
 40634 !(function() {
 41464 !(function() {
 40635   "use strict";
 41465   "use strict";
 40636 
 41466 
 40637   var VERSION = '2.1.0';
 41467   var VERSION = '3.0.0';
 40638 
 41468 
 40639   var ENTITIES = {};
 41469   var ENTITIES = {};
 40640 
 41470 
 40641   // from http://semplicewebsites.com/removing-accents-javascript
 41471   // from http://semplicewebsites.com/removing-accents-javascript
 40642   var latin_map={"Á":"A","Ă":"A","Ắ":"A","Ặ":"A","Ằ":"A","Ẳ":"A","Ẵ":"A","Ǎ":"A","Â":"A","Ấ":"A","Ậ":"A","Ầ":"A","Ẩ":"A","Ẫ":"A","Ä":"A","Ǟ":"A","Ȧ":"A","Ǡ":"A","Ạ":"A","Ȁ":"A","À":"A","Ả":"A","Ȃ":"A","Ā":"A","Ą":"A","Å":"A","Ǻ":"A","Ḁ":"A","Ⱥ":"A","Ã":"A","Ꜳ":"AA","Æ":"AE","Ǽ":"AE","Ǣ":"AE","Ꜵ":"AO","Ꜷ":"AU","Ꜹ":"AV","Ꜻ":"AV","Ꜽ":"AY","Ḃ":"B","Ḅ":"B","Ɓ":"B","Ḇ":"B","Ƀ":"B","Ƃ":"B","Ć":"C","Č":"C","Ç":"C","Ḉ":"C","Ĉ":"C","Ċ":"C","Ƈ":"C","Ȼ":"C","Ď":"D","Ḑ":"D","Ḓ":"D","Ḋ":"D","Ḍ":"D","Ɗ":"D","Ḏ":"D","Dz":"D","Dž":"D","Đ":"D","Ƌ":"D","DZ":"DZ","DŽ":"DZ","É":"E","Ĕ":"E","Ě":"E","Ȩ":"E","Ḝ":"E","Ê":"E","Ế":"E","Ệ":"E","Ề":"E","Ể":"E","Ễ":"E","Ḙ":"E","Ë":"E","Ė":"E","Ẹ":"E","Ȅ":"E","È":"E","Ẻ":"E","Ȇ":"E","Ē":"E","Ḗ":"E","Ḕ":"E","Ę":"E","Ɇ":"E","Ẽ":"E","Ḛ":"E","Ꝫ":"ET","Ḟ":"F","Ƒ":"F","Ǵ":"G","Ğ":"G","Ǧ":"G","Ģ":"G","Ĝ":"G","Ġ":"G","Ɠ":"G","Ḡ":"G","Ǥ":"G","Ḫ":"H","Ȟ":"H","Ḩ":"H","Ĥ":"H","Ⱨ":"H","Ḧ":"H","Ḣ":"H","Ḥ":"H","Ħ":"H","Í":"I","Ĭ":"I","Ǐ":"I","Î":"I","Ï":"I","Ḯ":"I","İ":"I","Ị":"I","Ȉ":"I","Ì":"I","Ỉ":"I","Ȋ":"I","Ī":"I","Į":"I","Ɨ":"I","Ĩ":"I","Ḭ":"I","Ꝺ":"D","Ꝼ":"F","Ᵹ":"G","Ꞃ":"R","Ꞅ":"S","Ꞇ":"T","Ꝭ":"IS","Ĵ":"J","Ɉ":"J","Ḱ":"K","Ǩ":"K","Ķ":"K","Ⱪ":"K","Ꝃ":"K","Ḳ":"K","Ƙ":"K","Ḵ":"K","Ꝁ":"K","Ꝅ":"K","Ĺ":"L","Ƚ":"L","Ľ":"L","Ļ":"L","Ḽ":"L","Ḷ":"L","Ḹ":"L","Ⱡ":"L","Ꝉ":"L","Ḻ":"L","Ŀ":"L","Ɫ":"L","Lj":"L","Ł":"L","LJ":"LJ","Ḿ":"M","Ṁ":"M","Ṃ":"M","Ɱ":"M","Ń":"N","Ň":"N","Ņ":"N","Ṋ":"N","Ṅ":"N","Ṇ":"N","Ǹ":"N","Ɲ":"N","Ṉ":"N","Ƞ":"N","Nj":"N","Ñ":"N","NJ":"NJ","Ó":"O","Ŏ":"O","Ǒ":"O","Ô":"O","Ố":"O","Ộ":"O","Ồ":"O","Ổ":"O","Ỗ":"O","Ö":"O","Ȫ":"O","Ȯ":"O","Ȱ":"O","Ọ":"O","Ő":"O","Ȍ":"O","Ò":"O","Ỏ":"O","Ơ":"O","Ớ":"O","Ợ":"O","Ờ":"O","Ở":"O","Ỡ":"O","Ȏ":"O","Ꝋ":"O","Ꝍ":"O","Ō":"O","Ṓ":"O","Ṑ":"O","Ɵ":"O","Ǫ":"O","Ǭ":"O","Ø":"O","Ǿ":"O","Õ":"O","Ṍ":"O","Ṏ":"O","Ȭ":"O","Ƣ":"OI","Ꝏ":"OO","Ɛ":"E","Ɔ":"O","Ȣ":"OU","Ṕ":"P","Ṗ":"P","Ꝓ":"P","Ƥ":"P","Ꝕ":"P","Ᵽ":"P","Ꝑ":"P","Ꝙ":"Q","Ꝗ":"Q","Ŕ":"R","Ř":"R","Ŗ":"R","Ṙ":"R","Ṛ":"R","Ṝ":"R","Ȑ":"R","Ȓ":"R","Ṟ":"R","Ɍ":"R","Ɽ":"R","Ꜿ":"C","Ǝ":"E","Ś":"S","Ṥ":"S","Š":"S","Ṧ":"S","Ş":"S","Ŝ":"S","Ș":"S","Ṡ":"S","Ṣ":"S","Ṩ":"S","ẞ":"SS","Ť":"T","Ţ":"T","Ṱ":"T","Ț":"T","Ⱦ":"T","Ṫ":"T","Ṭ":"T","Ƭ":"T","Ṯ":"T","Ʈ":"T","Ŧ":"T","Ɐ":"A","Ꞁ":"L","Ɯ":"M","Ʌ":"V","Ꜩ":"TZ","Ú":"U","Ŭ":"U","Ǔ":"U","Û":"U","Ṷ":"U","Ü":"U","Ǘ":"U","Ǚ":"U","Ǜ":"U","Ǖ":"U","Ṳ":"U","Ụ":"U","Ű":"U","Ȕ":"U","Ù":"U","Ủ":"U","Ư":"U","Ứ":"U","Ự":"U","Ừ":"U","Ử":"U","Ữ":"U","Ȗ":"U","Ū":"U","Ṻ":"U","Ų":"U","Ů":"U","Ũ":"U","Ṹ":"U","Ṵ":"U","Ꝟ":"V","Ṿ":"V","Ʋ":"V","Ṽ":"V","Ꝡ":"VY","Ẃ":"W","Ŵ":"W","Ẅ":"W","Ẇ":"W","Ẉ":"W","Ẁ":"W","Ⱳ":"W","Ẍ":"X","Ẋ":"X","Ý":"Y","Ŷ":"Y","Ÿ":"Y","Ẏ":"Y","Ỵ":"Y","Ỳ":"Y","Ƴ":"Y","Ỷ":"Y","Ỿ":"Y","Ȳ":"Y","Ɏ":"Y","Ỹ":"Y","Ź":"Z","Ž":"Z","Ẑ":"Z","Ⱬ":"Z","Ż":"Z","Ẓ":"Z","Ȥ":"Z","Ẕ":"Z","Ƶ":"Z","IJ":"IJ","Œ":"OE","ᴀ":"A","ᴁ":"AE","ʙ":"B","ᴃ":"B","ᴄ":"C","ᴅ":"D","ᴇ":"E","ꜰ":"F","ɢ":"G","ʛ":"G","ʜ":"H","ɪ":"I","ʁ":"R","ᴊ":"J","ᴋ":"K","ʟ":"L","ᴌ":"L","ᴍ":"M","ɴ":"N","ᴏ":"O","ɶ":"OE","ᴐ":"O","ᴕ":"OU","ᴘ":"P","ʀ":"R","ᴎ":"N","ᴙ":"R","ꜱ":"S","ᴛ":"T","ⱻ":"E","ᴚ":"R","ᴜ":"U","ᴠ":"V","ᴡ":"W","ʏ":"Y","ᴢ":"Z","á":"a","ă":"a","ắ":"a","ặ":"a","ằ":"a","ẳ":"a","ẵ":"a","ǎ":"a","â":"a","ấ":"a","ậ":"a","ầ":"a","ẩ":"a","ẫ":"a","ä":"a","ǟ":"a","ȧ":"a","ǡ":"a","ạ":"a","ȁ":"a","à":"a","ả":"a","ȃ":"a","ā":"a","ą":"a","ᶏ":"a","ẚ":"a","å":"a","ǻ":"a","ḁ":"a","ⱥ":"a","ã":"a","ꜳ":"aa","æ":"ae","ǽ":"ae","ǣ":"ae","ꜵ":"ao","ꜷ":"au","ꜹ":"av","ꜻ":"av","ꜽ":"ay","ḃ":"b","ḅ":"b","ɓ":"b","ḇ":"b","ᵬ":"b","ᶀ":"b","ƀ":"b","ƃ":"b","ɵ":"o","ć":"c","č":"c","ç":"c","ḉ":"c","ĉ":"c","ɕ":"c","ċ":"c","ƈ":"c","ȼ":"c","ď":"d","ḑ":"d","ḓ":"d","ȡ":"d","ḋ":"d","ḍ":"d","ɗ":"d","ᶑ":"d","ḏ":"d","ᵭ":"d","ᶁ":"d","đ":"d","ɖ":"d","ƌ":"d","ı":"i","ȷ":"j","ɟ":"j","ʄ":"j","dz":"dz","dž":"dz","é":"e","ĕ":"e","ě":"e","ȩ":"e","ḝ":"e","ê":"e","ế":"e","ệ":"e","ề":"e","ể":"e","ễ":"e","ḙ":"e","ë":"e","ė":"e","ẹ":"e","ȅ":"e","è":"e","ẻ":"e","ȇ":"e","ē":"e","ḗ":"e","ḕ":"e","ⱸ":"e","ę":"e","ᶒ":"e","ɇ":"e","ẽ":"e","ḛ":"e","ꝫ":"et","ḟ":"f","ƒ":"f","ᵮ":"f","ᶂ":"f","ǵ":"g","ğ":"g","ǧ":"g","ģ":"g","ĝ":"g","ġ":"g","ɠ":"g","ḡ":"g","ᶃ":"g","ǥ":"g","ḫ":"h","ȟ":"h","ḩ":"h","ĥ":"h","ⱨ":"h","ḧ":"h","ḣ":"h","ḥ":"h","ɦ":"h","ẖ":"h","ħ":"h","ƕ":"hv","í":"i","ĭ":"i","ǐ":"i","î":"i","ï":"i","ḯ":"i","ị":"i","ȉ":"i","ì":"i","ỉ":"i","ȋ":"i","ī":"i","į":"i","ᶖ":"i","ɨ":"i","ĩ":"i","ḭ":"i","ꝺ":"d","ꝼ":"f","ᵹ":"g","ꞃ":"r","ꞅ":"s","ꞇ":"t","ꝭ":"is","ǰ":"j","ĵ":"j","ʝ":"j","ɉ":"j","ḱ":"k","ǩ":"k","ķ":"k","ⱪ":"k","ꝃ":"k","ḳ":"k","ƙ":"k","ḵ":"k","ᶄ":"k","ꝁ":"k","ꝅ":"k","ĺ":"l","ƚ":"l","ɬ":"l","ľ":"l","ļ":"l","ḽ":"l","ȴ":"l","ḷ":"l","ḹ":"l","ⱡ":"l","ꝉ":"l","ḻ":"l","ŀ":"l","ɫ":"l","ᶅ":"l","ɭ":"l","ł":"l","lj":"lj","ſ":"s","ẜ":"s","ẛ":"s","ẝ":"s","ḿ":"m","ṁ":"m","ṃ":"m","ɱ":"m","ᵯ":"m","ᶆ":"m","ń":"n","ň":"n","ņ":"n","ṋ":"n","ȵ":"n","ṅ":"n","ṇ":"n","ǹ":"n","ɲ":"n","ṉ":"n","ƞ":"n","ᵰ":"n","ᶇ":"n","ɳ":"n","ñ":"n","nj":"nj","ó":"o","ŏ":"o","ǒ":"o","ô":"o","ố":"o","ộ":"o","ồ":"o","ổ":"o","ỗ":"o","ö":"o","ȫ":"o","ȯ":"o","ȱ":"o","ọ":"o","ő":"o","ȍ":"o","ò":"o","ỏ":"o","ơ":"o","ớ":"o","ợ":"o","ờ":"o","ở":"o","ỡ":"o","ȏ":"o","ꝋ":"o","ꝍ":"o","ⱺ":"o","ō":"o","ṓ":"o","ṑ":"o","ǫ":"o","ǭ":"o","ø":"o","ǿ":"o","õ":"o","ṍ":"o","ṏ":"o","ȭ":"o","ƣ":"oi","ꝏ":"oo","ɛ":"e","ᶓ":"e","ɔ":"o","ᶗ":"o","ȣ":"ou","ṕ":"p","ṗ":"p","ꝓ":"p","ƥ":"p","ᵱ":"p","ᶈ":"p","ꝕ":"p","ᵽ":"p","ꝑ":"p","ꝙ":"q","ʠ":"q","ɋ":"q","ꝗ":"q","ŕ":"r","ř":"r","ŗ":"r","ṙ":"r","ṛ":"r","ṝ":"r","ȑ":"r","ɾ":"r","ᵳ":"r","ȓ":"r","ṟ":"r","ɼ":"r","ᵲ":"r","ᶉ":"r","ɍ":"r","ɽ":"r","ↄ":"c","ꜿ":"c","ɘ":"e","ɿ":"r","ś":"s","ṥ":"s","š":"s","ṧ":"s","ş":"s","ŝ":"s","ș":"s","ṡ":"s","ṣ":"s","ṩ":"s","ʂ":"s","ᵴ":"s","ᶊ":"s","ȿ":"s","ɡ":"g","ß":"ss","ᴑ":"o","ᴓ":"o","ᴝ":"u","ť":"t","ţ":"t","ṱ":"t","ț":"t","ȶ":"t","ẗ":"t","ⱦ":"t","ṫ":"t","ṭ":"t","ƭ":"t","ṯ":"t","ᵵ":"t","ƫ":"t","ʈ":"t","ŧ":"t","ᵺ":"th","ɐ":"a","ᴂ":"ae","ǝ":"e","ᵷ":"g","ɥ":"h","ʮ":"h","ʯ":"h","ᴉ":"i","ʞ":"k","ꞁ":"l","ɯ":"m","ɰ":"m","ᴔ":"oe","ɹ":"r","ɻ":"r","ɺ":"r","ⱹ":"r","ʇ":"t","ʌ":"v","ʍ":"w","ʎ":"y","ꜩ":"tz","ú":"u","ŭ":"u","ǔ":"u","û":"u","ṷ":"u","ü":"u","ǘ":"u","ǚ":"u","ǜ":"u","ǖ":"u","ṳ":"u","ụ":"u","ű":"u","ȕ":"u","ù":"u","ủ":"u","ư":"u","ứ":"u","ự":"u","ừ":"u","ử":"u","ữ":"u","ȗ":"u","ū":"u","ṻ":"u","ų":"u","ᶙ":"u","ů":"u","ũ":"u","ṹ":"u","ṵ":"u","ᵫ":"ue","ꝸ":"um","ⱴ":"v","ꝟ":"v","ṿ":"v","ʋ":"v","ᶌ":"v","ⱱ":"v","ṽ":"v","ꝡ":"vy","ẃ":"w","ŵ":"w","ẅ":"w","ẇ":"w","ẉ":"w","ẁ":"w","ⱳ":"w","ẘ":"w","ẍ":"x","ẋ":"x","ᶍ":"x","ý":"y","ŷ":"y","ÿ":"y","ẏ":"y","ỵ":"y","ỳ":"y","ƴ":"y","ỷ":"y","ỿ":"y","ȳ":"y","ẙ":"y","ɏ":"y","ỹ":"y","ź":"z","ž":"z","ẑ":"z","ʑ":"z","ⱬ":"z","ż":"z","ẓ":"z","ȥ":"z","ẕ":"z","ᵶ":"z","ᶎ":"z","ʐ":"z","ƶ":"z","ɀ":"z","ff":"ff","ffi":"ffi","ffl":"ffl","fi":"fi","fl":"fl","ij":"ij","œ":"oe","st":"st","ₐ":"a","ₑ":"e","ᵢ":"i","ⱼ":"j","ₒ":"o","ᵣ":"r","ᵤ":"u","ᵥ":"v","ₓ":"x"};
 41472   var latin_map={"Á":"A","Ă":"A","Ắ":"A","Ặ":"A","Ằ":"A","Ẳ":"A","Ẵ":"A","Ǎ":"A","Â":"A","Ấ":"A","Ậ":"A","Ầ":"A","Ẩ":"A","Ẫ":"A","Ä":"A","Ǟ":"A","Ȧ":"A","Ǡ":"A","Ạ":"A","Ȁ":"A","À":"A","Ả":"A","Ȃ":"A","Ā":"A","Ą":"A","Å":"A","Ǻ":"A","Ḁ":"A","Ⱥ":"A","Ã":"A","Ꜳ":"AA","Æ":"AE","Ǽ":"AE","Ǣ":"AE","Ꜵ":"AO","Ꜷ":"AU","Ꜹ":"AV","Ꜻ":"AV","Ꜽ":"AY","Ḃ":"B","Ḅ":"B","Ɓ":"B","Ḇ":"B","Ƀ":"B","Ƃ":"B","Ć":"C","Č":"C","Ç":"C","Ḉ":"C","Ĉ":"C","Ċ":"C","Ƈ":"C","Ȼ":"C","Ď":"D","Ḑ":"D","Ḓ":"D","Ḋ":"D","Ḍ":"D","Ɗ":"D","Ḏ":"D","Dz":"D","Dž":"D","Đ":"D","Ƌ":"D","DZ":"DZ","DŽ":"DZ","É":"E","Ĕ":"E","Ě":"E","Ȩ":"E","Ḝ":"E","Ê":"E","Ế":"E","Ệ":"E","Ề":"E","Ể":"E","Ễ":"E","Ḙ":"E","Ë":"E","Ė":"E","Ẹ":"E","Ȅ":"E","È":"E","Ẻ":"E","Ȇ":"E","Ē":"E","Ḗ":"E","Ḕ":"E","Ę":"E","Ɇ":"E","Ẽ":"E","Ḛ":"E","Ꝫ":"ET","Ḟ":"F","Ƒ":"F","Ǵ":"G","Ğ":"G","Ǧ":"G","Ģ":"G","Ĝ":"G","Ġ":"G","Ɠ":"G","Ḡ":"G","Ǥ":"G","Ḫ":"H","Ȟ":"H","Ḩ":"H","Ĥ":"H","Ⱨ":"H","Ḧ":"H","Ḣ":"H","Ḥ":"H","Ħ":"H","Í":"I","Ĭ":"I","Ǐ":"I","Î":"I","Ï":"I","Ḯ":"I","İ":"I","Ị":"I","Ȉ":"I","Ì":"I","Ỉ":"I","Ȋ":"I","Ī":"I","Į":"I","Ɨ":"I","Ĩ":"I","Ḭ":"I","Ꝺ":"D","Ꝼ":"F","Ᵹ":"G","Ꞃ":"R","Ꞅ":"S","Ꞇ":"T","Ꝭ":"IS","Ĵ":"J","Ɉ":"J","Ḱ":"K","Ǩ":"K","Ķ":"K","Ⱪ":"K","Ꝃ":"K","Ḳ":"K","Ƙ":"K","Ḵ":"K","Ꝁ":"K","Ꝅ":"K","Ĺ":"L","Ƚ":"L","Ľ":"L","Ļ":"L","Ḽ":"L","Ḷ":"L","Ḹ":"L","Ⱡ":"L","Ꝉ":"L","Ḻ":"L","Ŀ":"L","Ɫ":"L","Lj":"L","Ł":"L","LJ":"LJ","Ḿ":"M","Ṁ":"M","Ṃ":"M","Ɱ":"M","Ń":"N","Ň":"N","Ņ":"N","Ṋ":"N","Ṅ":"N","Ṇ":"N","Ǹ":"N","Ɲ":"N","Ṉ":"N","Ƞ":"N","Nj":"N","Ñ":"N","NJ":"NJ","Ó":"O","Ŏ":"O","Ǒ":"O","Ô":"O","Ố":"O","Ộ":"O","Ồ":"O","Ổ":"O","Ỗ":"O","Ö":"O","Ȫ":"O","Ȯ":"O","Ȱ":"O","Ọ":"O","Ő":"O","Ȍ":"O","Ò":"O","Ỏ":"O","Ơ":"O","Ớ":"O","Ợ":"O","Ờ":"O","Ở":"O","Ỡ":"O","Ȏ":"O","Ꝋ":"O","Ꝍ":"O","Ō":"O","Ṓ":"O","Ṑ":"O","Ɵ":"O","Ǫ":"O","Ǭ":"O","Ø":"O","Ǿ":"O","Õ":"O","Ṍ":"O","Ṏ":"O","Ȭ":"O","Ƣ":"OI","Ꝏ":"OO","Ɛ":"E","Ɔ":"O","Ȣ":"OU","Ṕ":"P","Ṗ":"P","Ꝓ":"P","Ƥ":"P","Ꝕ":"P","Ᵽ":"P","Ꝑ":"P","Ꝙ":"Q","Ꝗ":"Q","Ŕ":"R","Ř":"R","Ŗ":"R","Ṙ":"R","Ṛ":"R","Ṝ":"R","Ȑ":"R","Ȓ":"R","Ṟ":"R","Ɍ":"R","Ɽ":"R","Ꜿ":"C","Ǝ":"E","Ś":"S","Ṥ":"S","Š":"S","Ṧ":"S","Ş":"S","Ŝ":"S","Ș":"S","Ṡ":"S","Ṣ":"S","Ṩ":"S","ẞ":"SS","Ť":"T","Ţ":"T","Ṱ":"T","Ț":"T","Ⱦ":"T","Ṫ":"T","Ṭ":"T","Ƭ":"T","Ṯ":"T","Ʈ":"T","Ŧ":"T","Ɐ":"A","Ꞁ":"L","Ɯ":"M","Ʌ":"V","Ꜩ":"TZ","Ú":"U","Ŭ":"U","Ǔ":"U","Û":"U","Ṷ":"U","Ü":"U","Ǘ":"U","Ǚ":"U","Ǜ":"U","Ǖ":"U","Ṳ":"U","Ụ":"U","Ű":"U","Ȕ":"U","Ù":"U","Ủ":"U","Ư":"U","Ứ":"U","Ự":"U","Ừ":"U","Ử":"U","Ữ":"U","Ȗ":"U","Ū":"U","Ṻ":"U","Ų":"U","Ů":"U","Ũ":"U","Ṹ":"U","Ṵ":"U","Ꝟ":"V","Ṿ":"V","Ʋ":"V","Ṽ":"V","Ꝡ":"VY","Ẃ":"W","Ŵ":"W","Ẅ":"W","Ẇ":"W","Ẉ":"W","Ẁ":"W","Ⱳ":"W","Ẍ":"X","Ẋ":"X","Ý":"Y","Ŷ":"Y","Ÿ":"Y","Ẏ":"Y","Ỵ":"Y","Ỳ":"Y","Ƴ":"Y","Ỷ":"Y","Ỿ":"Y","Ȳ":"Y","Ɏ":"Y","Ỹ":"Y","Ź":"Z","Ž":"Z","Ẑ":"Z","Ⱬ":"Z","Ż":"Z","Ẓ":"Z","Ȥ":"Z","Ẕ":"Z","Ƶ":"Z","IJ":"IJ","Œ":"OE","ᴀ":"A","ᴁ":"AE","ʙ":"B","ᴃ":"B","ᴄ":"C","ᴅ":"D","ᴇ":"E","ꜰ":"F","ɢ":"G","ʛ":"G","ʜ":"H","ɪ":"I","ʁ":"R","ᴊ":"J","ᴋ":"K","ʟ":"L","ᴌ":"L","ᴍ":"M","ɴ":"N","ᴏ":"O","ɶ":"OE","ᴐ":"O","ᴕ":"OU","ᴘ":"P","ʀ":"R","ᴎ":"N","ᴙ":"R","ꜱ":"S","ᴛ":"T","ⱻ":"E","ᴚ":"R","ᴜ":"U","ᴠ":"V","ᴡ":"W","ʏ":"Y","ᴢ":"Z","á":"a","ă":"a","ắ":"a","ặ":"a","ằ":"a","ẳ":"a","ẵ":"a","ǎ":"a","â":"a","ấ":"a","ậ":"a","ầ":"a","ẩ":"a","ẫ":"a","ä":"a","ǟ":"a","ȧ":"a","ǡ":"a","ạ":"a","ȁ":"a","à":"a","ả":"a","ȃ":"a","ā":"a","ą":"a","ᶏ":"a","ẚ":"a","å":"a","ǻ":"a","ḁ":"a","ⱥ":"a","ã":"a","ꜳ":"aa","æ":"ae","ǽ":"ae","ǣ":"ae","ꜵ":"ao","ꜷ":"au","ꜹ":"av","ꜻ":"av","ꜽ":"ay","ḃ":"b","ḅ":"b","ɓ":"b","ḇ":"b","ᵬ":"b","ᶀ":"b","ƀ":"b","ƃ":"b","ɵ":"o","ć":"c","č":"c","ç":"c","ḉ":"c","ĉ":"c","ɕ":"c","ċ":"c","ƈ":"c","ȼ":"c","ď":"d","ḑ":"d","ḓ":"d","ȡ":"d","ḋ":"d","ḍ":"d","ɗ":"d","ᶑ":"d","ḏ":"d","ᵭ":"d","ᶁ":"d","đ":"d","ɖ":"d","ƌ":"d","ı":"i","ȷ":"j","ɟ":"j","ʄ":"j","dz":"dz","dž":"dz","é":"e","ĕ":"e","ě":"e","ȩ":"e","ḝ":"e","ê":"e","ế":"e","ệ":"e","ề":"e","ể":"e","ễ":"e","ḙ":"e","ë":"e","ė":"e","ẹ":"e","ȅ":"e","è":"e","ẻ":"e","ȇ":"e","ē":"e","ḗ":"e","ḕ":"e","ⱸ":"e","ę":"e","ᶒ":"e","ɇ":"e","ẽ":"e","ḛ":"e","ꝫ":"et","ḟ":"f","ƒ":"f","ᵮ":"f","ᶂ":"f","ǵ":"g","ğ":"g","ǧ":"g","ģ":"g","ĝ":"g","ġ":"g","ɠ":"g","ḡ":"g","ᶃ":"g","ǥ":"g","ḫ":"h","ȟ":"h","ḩ":"h","ĥ":"h","ⱨ":"h","ḧ":"h","ḣ":"h","ḥ":"h","ɦ":"h","ẖ":"h","ħ":"h","ƕ":"hv","í":"i","ĭ":"i","ǐ":"i","î":"i","ï":"i","ḯ":"i","ị":"i","ȉ":"i","ì":"i","ỉ":"i","ȋ":"i","ī":"i","į":"i","ᶖ":"i","ɨ":"i","ĩ":"i","ḭ":"i","ꝺ":"d","ꝼ":"f","ᵹ":"g","ꞃ":"r","ꞅ":"s","ꞇ":"t","ꝭ":"is","ǰ":"j","ĵ":"j","ʝ":"j","ɉ":"j","ḱ":"k","ǩ":"k","ķ":"k","ⱪ":"k","ꝃ":"k","ḳ":"k","ƙ":"k","ḵ":"k","ᶄ":"k","ꝁ":"k","ꝅ":"k","ĺ":"l","ƚ":"l","ɬ":"l","ľ":"l","ļ":"l","ḽ":"l","ȴ":"l","ḷ":"l","ḹ":"l","ⱡ":"l","ꝉ":"l","ḻ":"l","ŀ":"l","ɫ":"l","ᶅ":"l","ɭ":"l","ł":"l","lj":"lj","ſ":"s","ẜ":"s","ẛ":"s","ẝ":"s","ḿ":"m","ṁ":"m","ṃ":"m","ɱ":"m","ᵯ":"m","ᶆ":"m","ń":"n","ň":"n","ņ":"n","ṋ":"n","ȵ":"n","ṅ":"n","ṇ":"n","ǹ":"n","ɲ":"n","ṉ":"n","ƞ":"n","ᵰ":"n","ᶇ":"n","ɳ":"n","ñ":"n","nj":"nj","ó":"o","ŏ":"o","ǒ":"o","ô":"o","ố":"o","ộ":"o","ồ":"o","ổ":"o","ỗ":"o","ö":"o","ȫ":"o","ȯ":"o","ȱ":"o","ọ":"o","ő":"o","ȍ":"o","ò":"o","ỏ":"o","ơ":"o","ớ":"o","ợ":"o","ờ":"o","ở":"o","ỡ":"o","ȏ":"o","ꝋ":"o","ꝍ":"o","ⱺ":"o","ō":"o","ṓ":"o","ṑ":"o","ǫ":"o","ǭ":"o","ø":"o","ǿ":"o","õ":"o","ṍ":"o","ṏ":"o","ȭ":"o","ƣ":"oi","ꝏ":"oo","ɛ":"e","ᶓ":"e","ɔ":"o","ᶗ":"o","ȣ":"ou","ṕ":"p","ṗ":"p","ꝓ":"p","ƥ":"p","ᵱ":"p","ᶈ":"p","ꝕ":"p","ᵽ":"p","ꝑ":"p","ꝙ":"q","ʠ":"q","ɋ":"q","ꝗ":"q","ŕ":"r","ř":"r","ŗ":"r","ṙ":"r","ṛ":"r","ṝ":"r","ȑ":"r","ɾ":"r","ᵳ":"r","ȓ":"r","ṟ":"r","ɼ":"r","ᵲ":"r","ᶉ":"r","ɍ":"r","ɽ":"r","ↄ":"c","ꜿ":"c","ɘ":"e","ɿ":"r","ś":"s","ṥ":"s","š":"s","ṧ":"s","ş":"s","ŝ":"s","ș":"s","ṡ":"s","ṣ":"s","ṩ":"s","ʂ":"s","ᵴ":"s","ᶊ":"s","ȿ":"s","ɡ":"g","ß":"ss","ᴑ":"o","ᴓ":"o","ᴝ":"u","ť":"t","ţ":"t","ṱ":"t","ț":"t","ȶ":"t","ẗ":"t","ⱦ":"t","ṫ":"t","ṭ":"t","ƭ":"t","ṯ":"t","ᵵ":"t","ƫ":"t","ʈ":"t","ŧ":"t","ᵺ":"th","ɐ":"a","ᴂ":"ae","ǝ":"e","ᵷ":"g","ɥ":"h","ʮ":"h","ʯ":"h","ᴉ":"i","ʞ":"k","ꞁ":"l","ɯ":"m","ɰ":"m","ᴔ":"oe","ɹ":"r","ɻ":"r","ɺ":"r","ⱹ":"r","ʇ":"t","ʌ":"v","ʍ":"w","ʎ":"y","ꜩ":"tz","ú":"u","ŭ":"u","ǔ":"u","û":"u","ṷ":"u","ü":"u","ǘ":"u","ǚ":"u","ǜ":"u","ǖ":"u","ṳ":"u","ụ":"u","ű":"u","ȕ":"u","ù":"u","ủ":"u","ư":"u","ứ":"u","ự":"u","ừ":"u","ử":"u","ữ":"u","ȗ":"u","ū":"u","ṻ":"u","ų":"u","ᶙ":"u","ů":"u","ũ":"u","ṹ":"u","ṵ":"u","ᵫ":"ue","ꝸ":"um","ⱴ":"v","ꝟ":"v","ṿ":"v","ʋ":"v","ᶌ":"v","ⱱ":"v","ṽ":"v","ꝡ":"vy","ẃ":"w","ŵ":"w","ẅ":"w","ẇ":"w","ẉ":"w","ẁ":"w","ⱳ":"w","ẘ":"w","ẍ":"x","ẋ":"x","ᶍ":"x","ý":"y","ŷ":"y","ÿ":"y","ẏ":"y","ỵ":"y","ỳ":"y","ƴ":"y","ỷ":"y","ỿ":"y","ȳ":"y","ẙ":"y","ɏ":"y","ỹ":"y","ź":"z","ž":"z","ẑ":"z","ʑ":"z","ⱬ":"z","ż":"z","ẓ":"z","ȥ":"z","ẕ":"z","ᵶ":"z","ᶎ":"z","ʐ":"z","ƶ":"z","ɀ":"z","ff":"ff","ffi":"ffi","ffl":"ffl","fi":"fi","fl":"fl","ij":"ij","œ":"oe","st":"st","ₐ":"a","ₑ":"e","ᵢ":"i","ⱼ":"j","ₒ":"o","ᵣ":"r","ᵤ":"u","ᵥ":"v","ₓ":"x"};
 40796       })
 41626       })
 40797 
 41627 
 40798       return new this.constructor(s);
 41628       return new this.constructor(s);
 40799     },
 41629     },
 40800 
 41630 
 40801     endsWith: function(suffix) {
 41631     endsWith: function() {
 40802       var l  = this.s.length - suffix.length;
 41632       var suffixes = Array.prototype.slice.call(arguments, 0);
 40803       return l >= 0 && this.s.indexOf(suffix, l) === l;
 41633       for (var i = 0; i < suffixes.length; ++i) {
       
 41634         var l  = this.s.length - suffixes[i].length;
       
 41635         if (l >= 0 && this.s.indexOf(suffixes[i], l) === l) return true;
       
 41636       }
       
 41637       return false;
 40804     },
 41638     },
 40805 
 41639 
 40806     escapeHTML: function() { //from underscore.string
 41640     escapeHTML: function() { //from underscore.string
 40807       return new this.constructor(this.s.replace(/[&<>"']/g, function(m){ return '&' + reversedEscapeChars[m] + ';'; }));
 41641       return new this.constructor(this.s.replace(/[&<>"']/g, function(m){ return '&' + reversedEscapeChars[m] + ';'; }));
 40808     },
 41642     },
 41007       if (sl.charAt(0) === '-')
 41841       if (sl.charAt(0) === '-')
 41008         sl = sl.substr(1);
 41842         sl = sl.substr(1);
 41009       return new this.constructor(sl);
 41843       return new this.constructor(sl);
 41010     },
 41844     },
 41011 
 41845 
 41012     startsWith: function(prefix) {
 41846     startsWith: function() {
 41013       return this.s.lastIndexOf(prefix, 0) === 0;
 41847       var prefixes = Array.prototype.slice.call(arguments, 0);
       
 41848       for (var i = 0; i < prefixes.length; ++i) {
       
 41849         if (this.s.lastIndexOf(prefixes[i], 0) === 0) return true;
       
 41850       }
       
 41851       return false;
 41014     },
 41852     },
 41015 
 41853 
 41016     stripPunctuation: function() {
 41854     stripPunctuation: function() {
 41017       //return new this.constructor(this.s.replace(/[\.,-\/#!$%\^&\*;:{}=\-_`~()]/g,""));
 41855       //return new this.constructor(this.s.replace(/[\.,-\/#!$%\^&\*;:{}=\-_`~()]/g,""));
 41018       return new this.constructor(this.s.replace(/[^\w\s]|_/g, "").replace(/\s+/g, " "));
 41856       return new this.constructor(this.s.replace(/[^\w\s]|_/g, "").replace(/\s+/g, " "));
 41036       var r = new RegExp(open + '(.+?)' + close, 'g')
 41874       var r = new RegExp(open + '(.+?)' + close, 'g')
 41037         //, r = /\{\{(.+?)\}\}/g
 41875         //, r = /\{\{(.+?)\}\}/g
 41038       var matches = s.match(r) || [];
 41876       var matches = s.match(r) || [];
 41039 
 41877 
 41040       matches.forEach(function(match) {
 41878       matches.forEach(function(match) {
 41041         var key = match.substring(opening.length, match.length - closing.length);//chop {{ and }}
 41879         var key = match.substring(opening.length, match.length - closing.length).trim();//chop {{ and }}
 41042         if (typeof values[key] != 'undefined')
 41880         var value = typeof values[key] == 'undefined' ? '' : values[key];
 41043           s = s.replace(match, values[key]);
 41881         s = s.replace(match, value);
 41044       });
 41882       });
 41045       return new this.constructor(s);
 41883       return new this.constructor(s);
 41046     },
 41884     },
 41047 
 41885 
 41048     times: function(n) {
 41886     times: function(n) {
 41186     },
 42024     },
 41187 
 42025 
 41188     //#modified from https://github.com/epeli/underscore.string
 42026     //#modified from https://github.com/epeli/underscore.string
 41189     underscore: function() {
 42027     underscore: function() {
 41190       var s = this.trim().s.replace(/([a-z\d])([A-Z]+)/g, '$1_$2').replace(/[-\s]+/g, '_').toLowerCase();
 42028       var s = this.trim().s.replace(/([a-z\d])([A-Z]+)/g, '$1_$2').replace(/[-\s]+/g, '_').toLowerCase();
 41191       if ((new S(this.s.charAt(0))).isUpper()) {
       
 41192         s = '_' + s;
       
 41193       }
       
 41194       return new this.constructor(s);
 42029       return new this.constructor(s);
 41195     },
 42030     },
 41196 
 42031 
 41197     unescapeHTML: function() { //from underscore.string
 42032     unescapeHTML: function() { //from underscore.string
 41198       return new this.constructor(this.s.replace(/\&([^;]+);/g, function(entity, entityCode){
 42033       return new this.constructor(this.s.replace(/\&([^;]+);/g, function(entity, entityCode){