to learn more about them.\n * You can ensure your document is in standards mode and not quirks mode by adding ``\n * to the top of your HTML document.\n *\n * SCE assists in writing code in way that (a) is secure by default and (b) makes auditing for\n * security vulnerabilities such as XSS, clickjacking, etc. a lot easier.\n *\n * Here's an example of a binding in a privileged context:\n *\n * \n * \n * \n * \n *\n * Notice that `ng-bind-html` is bound to `userHtml` controlled by the user. With SCE\n * disabled, this application allows the user to render arbitrary HTML into the DIV.\n * In a more realistic example, one may be rendering user comments, blog articles, etc. via\n * bindings. (HTML is just one example of a context where rendering user controlled input creates\n * security vulnerabilities.)\n *\n * For the case of HTML, you might use a library, either on the client side, or on the server side,\n * to sanitize unsafe HTML before binding to the value and rendering it in the document.\n *\n * How would you ensure that every place that used these types of bindings was bound to a value that\n * was sanitized by your library (or returned as safe for rendering by your server?) How can you\n * ensure that you didn't accidentally delete the line that sanitized the value, or renamed some\n * properties/fields and forgot to update the binding to the sanitized value?\n *\n * To be secure by default, you want to ensure that any such bindings are disallowed unless you can\n * determine that something explicitly says it's safe to use a value for binding in that\n * context. You can then audit your code (a simple grep would do) to ensure that this is only done\n * for those values that you can easily tell are safe - because they were received from your server,\n * sanitized by your library, etc. You can organize your codebase to help with this - perhaps\n * allowing only the files in a specific directory to do this. Ensuring that the internal API\n * exposed by that code doesn't markup arbitrary values as safe then becomes a more manageable task.\n *\n * In the case of AngularJS' SCE service, one uses {@link ng.$sce#methods_trustAs $sce.trustAs} \n * (and shorthand methods such as {@link ng.$sce#methods_trustAsHtml $sce.trustAsHtml}, etc.) to\n * obtain values that will be accepted by SCE / privileged contexts.\n *\n *\n * ## How does it work?\n *\n * In privileged contexts, directives and code will bind to the result of {@link ng.$sce#methods_getTrusted\n * $sce.getTrusted(context, value)} rather than to the value directly. Directives use {@link\n * ng.$sce#methods_parse $sce.parseAs} rather than `$parse` to watch attribute bindings, which performs the\n * {@link ng.$sce#methods_getTrusted $sce.getTrusted} behind the scenes on non-constant literals.\n *\n * As an example, {@link ng.directive:ngBindHtml ngBindHtml} uses {@link\n * ng.$sce#methods_parseAsHtml $sce.parseAsHtml(binding expression)}. Here's the actual code (slightly\n * simplified):\n *\n *
\n * var ngBindHtmlDirective = ['$sce', function($sce) {\n * return function(scope, element, attr) {\n * scope.$watch($sce.parseAsHtml(attr.ngBindHtml), function(value) {\n * element.html(value || '');\n * });\n * };\n * }];\n *
\n *\n * ## Impact on loading templates\n *\n * This applies both to the {@link ng.directive:ngInclude `ng-include`} directive as well as\n * `templateUrl`'s specified by {@link guide/directive directives}.\n *\n * By default, Angular only loads templates from the same domain and protocol as the application\n * document. This is done by calling {@link ng.$sce#methods_getTrustedResourceUrl\n * $sce.getTrustedResourceUrl} on the template URL. To load templates from other domains and/or\n * protocols, you may either either {@link ng.$sceDelegateProvider#methods_resourceUrlWhitelist whitelist\n * them} or {@link ng.$sce#methods_trustAsResourceUrl wrap it} into a trusted value.\n *\n * *Please note*:\n * The browser's\n * {@link https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest\n * Same Origin Policy} and {@link http://www.w3.org/TR/cors/ Cross-Origin Resource Sharing (CORS)}\n * policy apply in addition to this and may further restrict whether the template is successfully\n * loaded. This means that without the right CORS policy, loading templates from a different domain\n * won't work on all browsers. Also, loading templates from `file://` URL does not work on some\n * browsers.\n *\n * ## This feels like too much overhead for the developer?\n *\n * It's important to remember that SCE only applies to interpolation expressions.\n *\n * If your expressions are constant literals, they're automatically trusted and you don't need to\n * call `$sce.trustAs` on them. (e.g.\n * `
implicitly trusted'\">
`) just works.\n *\n * Additionally, `a[href]` and `img[src]` automatically sanitize their URLs and do not pass them\n * through {@link ng.$sce#methods_getTrusted $sce.getTrusted}. SCE doesn't play a role here.\n *\n * The included {@link ng.$sceDelegate $sceDelegate} comes with sane defaults to allow you to load\n * templates in `ng-include` from your application's domain without having to even know about SCE.\n * It blocks loading templates from other domains or loading templates over http from an https\n * served document. You can change these by setting your own custom {@link\n * ng.$sceDelegateProvider#methods_resourceUrlWhitelist whitelists} and {@link\n * ng.$sceDelegateProvider#methods_resourceUrlBlacklist blacklists} for matching such URLs.\n *\n * This significantly reduces the overhead. It is far easier to pay the small overhead and have an\n * application that's secure and can be audited to verify that with much more ease than bolting\n * security onto an application later.\n *\n *
\n * ## What trusted context types are supported?\n *\n * | Context | Notes |\n * |---------------------|----------------|\n * | `$sce.HTML` | For HTML that's safe to source into the application. The {@link ng.directive:ngBindHtml ngBindHtml} directive uses this context for bindings. |\n * | `$sce.CSS` | For CSS that's safe to source into the application. Currently unused. Feel free to use it in your own directives. |\n * | `$sce.URL` | For URLs that are safe to follow as links. Currently unused (`
Note that `$sce.RESOURCE_URL` makes a stronger statement about the URL than `$sce.URL` does and therefore contexts requiring values trusted for `$sce.RESOURCE_URL` can be used anywhere that values trusted for `$sce.URL` are required. |\n * | `$sce.JS` | For JavaScript that is safe to execute in your application's context. Currently unused. Feel free to use it in your own directives. |\n *\n * ## Format of items in {@link ng.$sceDelegateProvider#methods_resourceUrlWhitelist resourceUrlWhitelist}/{@link ng.$sceDelegateProvider#methods_resourceUrlBlacklist Blacklist} \n *\n * Each element in these arrays must be one of the following:\n *\n * - **'self'**\n * - The special **string**, `'self'`, can be used to match against all URLs of the **same\n * domain** as the application document using the **same protocol**.\n * - **String** (except the special value `'self'`)\n * - The string is matched against the full *normalized / absolute URL* of the resource\n * being tested (substring matches are not good enough.)\n * - There are exactly **two wildcard sequences** - `*` and `**`. All other characters\n * match themselves.\n * - `*`: matches zero or more occurances of any character other than one of the following 6\n * characters: '`:`', '`/`', '`.`', '`?`', '`&`' and ';'. It's a useful wildcard for use\n * in a whitelist.\n * - `**`: matches zero or more occurances of *any* character. As such, it's not\n * not appropriate to use in for a scheme, domain, etc. as it would match too much. (e.g.\n * http://**.example.com/ would match http://evil.com/?ignore=.example.com/ and that might\n * not have been the intention.) It's usage at the very end of the path is ok. (e.g.\n * http://foo.example.com/templates/**).\n * - **RegExp** (*see caveat below*)\n * - *Caveat*: While regular expressions are powerful and offer great flexibility, their syntax\n * (and all the inevitable escaping) makes them *harder to maintain*. It's easy to\n * accidentally introduce a bug when one updates a complex expression (imho, all regexes should\n * have good test coverage.). For instance, the use of `.` in the regex is correct only in a\n * small number of cases. A `.` character in the regex used when matching the scheme or a\n * subdomain could be matched against a `:` or literal `.` that was likely not intended. It\n * is highly recommended to use the string patterns and only fall back to regular expressions\n * if they as a last resort.\n * - The regular expression must be an instance of RegExp (i.e. not a string.) It is\n * matched against the **entire** *normalized / absolute URL* of the resource being tested\n * (even when the RegExp did not have the `^` and `$` codes.) In addition, any flags\n * present on the RegExp (such as multiline, global, ignoreCase) are ignored.\n * - If you are generating your Javascript from some other templating engine (not\n * recommended, e.g. in issue [#4006](https://github.com/angular/angular.js/issues/4006)),\n * remember to escape your regular expression (and be aware that you might need more than\n * one level of escaping depending on your templating engine and the way you interpolated\n * the value.) Do make use of your platform's escaping mechanism as it might be good\n * enough before coding your own. e.g. Ruby has\n * [Regexp.escape(str)](http://www.ruby-doc.org/core-2.0.0/Regexp.html#method-c-escape)\n * and Python has [re.escape](http://docs.python.org/library/re.html#re.escape).\n * Javascript lacks a similar built in function for escaping. Take a look at Google\n * Closure library's [goog.string.regExpEscape(s)](\n * http://docs.closure-library.googlecode.com/git/closure_goog_string_string.js.source.html#line962).\n *\n * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} for an example.\n *\n * ## Show me an example using SCE.\n *\n * @example\n
\n\n \n
\n
User comments\n By default, HTML that isn't explicitly trusted (e.g. Alice's comment) is sanitized when\n $sanitize is available. If $sanitize isn't available, this results in an error instead of an\n exploit.\n
\n
\n {{userComment.name}}:\n \n
\n
\n
\n
\n\n\n\n var mySceApp = angular.module('mySceApp', ['ngSanitize']);\n\n mySceApp.controller(\"myAppController\", function myAppController($http, $templateCache, $sce) {\n var self = this;\n $http.get(\"test_data.json\", {cache: $templateCache}).success(function(userComments) {\n self.userComments = userComments;\n });\n self.explicitlyTrustedHtml = $sce.trustAsHtml(\n 'Hover over this text.');\n });\n\n\n\n[\n { \"name\": \"Alice\",\n \"htmlComment\":\n \"Is anyone reading this?\"\n },\n { \"name\": \"Bob\",\n \"htmlComment\": \"Yes! Am I the only other one?\"\n }\n]\n\n\n\n describe('SCE doc demo', function() {\n it('should sanitize untrusted values', function() {\n expect(element('.htmlComment').html()).toBe('Is anyone reading this?');\n });\n it('should NOT sanitize explicitly trusted values', function() {\n expect(element('#explicitlyTrustedHtml').html()).toBe(\n 'Hover over this text.');\n });\n });\n\n\n *\n *\n *\n * ## Can I disable SCE completely?\n *\n * Yes, you can. However, this is strongly discouraged. SCE gives you a lot of security benefits\n * for little coding overhead. It will be much harder to take an SCE disabled application and\n * either secure it on your own or enable SCE at a later stage. It might make sense to disable SCE\n * for cases where you have a lot of existing code that was written before SCE was introduced and\n * you're migrating them a module at a time.\n *\n * That said, here's how you can completely disable SCE:\n *\n *
\n * angular.module('myAppWithSceDisabledmyApp', []).config(function($sceProvider) {\n * // Completely disable SCE. For demonstration purposes only!\n * // Do not use in new projects.\n * $sceProvider.enabled(false);\n * });\n *
\n *\n */\n/* jshint maxlen: 100 */\n\nfunction $SceProvider() {\n var enabled = true;\n\n /**\n * @ngdoc function\n * @name ng.sceProvider#enabled\n * @methodOf ng.$sceProvider\n * @function\n *\n * @param {boolean=} value If provided, then enables/disables SCE.\n * @return {boolean} true if SCE is enabled, false otherwise.\n *\n * @description\n * Enables/disables SCE and returns the current value.\n */\n this.enabled = function (value) {\n if (arguments.length) {\n enabled = !!value;\n }\n return enabled;\n };\n\n\n /* Design notes on the default implementation for SCE.\n *\n * The API contract for the SCE delegate\n * -------------------------------------\n * The SCE delegate object must provide the following 3 methods:\n *\n * - trustAs(contextEnum, value)\n * This method is used to tell the SCE service that the provided value is OK to use in the\n * contexts specified by contextEnum. It must return an object that will be accepted by\n * getTrusted() for a compatible contextEnum and return this value.\n *\n * - valueOf(value)\n * For values that were not produced by trustAs(), return them as is. For values that were\n * produced by trustAs(), return the corresponding input value to trustAs. Basically, if\n * trustAs is wrapping the given values into some type, this operation unwraps it when given\n * such a value.\n *\n * - getTrusted(contextEnum, value)\n * This function should return the a value that is safe to use in the context specified by\n * contextEnum or throw and exception otherwise.\n *\n * NOTE: This contract deliberately does NOT state that values returned by trustAs() must be\n * opaque or wrapped in some holder object. That happens to be an implementation detail. For\n * instance, an implementation could maintain a registry of all trusted objects by context. In\n * such a case, trustAs() would return the same object that was passed in. getTrusted() would\n * return the same object passed in if it was found in the registry under a compatible context or\n * throw an exception otherwise. An implementation might only wrap values some of the time based\n * on some criteria. getTrusted() might return a value and not throw an exception for special\n * constants or objects even if not wrapped. All such implementations fulfill this contract.\n *\n *\n * A note on the inheritance model for SCE contexts\n * ------------------------------------------------\n * I've used inheritance and made RESOURCE_URL wrapped types a subtype of URL wrapped types. This\n * is purely an implementation details.\n *\n * The contract is simply this:\n *\n * getTrusted($sce.RESOURCE_URL, value) succeeding implies that getTrusted($sce.URL, value)\n * will also succeed.\n *\n * Inheritance happens to capture this in a natural way. In some future, we\n * may not use inheritance anymore. That is OK because no code outside of\n * sce.js and sceSpecs.js would need to be aware of this detail.\n */\n\n this.$get = ['$parse', '$sniffer', '$sceDelegate', function(\n $parse, $sniffer, $sceDelegate) {\n // Prereq: Ensure that we're not running in IE8 quirks mode. In that mode, IE allows\n // the \"expression(javascript expression)\" syntax which is insecure.\n if (enabled && $sniffer.msie && $sniffer.msieDocumentMode < 8) {\n throw $sceMinErr('iequirks',\n 'Strict Contextual Escaping does not support Internet Explorer version < 9 in quirks ' +\n 'mode. You can fix this by adding the text to the top of your HTML ' +\n 'document. See http://docs.angularjs.org/api/ng.$sce for more information.');\n }\n\n var sce = copy(SCE_CONTEXTS);\n\n /**\n * @ngdoc function\n * @name ng.sce#isEnabled\n * @methodOf ng.$sce\n * @function\n *\n * @return {Boolean} true if SCE is enabled, false otherwise. If you want to set the value, you\n * have to do it at module config time on {@link ng.$sceProvider $sceProvider}.\n *\n * @description\n * Returns a boolean indicating if SCE is enabled.\n */\n sce.isEnabled = function () {\n return enabled;\n };\n sce.trustAs = $sceDelegate.trustAs;\n sce.getTrusted = $sceDelegate.getTrusted;\n sce.valueOf = $sceDelegate.valueOf;\n\n if (!enabled) {\n sce.trustAs = sce.getTrusted = function(type, value) { return value; };\n sce.valueOf = identity;\n }\n\n /**\n * @ngdoc method\n * @name ng.$sce#parse\n * @methodOf ng.$sce\n *\n * @description\n * Converts Angular {@link guide/expression expression} into a function. This is like {@link\n * ng.$parse $parse} and is identical when the expression is a literal constant. Otherwise, it\n * wraps the expression in a call to {@link ng.$sce#methods_getTrusted $sce.getTrusted(*type*,\n * *result*)}\n *\n * @param {string} type The kind of SCE context in which this result will be used.\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n * * `context` – `{object}` – an object against which any expressions embedded in the strings\n * are evaluated against (typically a scope object).\n * * `locals` – `{object=}` – local variables context object, useful for overriding values in\n * `context`.\n */\n sce.parseAs = function sceParseAs(type, expr) {\n var parsed = $parse(expr);\n if (parsed.literal && parsed.constant) {\n return parsed;\n } else {\n return function sceParseAsTrusted(self, locals) {\n return sce.getTrusted(type, parsed(self, locals));\n };\n }\n };\n\n /**\n * @ngdoc method\n * @name ng.$sce#trustAs\n * @methodOf ng.$sce\n *\n * @description\n * Delegates to {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs`}. As such,\n * returns an objectthat is trusted by angular for use in specified strict contextual\n * escaping contexts (such as ng-html-bind-unsafe, ng-include, any src attribute\n * interpolation, any dom event binding attribute interpolation such as for onclick, etc.)\n * that uses the provided value. See * {@link ng.$sce $sce} for enabling strict contextual\n * escaping.\n *\n * @param {string} type The kind of context in which this value is safe for use. e.g. url,\n * resource_url, html, js and css.\n * @param {*} value The value that that should be considered trusted/safe.\n * @returns {*} A value that can be used to stand in for the provided `value` in places\n * where Angular expects a $sce.trustAs() return value.\n */\n\n /**\n * @ngdoc method\n * @name ng.$sce#trustAsHtml\n * @methodOf ng.$sce\n *\n * @description\n * Shorthand method. `$sce.trustAsHtml(value)` →\n * {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs($sce.HTML, value)`}\n *\n * @param {*} value The value to trustAs.\n * @returns {*} An object that can be passed to {@link ng.$sce#methods_getTrustedHtml\n * $sce.getTrustedHtml(value)} to obtain the original value. (privileged directives\n * only accept expressions that are either literal constants or are the\n * return value of {@link ng.$sce#methods_trustAs $sce.trustAs}.)\n */\n\n /**\n * @ngdoc method\n * @name ng.$sce#trustAsUrl\n * @methodOf ng.$sce\n *\n * @description\n * Shorthand method. `$sce.trustAsUrl(value)` →\n * {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs($sce.URL, value)`}\n *\n * @param {*} value The value to trustAs.\n * @returns {*} An object that can be passed to {@link ng.$sce#methods_getTrustedUrl\n * $sce.getTrustedUrl(value)} to obtain the original value. (privileged directives\n * only accept expressions that are either literal constants or are the\n * return value of {@link ng.$sce#methods_trustAs $sce.trustAs}.)\n */\n\n /**\n * @ngdoc method\n * @name ng.$sce#trustAsResourceUrl\n * @methodOf ng.$sce\n *\n * @description\n * Shorthand method. `$sce.trustAsResourceUrl(value)` →\n * {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs($sce.RESOURCE_URL, value)`}\n *\n * @param {*} value The value to trustAs.\n * @returns {*} An object that can be passed to {@link ng.$sce#methods_getTrustedResourceUrl\n * $sce.getTrustedResourceUrl(value)} to obtain the original value. (privileged directives\n * only accept expressions that are either literal constants or are the return\n * value of {@link ng.$sce#methods_trustAs $sce.trustAs}.)\n */\n\n /**\n * @ngdoc method\n * @name ng.$sce#trustAsJs\n * @methodOf ng.$sce\n *\n * @description\n * Shorthand method. `$sce.trustAsJs(value)` →\n * {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs($sce.JS, value)`}\n *\n * @param {*} value The value to trustAs.\n * @returns {*} An object that can be passed to {@link ng.$sce#methods_getTrustedJs\n * $sce.getTrustedJs(value)} to obtain the original value. (privileged directives\n * only accept expressions that are either literal constants or are the\n * return value of {@link ng.$sce#methods_trustAs $sce.trustAs}.)\n */\n\n /**\n * @ngdoc method\n * @name ng.$sce#getTrusted\n * @methodOf ng.$sce\n *\n * @description\n * Delegates to {@link ng.$sceDelegate#methods_getTrusted `$sceDelegate.getTrusted`}. As such,\n * takes the result of a {@link ng.$sce#methods_trustAs `$sce.trustAs`}() call and returns the\n * originally supplied value if the queried context type is a supertype of the created type.\n * If this condition isn't satisfied, throws an exception.\n *\n * @param {string} type The kind of context in which this value is to be used.\n * @param {*} maybeTrusted The result of a prior {@link ng.$sce#methods_trustAs `$sce.trustAs`}\n * call.\n * @returns {*} The value the was originally provided to\n * {@link ng.$sce#methods_trustAs `$sce.trustAs`} if valid in this context.\n * Otherwise, throws an exception.\n */\n\n /**\n * @ngdoc method\n * @name ng.$sce#getTrustedHtml\n * @methodOf ng.$sce\n *\n * @description\n * Shorthand method. `$sce.getTrustedHtml(value)` →\n * {@link ng.$sceDelegate#methods_getTrusted `$sceDelegate.getTrusted($sce.HTML, value)`}\n *\n * @param {*} value The value to pass to `$sce.getTrusted`.\n * @returns {*} The return value of `$sce.getTrusted($sce.HTML, value)`\n */\n\n /**\n * @ngdoc method\n * @name ng.$sce#getTrustedCss\n * @methodOf ng.$sce\n *\n * @description\n * Shorthand method. `$sce.getTrustedCss(value)` →\n * {@link ng.$sceDelegate#methods_getTrusted `$sceDelegate.getTrusted($sce.CSS, value)`}\n *\n * @param {*} value The value to pass to `$sce.getTrusted`.\n * @returns {*} The return value of `$sce.getTrusted($sce.CSS, value)`\n */\n\n /**\n * @ngdoc method\n * @name ng.$sce#getTrustedUrl\n * @methodOf ng.$sce\n *\n * @description\n * Shorthand method. `$sce.getTrustedUrl(value)` →\n * {@link ng.$sceDelegate#methods_getTrusted `$sceDelegate.getTrusted($sce.URL, value)`}\n *\n * @param {*} value The value to pass to `$sce.getTrusted`.\n * @returns {*} The return value of `$sce.getTrusted($sce.URL, value)`\n */\n\n /**\n * @ngdoc method\n * @name ng.$sce#getTrustedResourceUrl\n * @methodOf ng.$sce\n *\n * @description\n * Shorthand method. `$sce.getTrustedResourceUrl(value)` →\n * {@link ng.$sceDelegate#methods_getTrusted `$sceDelegate.getTrusted($sce.RESOURCE_URL, value)`}\n *\n * @param {*} value The value to pass to `$sceDelegate.getTrusted`.\n * @returns {*} The return value of `$sce.getTrusted($sce.RESOURCE_URL, value)`\n */\n\n /**\n * @ngdoc method\n * @name ng.$sce#getTrustedJs\n * @methodOf ng.$sce\n *\n * @description\n * Shorthand method. `$sce.getTrustedJs(value)` →\n * {@link ng.$sceDelegate#methods_getTrusted `$sceDelegate.getTrusted($sce.JS, value)`}\n *\n * @param {*} value The value to pass to `$sce.getTrusted`.\n * @returns {*} The return value of `$sce.getTrusted($sce.JS, value)`\n */\n\n /**\n * @ngdoc method\n * @name ng.$sce#parseAsHtml\n * @methodOf ng.$sce\n *\n * @description\n * Shorthand method. `$sce.parseAsHtml(expression string)` →\n * {@link ng.$sce#methods_parse `$sce.parseAs($sce.HTML, value)`}\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n * * `context` – `{object}` – an object against which any expressions embedded in the strings\n * are evaluated against (typically a scope object).\n * * `locals` – `{object=}` – local variables context object, useful for overriding values in\n * `context`.\n */\n\n /**\n * @ngdoc method\n * @name ng.$sce#parseAsCss\n * @methodOf ng.$sce\n *\n * @description\n * Shorthand method. `$sce.parseAsCss(value)` →\n * {@link ng.$sce#methods_parse `$sce.parseAs($sce.CSS, value)`}\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n * * `context` – `{object}` – an object against which any expressions embedded in the strings\n * are evaluated against (typically a scope object).\n * * `locals` – `{object=}` – local variables context object, useful for overriding values in\n * `context`.\n */\n\n /**\n * @ngdoc method\n * @name ng.$sce#parseAsUrl\n * @methodOf ng.$sce\n *\n * @description\n * Shorthand method. `$sce.parseAsUrl(value)` →\n * {@link ng.$sce#methods_parse `$sce.parseAs($sce.URL, value)`}\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n * * `context` – `{object}` – an object against which any expressions embedded in the strings\n * are evaluated against (typically a scope object).\n * * `locals` – `{object=}` – local variables context object, useful for overriding values in\n * `context`.\n */\n\n /**\n * @ngdoc method\n * @name ng.$sce#parseAsResourceUrl\n * @methodOf ng.$sce\n *\n * @description\n * Shorthand method. `$sce.parseAsResourceUrl(value)` →\n * {@link ng.$sce#methods_parse `$sce.parseAs($sce.RESOURCE_URL, value)`}\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n * * `context` – `{object}` – an object against which any expressions embedded in the strings\n * are evaluated against (typically a scope object).\n * * `locals` – `{object=}` – local variables context object, useful for overriding values in\n * `context`.\n */\n\n /**\n * @ngdoc method\n * @name ng.$sce#parseAsJs\n * @methodOf ng.$sce\n *\n * @description\n * Shorthand method. `$sce.parseAsJs(value)` →\n * {@link ng.$sce#methods_parse `$sce.parseAs($sce.JS, value)`}\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n * * `context` – `{object}` – an object against which any expressions embedded in the strings\n * are evaluated against (typically a scope object).\n * * `locals` – `{object=}` – local variables context object, useful for overriding values in\n * `context`.\n */\n\n // Shorthand delegations.\n var parse = sce.parseAs,\n getTrusted = sce.getTrusted,\n trustAs = sce.trustAs;\n\n forEach(SCE_CONTEXTS, function (enumValue, name) {\n var lName = lowercase(name);\n sce[camelCase(\"parse_as_\" + lName)] = function (expr) {\n return parse(enumValue, expr);\n };\n sce[camelCase(\"get_trusted_\" + lName)] = function (value) {\n return getTrusted(enumValue, value);\n };\n sce[camelCase(\"trust_as_\" + lName)] = function (value) {\n return trustAs(enumValue, value);\n };\n });\n\n return sce;\n }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name ng.$sniffer\n * @requires $window\n * @requires $document\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n * @property {boolean} transitions Does the browser support CSS transition events ?\n * @property {boolean} animations Does the browser support CSS animation events ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n this.$get = ['$window', '$document', function($window, $document) {\n var eventSupport = {},\n android =\n int((/android (\\d+)/.exec(lowercase(($window.navigator || {}).userAgent)) || [])[1]),\n boxee = /Boxee/i.test(($window.navigator || {}).userAgent),\n document = $document[0] || {},\n documentMode = document.documentMode,\n vendorPrefix,\n vendorRegex = /^(Moz|webkit|O|ms)(?=[A-Z])/,\n bodyStyle = document.body && document.body.style,\n transitions = false,\n animations = false,\n match;\n\n if (bodyStyle) {\n for(var prop in bodyStyle) {\n if(match = vendorRegex.exec(prop)) {\n vendorPrefix = match[0];\n vendorPrefix = vendorPrefix.substr(0, 1).toUpperCase() + vendorPrefix.substr(1);\n break;\n }\n }\n\n if(!vendorPrefix) {\n vendorPrefix = ('WebkitOpacity' in bodyStyle) && 'webkit';\n }\n\n transitions = !!(('transition' in bodyStyle) || (vendorPrefix + 'Transition' in bodyStyle));\n animations = !!(('animation' in bodyStyle) || (vendorPrefix + 'Animation' in bodyStyle));\n\n if (android && (!transitions||!animations)) {\n transitions = isString(document.body.style.webkitTransition);\n animations = isString(document.body.style.webkitAnimation);\n }\n }\n\n\n return {\n // Android has history.pushState, but it does not update location correctly\n // so let's not use the history API at all.\n // http://code.google.com/p/android/issues/detail?id=17471\n // https://github.com/angular/angular.js/issues/904\n\n // older webit browser (533.9) on Boxee box has exactly the same problem as Android has\n // so let's not use the history API also\n // We are purposefully using `!(android < 4)` to cover the case when `android` is undefined\n // jshint -W018\n history: !!($window.history && $window.history.pushState && !(android < 4) && !boxee),\n // jshint +W018\n hashchange: 'onhashchange' in $window &&\n // IE8 compatible mode lies\n (!documentMode || documentMode > 7),\n hasEvent: function(event) {\n // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n // it. In particular the event is not fired when backspace or delete key are pressed or\n // when cut operation is performed.\n if (event == 'input' && msie == 9) return false;\n\n if (isUndefined(eventSupport[event])) {\n var divElm = document.createElement('div');\n eventSupport[event] = 'on' + event in divElm;\n }\n\n return eventSupport[event];\n },\n csp: csp(),\n vendorPrefix: vendorPrefix,\n transitions : transitions,\n animations : animations,\n msie : msie,\n msieDocumentMode: documentMode\n };\n }];\n}\n\nfunction $TimeoutProvider() {\n this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n function($rootScope, $browser, $q, $exceptionHandler) {\n var deferreds = {};\n\n\n /**\n * @ngdoc function\n * @name ng.$timeout\n * @requires $browser\n *\n * @description\n * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n * block and delegates any exceptions to\n * {@link ng.$exceptionHandler $exceptionHandler} service.\n *\n * The return value of registering a timeout function is a promise, which will be resolved when\n * the timeout is reached and the timeout function is executed.\n *\n * To cancel a timeout request, call `$timeout.cancel(promise)`.\n *\n * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n * synchronously flush the queue of deferred functions.\n *\n * @param {function()} fn A function, whose execution should be delayed.\n * @param {number=} [delay=0] Delay in milliseconds.\n * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise\n * will invoke `fn` within the {@link ng.$rootScope.Scope#methods_$apply $apply} block.\n * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n * promise will be resolved with is the return value of the `fn` function.\n * \n * @example\n
\n \n \n\n \n
\n Date format:
\n Current time is: \n
\n Blood 1 : {{blood_1}}\n Blood 2 : {{blood_2}}\n \n \n \n \n
\n\n \n \n */\n function timeout(fn, delay, invokeApply) {\n var deferred = $q.defer(),\n promise = deferred.promise,\n skipApply = (isDefined(invokeApply) && !invokeApply),\n timeoutId;\n\n timeoutId = $browser.defer(function() {\n try {\n deferred.resolve(fn());\n } catch(e) {\n deferred.reject(e);\n $exceptionHandler(e);\n }\n finally {\n delete deferreds[promise.$$timeoutId];\n }\n\n if (!skipApply) $rootScope.$apply();\n }, delay);\n\n promise.$$timeoutId = timeoutId;\n deferreds[timeoutId] = deferred;\n\n return promise;\n }\n\n\n /**\n * @ngdoc function\n * @name ng.$timeout#cancel\n * @methodOf ng.$timeout\n *\n * @description\n * Cancels a task associated with the `promise`. As a result of this, the promise will be\n * resolved with a rejection.\n *\n * @param {Promise=} promise Promise returned by the `$timeout` function.\n * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n * canceled.\n */\n timeout.cancel = function(promise) {\n if (promise && promise.$$timeoutId in deferreds) {\n deferreds[promise.$$timeoutId].reject('canceled');\n delete deferreds[promise.$$timeoutId];\n return $browser.defer.cancel(promise.$$timeoutId);\n }\n return false;\n };\n\n return timeout;\n }];\n}\n\n// NOTE: The usage of window and document instead of $window and $document here is\n// deliberate. This service depends on the specific behavior of anchor nodes created by the\n// browser (resolving and parsing URLs) that is unlikely to be provided by mock objects and\n// cause us to break tests. In addition, when the browser resolves a URL for XHR, it\n// doesn't know about mocked locations and resolves URLs to the real document - which is\n// exactly the behavior needed here. There is little value is mocking these out for this\n// service.\nvar urlParsingNode = document.createElement(\"a\");\nvar originUrl = urlResolve(window.location.href, true);\n\n\n/**\n *\n * Implementation Notes for non-IE browsers\n * ----------------------------------------\n * Assigning a URL to the href property of an anchor DOM node, even one attached to the DOM,\n * results both in the normalizing and parsing of the URL. Normalizing means that a relative\n * URL will be resolved into an absolute URL in the context of the application document.\n * Parsing means that the anchor node's host, hostname, protocol, port, pathname and related\n * properties are all populated to reflect the normalized URL. This approach has wide\n * compatibility - Safari 1+, Mozilla 1+, Opera 7+,e etc. See\n * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html\n *\n * Implementation Notes for IE\n * ---------------------------\n * IE >= 8 and <= 10 normalizes the URL when assigned to the anchor node similar to the other\n * browsers. However, the parsed components will not be set if the URL assigned did not specify\n * them. (e.g. if you assign a.href = \"foo\", then a.protocol, a.host, etc. will be empty.) We\n * work around that by performing the parsing in a 2nd step by taking a previously normalized\n * URL (e.g. by assigning to a.href) and assigning it a.href again. This correctly populates the\n * properties such as protocol, hostname, port, etc.\n *\n * IE7 does not normalize the URL when assigned to an anchor node. (Apparently, it does, if one\n * uses the inner HTML approach to assign the URL as part of an HTML snippet -\n * http://stackoverflow.com/a/472729) However, setting img[src] does normalize the URL.\n * Unfortunately, setting img[src] to something like \"javascript:foo\" on IE throws an exception.\n * Since the primary usage for normalizing URLs is to sanitize such URLs, we can't use that\n * method and IE < 8 is unsupported.\n *\n * References:\n * http://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement\n * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html\n * http://url.spec.whatwg.org/#urlutils\n * https://github.com/angular/angular.js/pull/2902\n * http://james.padolsey.com/javascript/parsing-urls-with-the-dom/\n *\n * @function\n * @param {string} url The URL to be parsed.\n * @description Normalizes and parses a URL.\n * @returns {object} Returns the normalized URL as a dictionary.\n *\n * | member name | Description |\n * |---------------|----------------|\n * | href | A normalized version of the provided URL if it was not an absolute URL |\n * | protocol | The protocol including the trailing colon |\n * | host | The host and port (if the port is non-default) of the normalizedUrl |\n * | search | The search params, minus the question mark |\n * | hash | The hash string, minus the hash symbol\n * | hostname | The hostname\n * | port | The port, without \":\"\n * | pathname | The pathname, beginning with \"/\"\n *\n */\nfunction urlResolve(url, base) {\n var href = url;\n\n if (msie) {\n // Normalize before parse. Refer Implementation Notes on why this is\n // done in two steps on IE.\n urlParsingNode.setAttribute(\"href\", href);\n href = urlParsingNode.href;\n }\n\n urlParsingNode.setAttribute('href', href);\n\n // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils\n return {\n href: urlParsingNode.href,\n protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '',\n host: urlParsingNode.host,\n search: urlParsingNode.search ? urlParsingNode.search.replace(/^\\?/, '') : '',\n hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '',\n hostname: urlParsingNode.hostname,\n port: urlParsingNode.port,\n pathname: (urlParsingNode.pathname.charAt(0) === '/')\n ? urlParsingNode.pathname\n : '/' + urlParsingNode.pathname\n };\n}\n\n/**\n * Parse a request URL and determine whether this is a same-origin request as the application document.\n *\n * @param {string|object} requestUrl The url of the request as a string that will be resolved\n * or a parsed URL object.\n * @returns {boolean} Whether the request is for the same origin as the application document.\n */\nfunction urlIsSameOrigin(requestUrl) {\n var parsed = (isString(requestUrl)) ? urlResolve(requestUrl) : requestUrl;\n return (parsed.protocol === originUrl.protocol &&\n parsed.host === originUrl.host);\n}\n\n/**\n * @ngdoc object\n * @name ng.$window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overridden, removed or mocked for testing.\n *\n * Expressions, like the one defined for the `ngClick` directive in the example\n * below, are evaluated with respect to the current scope. Therefore, there is\n * no risk of inadvertently coding in a dependency on a global value in such an\n * expression.\n *\n * @example\n
\n \n \n \n \n \n
\n \n \n it('should display the greeting in the input box', function() {\n input('greeting').enter('Hello, E2E Tests');\n // If we click the button it will block the test runner\n // element(':button').click();\n });\n \n \n */\nfunction $WindowProvider(){\n this.$get = valueFn(window);\n}\n\n/**\n * @ngdoc object\n * @name ng.$filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be\n * Dependency Injected. To achieve this a filter definition consists of a factory function which is\n * annotated with dependencies and is responsible for creating a filter function.\n *\n *
\n * // Filter registration\n * function MyModule($provide, $filterProvider) {\n * // create a service to demonstrate injection (not always needed)\n * $provide.value('greet', function(name){\n * return 'Hello ' + name + '!';\n * });\n *\n * // register a filter factory which uses the\n * // greet service to demonstrate DI.\n * $filterProvider.register('greet', function(greet){\n * // return the filter function which uses the greet service\n * // to generate salutation\n * return function(text) {\n * // filters need to be forgiving so check input validity\n * return text && greet(text) || text;\n * };\n * });\n * }\n *
\n *\n * The filter function is registered with the `$injector` under the filter name suffix with\n * `Filter`.\n * \n *
\n * it('should be the same instance', inject(\n * function($filterProvider) {\n * $filterProvider.register('reverse', function(){\n * return ...;\n * });\n * },\n * function($filter, reverseFilter) {\n * expect($filter('reverse')).toBe(reverseFilter);\n * });\n *
\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/filter Filters} in the Angular Developer Guide.\n */\n/**\n * @ngdoc method\n * @name ng.$filterProvider#register\n * @methodOf ng.$filterProvider\n * @description\n * Register filter factory function.\n *\n * @param {String} name Name of the filter.\n * @param {function} fn The filter factory function which is injectable.\n */\n\n\n/**\n * @ngdoc function\n * @name ng.$filter\n * @function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n * {{ expression [| filter_name[:parameter_value] ... ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n var suffix = 'Filter';\n\n /**\n * @ngdoc function\n * @name ng.$controllerProvider#register\n * @methodOf ng.$controllerProvider\n * @param {string|Object} name Name of the filter function, or an object map of filters where\n * the keys are the filter names and the values are the filter factories.\n * @returns {Object} Registered filter instance, or if a map of filters was provided then a map\n * of the registered filter instances.\n */\n function register(name, factory) {\n if(isObject(name)) {\n var filters = {};\n forEach(name, function(filter, key) {\n filters[key] = register(key, filter);\n });\n return filters;\n } else {\n return $provide.factory(name + suffix, factory);\n }\n }\n this.register = register;\n\n this.$get = ['$injector', function($injector) {\n return function(name) {\n return $injector.get(name + suffix);\n };\n }];\n\n ////////////////////////////////////////\n \n /* global\n currencyFilter: false,\n dateFilter: false,\n filterFilter: false,\n jsonFilter: false,\n limitToFilter: false,\n lowercaseFilter: false,\n numberFilter: false,\n orderByFilter: false,\n uppercaseFilter: false,\n */\n\n register('currency', currencyFilter);\n register('date', dateFilter);\n register('filter', filterFilter);\n register('json', jsonFilter);\n register('limitTo', limitToFilter);\n register('lowercase', lowercaseFilter);\n register('number', numberFilter);\n register('orderBy', orderByFilter);\n register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:filter\n * @function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n * `array`.\n *\n * Can be one of:\n *\n * - `string`: Predicate that results in a substring match using the value of `expression`\n * string. All strings or objects with string properties in `array` that contain this string\n * will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n * - `Object`: A pattern object can be used to filter specific properties on objects contained\n * by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n * which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n * property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n * property of the object. That's equivalent to the simple substring match with a `string`\n * as described above.\n *\n * - `function`: A predicate function can be used to write arbitrary filters. The function is\n * called for each element of `array`. The final result is an array of those elements that\n * the predicate returned true for.\n *\n * @param {function(expected, actual)|true|undefined} comparator Comparator which is used in\n * determining if the expected value (from the filter expression) and actual value (from\n * the object in the array) should be considered a match.\n *\n * Can be one of:\n *\n * - `function(expected, actual)`:\n * The function will be given the object value and the predicate value to compare and\n * should return true if the item should be included in filtered result.\n *\n * - `true`: A shorthand for `function(expected, actual) { return angular.equals(expected, actual)}`.\n * this is essentially strict comparison of expected and actual.\n *\n * - `false|undefined`: A short hand for a function which will look for a substring match in case\n * insensitive way.\n *\n * @example\n
\n \n \n\n Search: \n \n Name | Phone |
\n \n {{friend.name}} | \n {{friend.phone}} | \n
\n
\n
\n Any:
\n Name only
\n Phone only
\n Equality
\n \n Name | Phone |
\n \n {{friend.name}} | \n {{friend.phone}} | \n
\n
\n \n \n it('should search across all fields when filtering with a string', function() {\n input('searchText').enter('m');\n expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n toEqual(['Mary', 'Mike', 'Adam']);\n\n input('searchText').enter('76');\n expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).\n toEqual(['John', 'Julie']);\n });\n\n it('should search in specific fields when filtering with a predicate object', function() {\n input('search.$').enter('i');\n expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n toEqual(['Mary', 'Mike', 'Julie', 'Juliette']);\n });\n it('should use a equal comparison when comparator is true', function() {\n input('search.name').enter('Julie');\n input('strict').check();\n expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).\n toEqual(['Julie']);\n });\n \n \n */\nfunction filterFilter() {\n return function(array, expression, comparator) {\n if (!isArray(array)) return array;\n\n var comparatorType = typeof(comparator),\n predicates = [];\n\n predicates.check = function(value) {\n for (var j = 0; j < predicates.length; j++) {\n if(!predicates[j](value)) {\n return false;\n }\n }\n return true;\n };\n\n if (comparatorType !== 'function') {\n if (comparatorType === 'boolean' && comparator) {\n comparator = function(obj, text) {\n return angular.equals(obj, text);\n };\n } else {\n comparator = function(obj, text) {\n text = (''+text).toLowerCase();\n return (''+obj).toLowerCase().indexOf(text) > -1;\n };\n }\n }\n\n var search = function(obj, text){\n if (typeof text == 'string' && text.charAt(0) === '!') {\n return !search(obj, text.substr(1));\n }\n switch (typeof obj) {\n case \"boolean\":\n case \"number\":\n case \"string\":\n return comparator(obj, text);\n case \"object\":\n switch (typeof text) {\n case \"object\":\n return comparator(obj, text);\n default:\n for ( var objKey in obj) {\n if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n return true;\n }\n }\n break;\n }\n return false;\n case \"array\":\n for ( var i = 0; i < obj.length; i++) {\n if (search(obj[i], text)) {\n return true;\n }\n }\n return false;\n default:\n return false;\n }\n };\n switch (typeof expression) {\n case \"boolean\":\n case \"number\":\n case \"string\":\n // Set up expression object and fall through\n expression = {$:expression};\n // jshint -W086\n case \"object\":\n // jshint +W086\n for (var key in expression) {\n if (key == '$') {\n (function() {\n if (!expression[key]) return;\n var path = key;\n predicates.push(function(value) {\n return search(value, expression[path]);\n });\n })();\n } else {\n (function() {\n if (typeof(expression[key]) == 'undefined') { return; }\n var path = key;\n predicates.push(function(value) {\n return search(getter(value,path), expression[path]);\n });\n })();\n }\n }\n break;\n case 'function':\n predicates.push(expression);\n break;\n default:\n return array;\n }\n var filtered = [];\n for ( var j = 0; j < array.length; j++) {\n var value = array[j];\n if (predicates.check(value)) {\n filtered.push(value);\n }\n }\n return filtered;\n };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:currency\n * @function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n
\n \n \n \n
\n default currency symbol ($): {{amount | currency}}
\n custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n
\n \n \n it('should init with 1234.56', function() {\n expect(binding('amount | currency')).toBe('$1,234.56');\n expect(binding('amount | currency:\"USD$\"')).toBe('USD$1,234.56');\n });\n it('should update', function() {\n input('amount').enter('-1234');\n expect(binding('amount | currency')).toBe('($1,234.00)');\n expect(binding('amount | currency:\"USD$\"')).toBe('(USD$1,234.00)');\n });\n \n \n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n var formats = $locale.NUMBER_FORMATS;\n return function(amount, currencySymbol){\n if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n replace(/\\u00A4/g, currencySymbol);\n };\n}\n\n/**\n * @ngdoc filter\n * @name ng.filter:number\n * @function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} fractionSize Number of decimal places to round the number to.\n * If this is not provided then the fraction size is computed from the current locale's number\n * formatting pattern. In the case of the default locale, it will be 3.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n
\n \n \n \n Enter number:
\n Default formatting: {{val | number}}
\n No fractions: {{val | number:0}}
\n Negative number: {{-val | number:4}}\n
\n \n \n it('should format numbers', function() {\n expect(binding('val | number')).toBe('1,234.568');\n expect(binding('val | number:0')).toBe('1,235');\n expect(binding('-val | number:4')).toBe('-1,234.5679');\n });\n\n it('should update', function() {\n input('val').enter('3374.333');\n expect(binding('val | number')).toBe('3,374.333');\n expect(binding('val | number:0')).toBe('3,374');\n expect(binding('-val | number:4')).toBe('-3,374.3330');\n });\n \n \n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n var formats = $locale.NUMBER_FORMATS;\n return function(number, fractionSize) {\n return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n fractionSize);\n };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n if (isNaN(number) || !isFinite(number)) return '';\n\n var isNegative = number < 0;\n number = Math.abs(number);\n var numStr = number + '',\n formatedText = '',\n parts = [];\n\n var hasExponent = false;\n if (numStr.indexOf('e') !== -1) {\n var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n numStr = '0';\n } else {\n formatedText = numStr;\n hasExponent = true;\n }\n }\n\n if (!hasExponent) {\n var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n // determine fractionSize if it is not specified\n if (isUndefined(fractionSize)) {\n fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n }\n\n var pow = Math.pow(10, fractionSize);\n number = Math.round(number * pow) / pow;\n var fraction = ('' + number).split(DECIMAL_SEP);\n var whole = fraction[0];\n fraction = fraction[1] || '';\n\n var i, pos = 0,\n lgroup = pattern.lgSize,\n group = pattern.gSize;\n\n if (whole.length >= (lgroup + group)) {\n pos = whole.length - lgroup;\n for (i = 0; i < pos; i++) {\n if ((pos - i)%group === 0 && i !== 0) {\n formatedText += groupSep;\n }\n formatedText += whole.charAt(i);\n }\n }\n\n for (i = pos; i < whole.length; i++) {\n if ((whole.length - i)%lgroup === 0 && i !== 0) {\n formatedText += groupSep;\n }\n formatedText += whole.charAt(i);\n }\n\n // format fraction part.\n while(fraction.length < fractionSize) {\n fraction += '0';\n }\n\n if (fractionSize && fractionSize !== \"0\") formatedText += decimalSep + fraction.substr(0, fractionSize);\n } else {\n\n if (fractionSize > 0 && number > -1 && number < 1) {\n formatedText = number.toFixed(fractionSize);\n }\n }\n\n parts.push(isNegative ? pattern.negPre : pattern.posPre);\n parts.push(formatedText);\n parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n var neg = '';\n if (num < 0) {\n neg = '-';\n num = -num;\n }\n num = '' + num;\n while(num.length < digits) num = '0' + num;\n if (trim)\n num = num.substr(num.length - digits);\n return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n offset = offset || 0;\n return function(date) {\n var value = date['get' + name]();\n if (offset > 0 || value > -offset)\n value += offset;\n if (value === 0 && offset == -12 ) value = 12;\n return padNumber(value, size, trim);\n };\n}\n\nfunction dateStrGetter(name, shortForm) {\n return function(date, formats) {\n var value = date['get' + name]();\n var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n return formats[get][value];\n };\n}\n\nfunction timeZoneGetter(date) {\n var zone = -1 * date.getTimezoneOffset();\n var paddedZone = (zone >= 0) ? \"+\" : \"\";\n\n paddedZone += padNumber(Math[zone > 0 ? 'floor' : 'ceil'](zone / 60), 2) +\n padNumber(Math.abs(zone % 60), 2);\n\n return paddedZone;\n}\n\nfunction ampmGetter(date, formats) {\n return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n yyyy: dateGetter('FullYear', 4),\n yy: dateGetter('FullYear', 2, 0, true),\n y: dateGetter('FullYear', 1),\n MMMM: dateStrGetter('Month'),\n MMM: dateStrGetter('Month', true),\n MM: dateGetter('Month', 2, 1),\n M: dateGetter('Month', 1, 1),\n dd: dateGetter('Date', 2),\n d: dateGetter('Date', 1),\n HH: dateGetter('Hours', 2),\n H: dateGetter('Hours', 1),\n hh: dateGetter('Hours', 2, -12),\n h: dateGetter('Hours', 1, -12),\n mm: dateGetter('Minutes', 2),\n m: dateGetter('Minutes', 1),\n ss: dateGetter('Seconds', 2),\n s: dateGetter('Seconds', 1),\n // while ISO 8601 requires fractions to be prefixed with `.` or `,`\n // we can be just safely rely on using `sss` since we currently don't support single or two digit fractions\n sss: dateGetter('Milliseconds', 3),\n EEEE: dateStrGetter('Day'),\n EEE: dateStrGetter('Day', true),\n a: ampmGetter,\n Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n NUMBER_STRING = /^\\-?\\d+$/;\n\n/**\n * @ngdoc filter\n * @name ng.filter:date\n * @function\n *\n * @description\n * Formats `date` to a string based on the requested `format`.\n *\n * `format` string can be composed of the following elements:\n *\n * * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n * * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n * * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n * * `'MMMM'`: Month in year (January-December)\n * * `'MMM'`: Month in year (Jan-Dec)\n * * `'MM'`: Month in year, padded (01-12)\n * * `'M'`: Month in year (1-12)\n * * `'dd'`: Day in month, padded (01-31)\n * * `'d'`: Day in month (1-31)\n * * `'EEEE'`: Day in Week,(Sunday-Saturday)\n * * `'EEE'`: Day in Week, (Sun-Sat)\n * * `'HH'`: Hour in day, padded (00-23)\n * * `'H'`: Hour in day (0-23)\n * * `'hh'`: Hour in am/pm, padded (01-12)\n * * `'h'`: Hour in am/pm, (1-12)\n * * `'mm'`: Minute in hour, padded (00-59)\n * * `'m'`: Minute in hour (0-59)\n * * `'ss'`: Second in minute, padded (00-59)\n * * `'s'`: Second in minute (0-59)\n * * `'.sss' or ',sss'`: Millisecond in second, padded (000-999)\n * * `'a'`: am/pm marker\n * * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200)\n *\n * `format` string can also be one of the following predefined\n * {@link guide/i18n localizable formats}:\n *\n * * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n * (e.g. Sep 3, 2010 12:05:08 pm)\n * * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US locale (e.g. 9/3/10 12:05 pm)\n * * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US locale\n * (e.g. Friday, September 3, 2010)\n * * `'longDate'`: equivalent to `'MMMM d, y'` for en_US locale (e.g. September 3, 2010)\n * * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US locale (e.g. Sep 3, 2010)\n * * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n * * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n * * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n * `format` string can contain literal values. These need to be quoted with single quotes (e.g.\n * `\"h 'in the morning'\"`). In order to output single quote, use two single quotes in a sequence\n * (e.g. `\"h 'o''clock'\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n * number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and its\n * shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ). If no timezone is\n * specified in the string input, the time is considered to be in the local timezone.\n * @param {string=} format Formatting rules (see Description). If not specified,\n * `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n
\n \n {{1288323623006 | date:'medium'}}:\n {{1288323623006 | date:'medium'}}
\n {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}:\n {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}
\n {{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}:\n {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}
\n \n \n it('should format date', function() {\n expect(binding(\"1288323623006 | date:'medium'\")).\n toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n expect(binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).\n toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} (\\-|\\+)?\\d{4}/);\n expect(binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).\n toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n });\n \n \n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n // 1 2 3 4 5 6 7 8 9 10 11\n function jsonStringToDate(string) {\n var match;\n if (match = string.match(R_ISO8601_STR)) {\n var date = new Date(0),\n tzHour = 0,\n tzMin = 0,\n dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear,\n timeSetter = match[8] ? date.setUTCHours : date.setHours;\n\n if (match[9]) {\n tzHour = int(match[9] + match[10]);\n tzMin = int(match[9] + match[11]);\n }\n dateSetter.call(date, int(match[1]), int(match[2]) - 1, int(match[3]));\n var h = int(match[4]||0) - tzHour;\n var m = int(match[5]||0) - tzMin;\n var s = int(match[6]||0);\n var ms = Math.round(parseFloat('0.' + (match[7]||0)) * 1000);\n timeSetter.call(date, h, m, s, ms);\n return date;\n }\n return string;\n }\n\n\n return function(date, format) {\n var text = '',\n parts = [],\n fn, match;\n\n format = format || 'mediumDate';\n format = $locale.DATETIME_FORMATS[format] || format;\n if (isString(date)) {\n if (NUMBER_STRING.test(date)) {\n date = int(date);\n } else {\n date = jsonStringToDate(date);\n }\n }\n\n if (isNumber(date)) {\n date = new Date(date);\n }\n\n if (!isDate(date)) {\n return date;\n }\n\n while(format) {\n match = DATE_FORMATS_SPLIT.exec(format);\n if (match) {\n parts = concat(parts, match, 1);\n format = parts.pop();\n } else {\n parts.push(format);\n format = null;\n }\n }\n\n forEach(parts, function(value){\n fn = DATE_FORMATS[value];\n text += fn ? fn(date, $locale.DATETIME_FORMATS)\n : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n });\n\n return text;\n };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:json\n * @function\n *\n * @description\n * Allows you to convert a JavaScript object into JSON string.\n *\n * This filter is mostly useful for debugging. When using the double curly {{value}} notation\n * the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example:\n
\n \n {{ {'name':'value'} | json }}
\n \n \n it('should jsonify filtered objects', function() {\n expect(binding(\"{'name':'value'}\")).toMatch(/\\{\\n \"name\": ?\"value\"\\n}/);\n });\n \n \n *\n */\nfunction jsonFilter() {\n return function(object) {\n return toJson(object, true);\n };\n}\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:lowercase\n * @function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name ng.filter:uppercase\n * @function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc function\n * @name ng.filter:limitTo\n * @function\n *\n * @description\n * Creates a new array or string containing only a specified number of elements. The elements\n * are taken from either the beginning or the end of the source array or string, as specified by\n * the value and sign (positive or negative) of `limit`.\n *\n * @param {Array|string} input Source array or string to be limited.\n * @param {string|number} limit The length of the returned array or string. If the `limit` number \n * is positive, `limit` number of items from the beginning of the source array/string are copied.\n * If the number is negative, `limit` number of items from the end of the source array/string \n * are copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array|string} A new sub-array or substring of length `limit` or less if input array\n * had less than `limit` elements.\n *\n * @example\n
\n \n \n \n Limit {{numbers}} to:
\n
Output numbers: {{ numbers | limitTo:numLimit }}
\n Limit {{letters}} to:
\n
Output letters: {{ letters | limitTo:letterLimit }}
\n
\n \n \n it('should limit the number array to first three items', function() {\n expect(element('.doc-example-live input[ng-model=numLimit]').val()).toBe('3');\n expect(element('.doc-example-live input[ng-model=letterLimit]').val()).toBe('3');\n expect(binding('numbers | limitTo:numLimit')).toEqual('[1,2,3]');\n expect(binding('letters | limitTo:letterLimit')).toEqual('abc');\n });\n\n it('should update the output when -3 is entered', function() {\n input('numLimit').enter(-3);\n input('letterLimit').enter(-3);\n expect(binding('numbers | limitTo:numLimit')).toEqual('[7,8,9]');\n expect(binding('letters | limitTo:letterLimit')).toEqual('ghi');\n });\n\n it('should not exceed the maximum size of input array', function() {\n input('numLimit').enter(100);\n input('letterLimit').enter(100);\n expect(binding('numbers | limitTo:numLimit')).toEqual('[1,2,3,4,5,6,7,8,9]');\n expect(binding('letters | limitTo:letterLimit')).toEqual('abcdefghi');\n });\n \n \n */\nfunction limitToFilter(){\n return function(input, limit) {\n if (!isArray(input) && !isString(input)) return input;\n \n limit = int(limit);\n\n if (isString(input)) {\n //NaN check on limit\n if (limit) {\n return limit >= 0 ? input.slice(0, limit) : input.slice(limit, input.length);\n } else {\n return \"\";\n }\n }\n\n var out = [],\n i, n;\n\n // if abs(limit) exceeds maximum length, trim it\n if (limit > input.length)\n limit = input.length;\n else if (limit < -input.length)\n limit = -input.length;\n\n if (limit > 0) {\n i = 0;\n n = limit;\n } else {\n i = input.length + limit;\n n = input.length;\n }\n\n for (; i
} expression A predicate to be\n * used by the comparator to determine the order of elements.\n *\n * Can be one of:\n *\n * - `function`: Getter function. The result of this function will be sorted using the\n * `<`, `=`, `>` operator.\n * - `string`: An Angular expression which evaluates to an object to order by, such as 'name'\n * to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control\n * ascending or descending sort order (for example, +name or -name).\n * - `Array`: An array of function or string predicates. The first predicate in the array\n * is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * @param {boolean=} reverse Reverse the order the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n \n \n \n \n
Sorting predicate = {{predicate}}; reverse = {{reverse}}
\n
\n [
unsorted ]\n
\n \n Name\n (^) | \n Phone Number | \n Age | \n
\n \n {{friend.name}} | \n {{friend.phone}} | \n {{friend.age}} | \n
\n
\n
\n \n \n it('should be reverse ordered by aged', function() {\n expect(binding('predicate')).toBe('-age');\n expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n toEqual(['35', '29', '21', '19', '10']);\n expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);\n });\n\n it('should reorder the table when user selects different predicate', function() {\n element('.doc-example-live a:contains(\"Name\")').click();\n expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);\n expect(repeater('table.friend', 'friend in friends').column('friend.age')).\n toEqual(['35', '10', '29', '19', '21']);\n\n element('.doc-example-live a:contains(\"Phone\")').click();\n expect(repeater('table.friend', 'friend in friends').column('friend.phone')).\n toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);\n expect(repeater('table.friend', 'friend in friends').column('friend.name')).\n toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);\n });\n \n \n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n return function(array, sortPredicate, reverseOrder) {\n if (!isArray(array)) return array;\n if (!sortPredicate) return array;\n sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n sortPredicate = map(sortPredicate, function(predicate){\n var descending = false, get = predicate || identity;\n if (isString(predicate)) {\n if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n descending = predicate.charAt(0) == '-';\n predicate = predicate.substring(1);\n }\n get = $parse(predicate);\n }\n return reverseComparator(function(a,b){\n return compare(get(a),get(b));\n }, descending);\n });\n var arrayCopy = [];\n for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }\n return arrayCopy.sort(reverseComparator(comparator, reverseOrder));\n\n function comparator(o1, o2){\n for ( var i = 0; i < sortPredicate.length; i++) {\n var comp = sortPredicate[i](o1, o2);\n if (comp !== 0) return comp;\n }\n return 0;\n }\n function reverseComparator(comp, descending) {\n return toBoolean(descending)\n ? function(a,b){return comp(b,a);}\n : comp;\n }\n function compare(v1, v2){\n var t1 = typeof v1;\n var t2 = typeof v2;\n if (t1 == t2) {\n if (t1 == \"string\") {\n v1 = v1.toLowerCase();\n v2 = v2.toLowerCase();\n }\n if (v1 === v2) return 0;\n return v1 < v2 ? -1 : 1;\n } else {\n return t1 < t2 ? -1 : 1;\n }\n }\n };\n}\n\nfunction ngDirective(directive) {\n if (isFunction(directive)) {\n directive = {\n link: directive\n };\n }\n directive.restrict = directive.restrict || 'AC';\n return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name ng.directive:a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of the html A tag so that the default action is prevented when\n * the href attribute is empty.\n *\n * This change permits the easy creation of action links with the `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * `Add Item`\n */\nvar htmlAnchorDirective = valueFn({\n restrict: 'E',\n compile: function(element, attr) {\n\n if (msie <= 8) {\n\n // turn link into a stylable link in IE\n // but only if it doesn't have name attribute, in which case it's an anchor\n if (!attr.href && !attr.name) {\n attr.$set('href', '');\n }\n\n // add a comment node to anchors to workaround IE bug that causes element content to be reset\n // to new attribute content if attribute is updated with value containing @ and element also\n // contains value with @\n // see issue #1949\n element.append(document.createComment('IE fix'));\n }\n\n return function(scope, element) {\n element.on('click', function(event){\n // if we have no href url, then don't navigate anywhere.\n if (!element.attr('href')) {\n event.preventDefault();\n }\n });\n };\n }\n});\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngHref\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in an href attribute will\n * make the link go to the wrong URL if the user clicks it before\n * Angular has a chance to replace the `{{hash}}` markup with its\n * value. Until Angular replaces the markup the link will be broken\n * and will most likely return a 404 error.\n *\n * The `ngHref` directive solves this problem.\n *\n * The wrong way to write it:\n * \n * \n *
\n *\n * The correct way to write it:\n * \n * \n *
\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example shows various combinations of `href`, `ng-href` and `ng-click` attributes\n * in links and their different behaviors:\n \n \n
\n link 1 (link, don't reload)
\n link 2 (link, don't reload)
\n link 3 (link, reload!)
\n anchor (link, don't reload)
\n anchor (no link)
\n link (link, change location)\n \n \n it('should execute ng-click but not reload when href without value', function() {\n element('#link-1').click();\n expect(input('value').val()).toEqual('1');\n expect(element('#link-1').attr('href')).toBe(\"\");\n });\n\n it('should execute ng-click but not reload when href empty string', function() {\n element('#link-2').click();\n expect(input('value').val()).toEqual('2');\n expect(element('#link-2').attr('href')).toBe(\"\");\n });\n\n it('should execute ng-click and change url when ng-href specified', function() {\n expect(element('#link-3').attr('href')).toBe(\"/123\");\n\n element('#link-3').click();\n expect(browser().window().path()).toEqual('/123');\n });\n\n it('should execute ng-click but not reload when href empty string and name specified', function() {\n element('#link-4').click();\n expect(input('value').val()).toEqual('4');\n expect(element('#link-4').attr('href')).toBe('');\n });\n\n it('should execute ng-click but not reload when no href but name specified', function() {\n element('#link-5').click();\n expect(input('value').val()).toEqual('5');\n expect(element('#link-5').attr('href')).toBe(undefined);\n });\n\n it('should only change url when only ng-href', function() {\n input('value').enter('6');\n expect(element('#link-6').attr('href')).toBe('6');\n\n element('#link-6').click();\n expect(browser().location().url()).toEqual('/6');\n });\n \n \n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrc\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * \n *
\n *
\n *\n * The correct way to write it:\n * \n *
\n *
\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSrcset\n * @restrict A\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `srcset` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrcset` directive solves this problem.\n *\n * The buggy way to write it:\n * \n *
\n *
\n *\n * The correct way to write it:\n * \n *
\n *
\n *\n * @element IMG\n * @param {template} ngSrcset any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngDisabled\n * @restrict A\n *\n * @description\n *\n * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * \n * \n * \n *
\n *
\n *\n * The HTML specification does not require browsers to preserve the values of boolean attributes\n * such as disabled. (Their presence means true and their absence means false.)\n * If we put an Angular interpolation expression into such an attribute then the\n * binding information would be lost when the browser removes the attribute.\n * The `ngDisabled` directive solves this problem for the `disabled` attribute.\n * This complementary directive is not removed by the browser and so provides\n * a permanent reliable place to store the binding information.\n *\n * @example\n \n \n Click me to toggle:
\n \n \n \n it('should toggle button', function() {\n expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();\n input('checked').check();\n expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();\n });\n \n \n *\n * @element INPUT\n * @param {expression} ngDisabled If the {@link guide/expression expression} is truthy, \n * then special attribute \"disabled\" will be set on the element\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngChecked\n * @restrict A\n *\n * @description\n * The HTML specification does not require browsers to preserve the values of boolean attributes\n * such as checked. (Their presence means true and their absence means false.)\n * If we put an Angular interpolation expression into such an attribute then the\n * binding information would be lost when the browser removes the attribute.\n * The `ngChecked` directive solves this problem for the `checked` attribute.\n * This complementary directive is not removed by the browser and so provides\n * a permanent reliable place to store the binding information.\n * @example\n \n \n Check me to check both:
\n \n \n \n it('should check both checkBoxes', function() {\n expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();\n input('master').check();\n expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();\n });\n \n \n *\n * @element INPUT\n * @param {expression} ngChecked If the {@link guide/expression expression} is truthy, \n * then special attribute \"checked\" will be set on the element\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngReadonly\n * @restrict A\n *\n * @description\n * The HTML specification does not require browsers to preserve the values of boolean attributes\n * such as readonly. (Their presence means true and their absence means false.)\n * If we put an Angular interpolation expression into such an attribute then the\n * binding information would be lost when the browser removes the attribute.\n * The `ngReadonly` directive solves this problem for the `readonly` attribute.\n * This complementary directive is not removed by the browser and so provides\n * a permanent reliable place to store the binding information.\n\n * @example\n \n \n Check me to make text readonly:
\n \n \n \n it('should toggle readonly attr', function() {\n expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();\n input('checked').check();\n expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();\n });\n \n \n *\n * @element INPUT\n * @param {expression} ngReadonly If the {@link guide/expression expression} is truthy, \n * then special attribute \"readonly\" will be set on the element\n */\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngSelected\n * @restrict A\n *\n * @description\n * The HTML specification does not require browsers to preserve the values of boolean attributes\n * such as selected. (Their presence means true and their absence means false.)\n * If we put an Angular interpolation expression into such an attribute then the\n * binding information would be lost when the browser removes the attribute.\n * The `ngSelected` directive solves this problem for the `selected` atttribute.\n * This complementary directive is not removed by the browser and so provides\n * a permanent reliable place to store the binding information.\n * @example\n \n \n Check me to select:
\n \n \n \n it('should select Greetings!', function() {\n expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();\n input('selected').check();\n expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();\n });\n \n \n *\n * @element OPTION\n * @param {expression} ngSelected If the {@link guide/expression expression} is truthy, \n * then special attribute \"selected\" will be set on the element\n */\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngOpen\n * @restrict A\n *\n * @description\n * The HTML specification does not require browsers to preserve the values of boolean attributes\n * such as open. (Their presence means true and their absence means false.)\n * If we put an Angular interpolation expression into such an attribute then the\n * binding information would be lost when the browser removes the attribute.\n * The `ngOpen` directive solves this problem for the `open` attribute.\n * This complementary directive is not removed by the browser and so provides\n * a permanent reliable place to store the binding information.\n\n *\n * @example\n \n \n Check me check multiple:
\n \n Show/Hide me
\n \n \n \n it('should toggle open', function() {\n expect(element('#details').prop('open')).toBeFalsy();\n input('open').check();\n expect(element('#details').prop('open')).toBeTruthy();\n });\n \n \n *\n * @element DETAILS\n * @param {expression} ngOpen If the {@link guide/expression expression} is truthy, \n * then special attribute \"open\" will be set on the element\n */\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n // binding to multiple is not supported\n if (propName == \"multiple\") return;\n\n var normalized = directiveNormalize('ng-' + attrName);\n ngAttributeAliasDirectives[normalized] = function() {\n return {\n priority: 100,\n compile: function() {\n return function(scope, element, attr) {\n scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n attr.$set(attrName, !!value);\n });\n };\n }\n };\n };\n});\n\n\n// ng-src, ng-srcset, ng-href are interpolated\nforEach(['src', 'srcset', 'href'], function(attrName) {\n var normalized = directiveNormalize('ng-' + attrName);\n ngAttributeAliasDirectives[normalized] = function() {\n return {\n priority: 99, // it needs to run after the attributes are interpolated\n link: function(scope, element, attr) {\n attr.$observe(normalized, function(value) {\n if (!value)\n return;\n\n attr.$set(attrName, value);\n\n // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n // to set the property as well to achieve the desired effect.\n // we use attr[attrName] value since $set can sanitize the url.\n if (msie) element.prop(attrName, attr[attrName]);\n });\n }\n };\n };\n});\n\n/* global -nullFormCtrl */\nvar nullFormCtrl = {\n $addControl: noop,\n $removeControl: noop,\n $setValidity: noop,\n $setDirty: noop,\n $setPristine: noop\n};\n\n/**\n * @ngdoc object\n * @name ng.directive:form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n * forms, where:\n *\n * - keys are validation tokens (error names) — such as `required`, `url` or `email`,\n * - values are arrays of controls or forms that are invalid with given error.\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope'];\nfunction FormController(element, attrs) {\n var form = this,\n parentForm = element.parent().controller('form') || nullFormCtrl,\n invalidCount = 0, // used to easily determine if we are valid\n errors = form.$error = {},\n controls = [];\n\n // init state\n form.$name = attrs.name || attrs.ngForm;\n form.$dirty = false;\n form.$pristine = true;\n form.$valid = true;\n form.$invalid = false;\n\n parentForm.$addControl(form);\n\n // Setup initial state of the control\n element.addClass(PRISTINE_CLASS);\n toggleValidCss(true);\n\n // convenience method for easy toggling of classes\n function toggleValidCss(isValid, validationErrorKey) {\n validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n element.\n removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).\n addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n }\n\n /**\n * @ngdoc function\n * @name ng.directive:form.FormController#$addControl\n * @methodOf ng.directive:form.FormController\n *\n * @description\n * Register a control with the form.\n *\n * Input elements using ngModelController do this automatically when they are linked.\n */\n form.$addControl = function(control) {\n // Breaking change - before, inputs whose name was \"hasOwnProperty\" were quietly ignored\n // and not added to the scope. Now we throw an error.\n assertNotHasOwnProperty(control.$name, 'input');\n controls.push(control);\n\n if (control.$name) {\n form[control.$name] = control;\n }\n };\n\n /**\n * @ngdoc function\n * @name ng.directive:form.FormController#$removeControl\n * @methodOf ng.directive:form.FormController\n *\n * @description\n * Deregister a control from the form.\n *\n * Input elements using ngModelController do this automatically when they are destroyed.\n */\n form.$removeControl = function(control) {\n if (control.$name && form[control.$name] === control) {\n delete form[control.$name];\n }\n forEach(errors, function(queue, validationToken) {\n form.$setValidity(validationToken, true, control);\n });\n\n arrayRemove(controls, control);\n };\n\n /**\n * @ngdoc function\n * @name ng.directive:form.FormController#$setValidity\n * @methodOf ng.directive:form.FormController\n *\n * @description\n * Sets the validity of a form control.\n *\n * This method will also propagate to parent forms.\n */\n form.$setValidity = function(validationToken, isValid, control) {\n var queue = errors[validationToken];\n\n if (isValid) {\n if (queue) {\n arrayRemove(queue, control);\n if (!queue.length) {\n invalidCount--;\n if (!invalidCount) {\n toggleValidCss(isValid);\n form.$valid = true;\n form.$invalid = false;\n }\n errors[validationToken] = false;\n toggleValidCss(true, validationToken);\n parentForm.$setValidity(validationToken, true, form);\n }\n }\n\n } else {\n if (!invalidCount) {\n toggleValidCss(isValid);\n }\n if (queue) {\n if (includes(queue, control)) return;\n } else {\n errors[validationToken] = queue = [];\n invalidCount++;\n toggleValidCss(false, validationToken);\n parentForm.$setValidity(validationToken, false, form);\n }\n queue.push(control);\n\n form.$valid = false;\n form.$invalid = true;\n }\n };\n\n /**\n * @ngdoc function\n * @name ng.directive:form.FormController#$setDirty\n * @methodOf ng.directive:form.FormController\n *\n * @description\n * Sets the form to a dirty state.\n *\n * This method can be called to add the 'ng-dirty' class and set the form to a dirty\n * state (ng-dirty class). This method will also propagate to parent forms.\n */\n form.$setDirty = function() {\n element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);\n form.$dirty = true;\n form.$pristine = false;\n parentForm.$setDirty();\n };\n\n /**\n * @ngdoc function\n * @name ng.directive:form.FormController#$setPristine\n * @methodOf ng.directive:form.FormController\n *\n * @description\n * Sets the form to its pristine state.\n *\n * This method can be called to remove the 'ng-dirty' class and set the form to its pristine\n * state (ng-pristine class). This method will also propagate to all the controls contained\n * in this form.\n *\n * Setting a form back to a pristine state is often useful when we want to 'reuse' a form after\n * saving or resetting it.\n */\n form.$setPristine = function () {\n element.removeClass(DIRTY_CLASS).addClass(PRISTINE_CLASS);\n form.$dirty = false;\n form.$pristine = true;\n forEach(controls, function(control) {\n control.$setPristine();\n });\n };\n}\n\n\n/**\n * @ngdoc directive\n * @name ng.directive:ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * @param {string=} ngForm|name Name of the form. If specified, the form controller will be published into\n * related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name ng.directive:form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link ng.directive:form.FormController FormController}.\n *\n * If the `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In Angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However, browsers do not allow nesting of `