From baa6ab26449e00639809423a41438a18343d02f0 Mon Sep 17 00:00:00 2001 From: Plastiquewind Date: Wed, 17 Jan 2018 23:42:11 +0500 Subject: [PATCH] Added cross-domain-storage --- app.d6ee7810cac7e6943ab8.js | 40 +++++++++++++++ app.d6ee7810cac7e6943ab8.js.map | 1 + index.html | 2 +- package.json | 6 ++- src/app/components/main/index.ts | 9 +++- src/app/components/main/main.component.ts | 4 +- vendor.d6ee7810cac7e6943ab8.js | 62 +++++++++++++++++++++++ vendor.d6ee7810cac7e6943ab8.js.map | 1 + webpack.config.js | 2 +- 9 files changed, 120 insertions(+), 7 deletions(-) create mode 100644 app.d6ee7810cac7e6943ab8.js create mode 100644 app.d6ee7810cac7e6943ab8.js.map create mode 100644 vendor.d6ee7810cac7e6943ab8.js create mode 100644 vendor.d6ee7810cac7e6943ab8.js.map diff --git a/app.d6ee7810cac7e6943ab8.js b/app.d6ee7810cac7e6943ab8.js new file mode 100644 index 0000000..6ee6ecb --- /dev/null +++ b/app.d6ee7810cac7e6943ab8.js @@ -0,0 +1,40 @@ +webpackJsonp([0],[function(e,t,n){"use strict";function r(e,t,n){"ngInject";n.state("app",{redirectTo:"app.main","abstract":!0,component:"app"}),e.html5Mode(!0),t.otherwise("/")}function a(e){"ngInject";e.theme("default").primaryPalette("blue").accentPalette("red")}function s(){o.options.positionClass="toast-bottom-right",o.options.closeButton=!0}r.$inject=["$locationProvider","$urlRouterProvider","$stateProvider"],a.$inject=["$mdThemingProvider"],Object.defineProperty(t,"__esModule",{value:!0});var i=n(1),o=n(3),d=n(6),u=n(8),l=n(215);n(231);var _=i.module("app",["ui.router","ngMessages","ngMaterial","ngAria","ngAnimate",u["default"].name,l["default"].name]).config(r).config(a).config(s).component("app",new d.AppComponent);t["default"]=_},,,function(e,t,n){var r,a;!function(s){r=[n(4)],a=function(e){return function(){function t(e,t,n){return f({type:Y.error,iconClass:h().iconClasses.error,message:e,optionsOverride:n,title:t})}function n(t,n){return t||(t=h()),y=e("#"+t.containerId),y.length?y:(n&&(y=_(t)),y)}function r(e,t,n){return f({type:Y.info,iconClass:h().iconClasses.info,message:e,optionsOverride:n,title:t})}function a(e){M=e}function s(e,t,n){return f({type:Y.success,iconClass:h().iconClasses.success,message:e,optionsOverride:n,title:t})}function i(e,t,n){return f({type:Y.warning,iconClass:h().iconClasses.warning,message:e,optionsOverride:n,title:t})}function o(e,t){var r=h();y||n(r),l(e,r,t)||u(r)}function d(t){var r=h();return y||n(r),t&&0===e(":focus",t).length?void p(t):void(y.children().length&&y.remove())}function u(t){for(var n=y.children(),r=n.length-1;r>=0;r--)l(e(n[r]),t)}function l(t,n,r){var a=!(!r||!r.force)&&r.force;return!(!t||!a&&0!==e(":focus",t).length)&&(t[n.hideMethod]({duration:n.hideDuration,easing:n.hideEasing,complete:function(){p(t)}}),!0)}function _(t){return y=e("
").attr("id",t.containerId).addClass(t.positionClass),y.appendTo(e(t.target)),y}function c(){return{tapToDismiss:!0,toastClass:"toast",containerId:"toast-container",debug:!1,showMethod:"fadeIn",showDuration:300,showEasing:"swing",onShown:void 0,hideMethod:"fadeOut",hideDuration:1e3,hideEasing:"swing",onHidden:void 0,closeMethod:!1,closeDuration:!1,closeEasing:!1,closeOnHover:!0,extendedTimeOut:1e3,iconClasses:{error:"toast-error",info:"toast-info",success:"toast-success",warning:"toast-warning"},iconClass:"toast-info",positionClass:"toast-top-right",timeOut:5e3,titleClass:"toast-title",messageClass:"toast-message",escapeHtml:!1,target:"body",closeHtml:'',closeClass:"toast-close-button",newestOnTop:!0,preventDuplicates:!1,progressBar:!1,progressClass:"toast-progress",rtl:!1}}function m(e){M&&M(e)}function f(t){function r(e){return null==e&&(e=""),e.replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(//g,">")}function a(){d(),l(),_(),c(),f(),M(),u(),s()}function s(){var e="";switch(t.iconClass){case"toast-success":case"toast-info":e="polite";break;default:e="assertive"}x.attr("aria-live",e)}function i(){T.closeOnHover&&x.hover(D,k),!T.onclick&&T.tapToDismiss&&x.click(v),T.closeButton&&P&&P.click(function(e){e.stopPropagation?e.stopPropagation():void 0!==e.cancelBubble&&e.cancelBubble!==!0&&(e.cancelBubble=!0),T.onCloseClick&&T.onCloseClick(e),v(!0)}),T.onclick&&x.click(function(e){T.onclick(e),v()})}function o(){x.hide(),x[T.showMethod]({duration:T.showDuration,easing:T.showEasing,complete:T.onShown}),T.timeOut>0&&(S=setTimeout(v,T.timeOut),A.maxHideTime=parseFloat(T.timeOut),A.hideEta=(new Date).getTime()+A.maxHideTime,T.progressBar&&(A.intervalId=setInterval(w,10)))}function d(){t.iconClass&&x.addClass(T.toastClass).addClass(b)}function u(){T.newestOnTop?y.prepend(x):y.append(x)}function l(){if(t.title){var e=t.title;T.escapeHtml&&(e=r(t.title)),j.append(e).addClass(T.titleClass),x.append(j)}}function _(){if(t.message){var e=t.message;T.escapeHtml&&(e=r(t.message)),H.append(e).addClass(T.messageClass),x.append(H)}}function c(){T.closeButton&&(P.addClass(T.closeClass).attr("role","button"),x.prepend(P))}function f(){T.progressBar&&(O.addClass(T.progressClass),x.prepend(O))}function M(){T.rtl&&x.addClass("rtl")}function Y(e,t){if(e.preventDuplicates){if(t.message===L)return!0;L=t.message}return!1}function v(t){var n=t&&T.closeMethod!==!1?T.closeMethod:T.hideMethod,r=t&&T.closeDuration!==!1?T.closeDuration:T.hideDuration,a=t&&T.closeEasing!==!1?T.closeEasing:T.hideEasing;if(!e(":focus",x).length||t)return clearTimeout(A.intervalId),x[n]({duration:r,easing:a,complete:function(){p(x),clearTimeout(S),T.onHidden&&"hidden"!==E.state&&T.onHidden(),E.state="hidden",E.endTime=new Date,m(E)}})}function k(){(T.timeOut>0||T.extendedTimeOut>0)&&(S=setTimeout(v,T.extendedTimeOut),A.maxHideTime=parseFloat(T.extendedTimeOut),A.hideEta=(new Date).getTime()+A.maxHideTime)}function D(){clearTimeout(S),A.hideEta=0,x.stop(!0,!0)[T.showMethod]({duration:T.showDuration,easing:T.showEasing})}function w(){var e=(A.hideEta-(new Date).getTime())/A.maxHideTime*100;O.width(e+"%")}var T=h(),b=t.iconClass||T.iconClass;if("undefined"!=typeof t.optionsOverride&&(T=e.extend(T,t.optionsOverride),b=t.optionsOverride.iconClass||b),!Y(T,t)){g++,y=n(T,!0);var S=null,x=e("
"),j=e("
"),H=e("
"),O=e("
"),P=e(T.closeHtml),A={intervalId:null,hideEta:null,maxHideTime:null},E={toastId:g,state:"visible",startTime:new Date,options:T,map:t};return a(),o(),i(),m(E),T.debug&&console&&console.log(E),x}}function h(){return e.extend({},c(),v.options)}function p(e){y||(y=n()),e.is(":visible")||(e.remove(),e=null,0===y.children().length&&(y.remove(),L=void 0))}var y,M,L,g=0,Y={error:"error",info:"info",success:"success",warning:"warning"},v={clear:o,remove:d,error:t,getContainer:n,info:r,options:{},subscribe:a,success:s,version:"2.1.4",warning:i};return v}()}.apply(t,r),!(void 0!==a&&(e.exports=a))}(n(5))},function(e,t,n){var r,a;/*! + * jQuery JavaScript Library v3.2.1 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2017-03-20T18:59Z + */ +!function(t,n){"use strict";"object"==typeof e&&"object"==typeof e.exports?e.exports=t.document?n(t,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return n(e)}:n(t)}("undefined"!=typeof window?window:this,function(n,s){"use strict";function i(e,t){t=t||ie;var n=t.createElement("script");n.text=e,t.head.appendChild(n).parentNode.removeChild(n)}function o(e){var t=!!e&&"length"in e&&e.length,n=Le.type(e);return"function"!==n&&!Le.isWindow(e)&&("array"===n||0===t||"number"==typeof t&&t>0&&t-1 in e)}function d(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}function u(e,t,n){return Le.isFunction(t)?Le.grep(e,function(e,r){return!!t.call(e,r,e)!==n}):t.nodeType?Le.grep(e,function(e){return e===t!==n}):"string"!=typeof t?Le.grep(e,function(e){return _e.call(t,e)>-1!==n}):xe.test(t)?Le.filter(t,e,n):(t=Le.filter(t,e),Le.grep(e,function(e){return _e.call(t,e)>-1!==n&&1===e.nodeType}))}function l(e,t){for(;(e=e[t])&&1!==e.nodeType;);return e}function _(e){var t={};return Le.each(e.match(Ee)||[],function(e,n){t[n]=!0}),t}function c(e){return e}function m(e){throw e}function f(e,t,n,r){var a;try{e&&Le.isFunction(a=e.promise)?a.call(e).done(t).fail(n):e&&Le.isFunction(a=e.then)?a.call(e,t,n):t.apply(void 0,[e].slice(r))}catch(e){n.apply(void 0,[e])}}function h(){ie.removeEventListener("DOMContentLoaded",h),n.removeEventListener("load",h),Le.ready()}function p(){this.expando=Le.expando+p.uid++}function y(e){return"true"===e||"false"!==e&&("null"===e?null:e===+e+""?+e:ze.test(e)?JSON.parse(e):e)}function M(e,t,n){var r;if(void 0===n&&1===e.nodeType)if(r="data-"+t.replace(Re,"-$&").toLowerCase(),n=e.getAttribute(r),"string"==typeof n){try{n=y(n)}catch(a){}Ie.set(e,t,n)}else n=void 0;return n}function L(e,t,n,r){var a,s=1,i=20,o=r?function(){return r.cur()}:function(){return Le.css(e,t,"")},d=o(),u=n&&n[3]||(Le.cssNumber[t]?"":"px"),l=(Le.cssNumber[t]||"px"!==u&&+d)&&Ue.exec(Le.css(e,t));if(l&&l[3]!==u){u=u||l[3],n=n||[],l=+d||1;do s=s||".5",l/=s,Le.style(e,t,l+u);while(s!==(s=o()/d)&&1!==s&&--i)}return n&&(l=+l||+d||0,a=n[1]?l+(n[1]+1)*n[2]:+n[2],r&&(r.unit=u,r.start=l,r.end=a)),a}function g(e){var t,n=e.ownerDocument,r=e.nodeName,a=Ve[r];return a?a:(t=n.body.appendChild(n.createElement(r)),a=Le.css(t,"display"),t.parentNode.removeChild(t),"none"===a&&(a="block"),Ve[r]=a,a)}function Y(e,t){for(var n,r,a=[],s=0,i=e.length;s-1)a&&a.push(s);else if(u=Le.contains(s.ownerDocument,s),i=v(_.appendChild(s),"script"),u&&k(i),n)for(l=0;s=i[l++];)Qe.test(s.type||"")&&n.push(s);return _}function w(){return!0}function T(){return!1}function b(){try{return ie.activeElement}catch(e){}}function S(e,t,n,r,a,s){var i,o;if("object"==typeof t){"string"!=typeof n&&(r=r||n,n=void 0);for(o in t)S(e,o,n,r,t[o],s);return e}if(null==r&&null==a?(a=n,r=n=void 0):null==a&&("string"==typeof n?(a=r,r=void 0):(a=r,r=n,n=void 0)),a===!1)a=T;else if(!a)return e;return 1===s&&(i=a,a=function(e){return Le().off(e),i.apply(this,arguments)},a.guid=i.guid||(i.guid=Le.guid++)),e.each(function(){Le.event.add(this,t,a,r,n)})}function x(e,t){return d(e,"table")&&d(11!==t.nodeType?t:t.firstChild,"tr")?Le(">tbody",e)[0]||e:e}function j(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function H(e){var t=dt.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function O(e,t){var n,r,a,s,i,o,d,u;if(1===t.nodeType){if($e.hasData(e)&&(s=$e.access(e),i=$e.set(t,s),u=s.events)){delete i.handle,i.events={};for(a in u)for(n=0,r=u[a].length;n1&&"string"==typeof f&&!ye.checkClone&&ot.test(f))return e.each(function(a){var s=e.eq(a);h&&(t[0]=f.call(this,a,s.html())),A(s,t,n,r)});if(c&&(a=D(t,e[0].ownerDocument,!1,e,r),s=a.firstChild,1===a.childNodes.length&&(a=s),s||r)){for(o=Le.map(v(a,"script"),j),d=o.length;_=0&&nk.cacheLength&&delete e[t.shift()],e[n+" "]=r}var t=[];return e}function r(e){return e[$]=!0,e}function a(e){var t=P.createElement("fieldset");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function s(e,t){for(var n=e.split("|"),r=n.length;r--;)k.attrHandle[n[r]]=t}function i(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function o(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function d(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function u(e){return function(t){return"form"in t?t.parentNode&&t.disabled===!1?"label"in t?"label"in t.parentNode?t.parentNode.disabled===e:t.disabled===e:t.isDisabled===e||t.isDisabled!==!e&&De(t)===e:t.disabled===e:"label"in t&&t.disabled===e}}function l(e){return r(function(t){return t=+t,r(function(n,r){for(var a,s=e([],n.length,t),i=s.length;i--;)n[a=s[i]]&&(n[a]=!(r[a]=n[a]))})})}function _(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}function c(){}function m(e){for(var t=0,n=e.length,r="";t1?function(t,n,r){for(var a=e.length;a--;)if(!e[a](t,n,r))return!1;return!0}:e[0]}function p(e,n,r){for(var a=0,s=n.length;a-1&&(r[u]=!(i[u]=_))}}else L=y(L===i?L.splice(f,L.length):L),s?s(null,i,L,d):Q.apply(i,L)})}function L(e){for(var t,n,r,a=e.length,s=k.relative[e[0].type],i=s||k.relative[" "],o=s?1:0,d=f(function(e){return e===t},i,!0),u=f(function(e){return ee(t,e)>-1},i,!0),l=[function(e,n,r){var a=!s&&(r||n!==x)||((t=n).nodeType?d(e,n,r):u(e,n,r));return t=null,a}];o1&&h(l),o>1&&m(e.slice(0,o-1).concat({value:" "===e[o-2].type?"*":""})).replace(oe,"$1"),n,o0,s=e.length>0,i=function(r,i,o,d,u){var l,_,c,m=0,f="0",h=r&&[],p=[],M=x,L=r||s&&k.find.TAG("*",u),g=z+=null==M?1:Math.random()||.1,Y=L.length;for(u&&(x=i===P||i||u);f!==Y&&null!=(l=L[f]);f++){if(s&&l){for(_=0,i||l.ownerDocument===P||(O(l),o=!E);c=e[_++];)if(c(l,i||P,o)){d.push(l);break}u&&(z=g)}a&&((l=!c&&l)&&m--,r&&h.push(l))}if(m+=f,a&&f!==m){for(_=0;c=n[_++];)c(h,p,i,o);if(r){if(m>0)for(;f--;)h[f]||p[f]||(p[f]=Z.call(d));p=y(p)}Q.apply(d,p),u&&!r&&p.length>0&&m+n.length>1&&t.uniqueSort(d)}return u&&(z=g,x=M),h};return a?r(i):i}var Y,v,k,D,w,T,b,S,x,j,H,O,P,A,E,F,C,W,N,$="sizzle"+1*new Date,I=e.document,z=0,R=0,J=n(),U=n(),q=n(),G=function(e,t){return e===t&&(H=!0),0},B={}.hasOwnProperty,V=[],Z=V.pop,K=V.push,Q=V.push,X=V.slice,ee=function(e,t){for(var n=0,r=e.length;n+~]|"+ne+")"+ne+"*"),le=new RegExp("="+ne+"*([^\\]'\"]*?)"+ne+"*\\]","g"),_e=new RegExp(se),ce=new RegExp("^"+re+"$"),me={ID:new RegExp("^#("+re+")"),CLASS:new RegExp("^\\.("+re+")"),TAG:new RegExp("^("+re+"|[*])"),ATTR:new RegExp("^"+ae),PSEUDO:new RegExp("^"+se),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+ne+"*(even|odd|(([+-]|)(\\d*)n|)"+ne+"*(?:([+-]|)"+ne+"*(\\d+)|))"+ne+"*\\)|)","i"),bool:new RegExp("^(?:"+te+")$","i"),needsContext:new RegExp("^"+ne+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+ne+"*((?:-\\d)?\\d*)"+ne+"*\\)|)(?=[^-]|$)","i")},fe=/^(?:input|select|textarea|button)$/i,he=/^h\d$/i,pe=/^[^{]+\{\s*\[native \w/,ye=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,Me=/[+~]/,Le=new RegExp("\\\\([\\da-f]{1,6}"+ne+"?|("+ne+")|.)","ig"),ge=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},Ye=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ve=function(e,t){return t?"\0"===e?"�":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},ke=function(){O()},De=f(function(e){return e.disabled===!0&&("form"in e||"label"in e)},{dir:"parentNode",next:"legend"});try{Q.apply(V=X.call(I.childNodes),I.childNodes),V[I.childNodes.length].nodeType}catch(we){Q={apply:V.length?function(e,t){K.apply(e,X.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}v=t.support={},w=t.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return!!t&&"HTML"!==t.nodeName},O=t.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:I;return r!==P&&9===r.nodeType&&r.documentElement?(P=r,A=P.documentElement,E=!w(P),I!==P&&(n=P.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",ke,!1):n.attachEvent&&n.attachEvent("onunload",ke)),v.attributes=a(function(e){return e.className="i",!e.getAttribute("className")}),v.getElementsByTagName=a(function(e){return e.appendChild(P.createComment("")),!e.getElementsByTagName("*").length}),v.getElementsByClassName=pe.test(P.getElementsByClassName),v.getById=a(function(e){return A.appendChild(e).id=$,!P.getElementsByName||!P.getElementsByName($).length}),v.getById?(k.filter.ID=function(e){var t=e.replace(Le,ge);return function(e){return e.getAttribute("id")===t}},k.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(k.filter.ID=function(e){var t=e.replace(Le,ge);return function(e){var n="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return n&&n.value===t}},k.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,a,s=t.getElementById(e);if(s){if(n=s.getAttributeNode("id"),n&&n.value===e)return[s];for(a=t.getElementsByName(e),r=0;s=a[r++];)if(n=s.getAttributeNode("id"),n&&n.value===e)return[s]}return[]}}),k.find.TAG=v.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):v.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],a=0,s=t.getElementsByTagName(e);if("*"===e){for(;n=s[a++];)1===n.nodeType&&r.push(n);return r}return s},k.find.CLASS=v.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},C=[],F=[],(v.qsa=pe.test(P.querySelectorAll))&&(a(function(e){A.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&F.push("[*^$]="+ne+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||F.push("\\["+ne+"*(?:value|"+te+")"),e.querySelectorAll("[id~="+$+"-]").length||F.push("~="),e.querySelectorAll(":checked").length||F.push(":checked"),e.querySelectorAll("a#"+$+"+*").length||F.push(".#.+[+~]")}),a(function(e){e.innerHTML="";var t=P.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&F.push("name"+ne+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&F.push(":enabled",":disabled"),A.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&F.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),F.push(",.*:")})),(v.matchesSelector=pe.test(W=A.matches||A.webkitMatchesSelector||A.mozMatchesSelector||A.oMatchesSelector||A.msMatchesSelector))&&a(function(e){v.disconnectedMatch=W.call(e,"*"),W.call(e,"[s!='']:x"),C.push("!=",se)}),F=F.length&&new RegExp(F.join("|")),C=C.length&&new RegExp(C.join("|")),t=pe.test(A.compareDocumentPosition),N=t||pe.test(A.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},G=t?function(e,t){if(e===t)return H=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n?n:(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1,1&n||!v.sortDetached&&t.compareDocumentPosition(e)===n?e===P||e.ownerDocument===I&&N(I,e)?-1:t===P||t.ownerDocument===I&&N(I,t)?1:j?ee(j,e)-ee(j,t):0:4&n?-1:1)}:function(e,t){if(e===t)return H=!0,0;var n,r=0,a=e.parentNode,s=t.parentNode,o=[e],d=[t];if(!a||!s)return e===P?-1:t===P?1:a?-1:s?1:j?ee(j,e)-ee(j,t):0;if(a===s)return i(e,t);for(n=e;n=n.parentNode;)o.unshift(n);for(n=t;n=n.parentNode;)d.unshift(n);for(;o[r]===d[r];)r++;return r?i(o[r],d[r]):o[r]===I?-1:d[r]===I?1:0},P):P},t.matches=function(e,n){return t(e,null,null,n)},t.matchesSelector=function(e,n){if((e.ownerDocument||e)!==P&&O(e),n=n.replace(le,"='$1']"),v.matchesSelector&&E&&!q[n+" "]&&(!C||!C.test(n))&&(!F||!F.test(n)))try{var r=W.call(e,n);if(r||v.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(a){}return t(n,P,null,[e]).length>0},t.contains=function(e,t){return(e.ownerDocument||e)!==P&&O(e),N(e,t)},t.attr=function(e,t){(e.ownerDocument||e)!==P&&O(e);var n=k.attrHandle[t.toLowerCase()],r=n&&B.call(k.attrHandle,t.toLowerCase())?n(e,t,!E):void 0;return void 0!==r?r:v.attributes||!E?e.getAttribute(t):(r=e.getAttributeNode(t))&&r.specified?r.value:null},t.escape=function(e){return(e+"").replace(Ye,ve)},t.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},t.uniqueSort=function(e){var t,n=[],r=0,a=0;if(H=!v.detectDuplicates,j=!v.sortStable&&e.slice(0),e.sort(G),H){for(;t=e[a++];)t===e[a]&&(r=n.push(a));for(;r--;)e.splice(n[r],1)}return j=null,e},D=t.getText=function(e){var t,n="",r=0,a=e.nodeType;if(a){if(1===a||9===a||11===a){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=D(e)}else if(3===a||4===a)return e.nodeValue}else for(;t=e[r++];)n+=D(t);return n},k=t.selectors={cacheLength:50,createPseudo:r,match:me,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(Le,ge),e[3]=(e[3]||e[4]||e[5]||"").replace(Le,ge),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||t.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&t.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return me.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&_e.test(n)&&(t=T(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(Le,ge).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=J[e+" "];return t||(t=new RegExp("(^|"+ne+")"+e+"("+ne+"|$)"))&&J(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(e,n,r){return function(a){var s=t.attr(a,e);return null==s?"!="===n:!n||(s+="","="===n?s===r:"!="===n?s!==r:"^="===n?r&&0===s.indexOf(r):"*="===n?r&&s.indexOf(r)>-1:"$="===n?r&&s.slice(-r.length)===r:"~="===n?(" "+s.replace(ie," ")+" ").indexOf(r)>-1:"|="===n&&(s===r||s.slice(0,r.length+1)===r+"-"))}},CHILD:function(e,t,n,r,a){var s="nth"!==e.slice(0,3),i="last"!==e.slice(-4),o="of-type"===t;return 1===r&&0===a?function(e){return!!e.parentNode}:function(t,n,d){var u,l,_,c,m,f,h=s!==i?"nextSibling":"previousSibling",p=t.parentNode,y=o&&t.nodeName.toLowerCase(),M=!d&&!o,L=!1;if(p){if(s){for(;h;){for(c=t;c=c[h];)if(o?c.nodeName.toLowerCase()===y:1===c.nodeType)return!1;f=h="only"===e&&!f&&"nextSibling"}return!0}if(f=[i?p.firstChild:p.lastChild],i&&M){for(c=p,_=c[$]||(c[$]={}),l=_[c.uniqueID]||(_[c.uniqueID]={}),u=l[e]||[],m=u[0]===z&&u[1],L=m&&u[2],c=m&&p.childNodes[m];c=++m&&c&&c[h]||(L=m=0)||f.pop();)if(1===c.nodeType&&++L&&c===t){l[e]=[z,m,L];break}}else if(M&&(c=t,_=c[$]||(c[$]={}),l=_[c.uniqueID]||(_[c.uniqueID]={}),u=l[e]||[],m=u[0]===z&&u[1],L=m),L===!1)for(;(c=++m&&c&&c[h]||(L=m=0)||f.pop())&&((o?c.nodeName.toLowerCase()!==y:1!==c.nodeType)||!++L||(M&&(_=c[$]||(c[$]={}),l=_[c.uniqueID]||(_[c.uniqueID]={}),l[e]=[z,L]),c!==t)););return L-=a,L===r||L%r===0&&L/r>=0}}},PSEUDO:function(e,n){var a,s=k.pseudos[e]||k.setFilters[e.toLowerCase()]||t.error("unsupported pseudo: "+e);return s[$]?s(n):s.length>1?(a=[e,e,"",n],k.setFilters.hasOwnProperty(e.toLowerCase())?r(function(e,t){for(var r,a=s(e,n),i=a.length;i--;)r=ee(e,a[i]),e[r]=!(t[r]=a[i])}):function(e){return s(e,0,a)}):s}},pseudos:{not:r(function(e){var t=[],n=[],a=b(e.replace(oe,"$1"));return a[$]?r(function(e,t,n,r){for(var s,i=a(e,null,r,[]),o=e.length;o--;)(s=i[o])&&(e[o]=!(t[o]=s))}):function(e,r,s){return t[0]=e,a(t,null,s,n),t[0]=null,!n.pop()}}),has:r(function(e){return function(n){return t(e,n).length>0}}),contains:r(function(e){return e=e.replace(Le,ge),function(t){return(t.textContent||t.innerText||D(t)).indexOf(e)>-1}}),lang:r(function(e){return ce.test(e||"")||t.error("unsupported lang: "+e),e=e.replace(Le,ge).toLowerCase(),function(t){var n;do if(n=E?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===A},focus:function(e){return e===P.activeElement&&(!P.hasFocus||P.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:u(!1),disabled:u(!0),checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!k.pseudos.empty(e)},header:function(e){return he.test(e.nodeName)},input:function(e){return fe.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:l(function(){return[0]}),last:l(function(e,t){return[t-1]}),eq:l(function(e,t,n){return[n<0?n+t:n]}),even:l(function(e,t){for(var n=0;n=0;)e.push(r);return e}),gt:l(function(e,t,n){for(var r=n<0?n+t:n;++r2&&"ID"===(i=s[0]).type&&9===t.nodeType&&E&&k.relative[s[1].type]){if(t=(k.find.ID(i.matches[0].replace(Le,ge),t)||[])[0],!t)return n;u&&(t=t.parentNode),e=e.slice(s.shift().value.length)}for(a=me.needsContext.test(e)?0:s.length;a--&&(i=s[a],!k.relative[o=i.type]);)if((d=k.find[o])&&(r=d(i.matches[0].replace(Le,ge),Me.test(s[0].type)&&_(t.parentNode)||t))){if(s.splice(a,1),e=r.length&&m(s),!e)return Q.apply(n,r),n;break}}return(u||b(e,l))(r,t,!E,n,!t||Me.test(e)&&_(t.parentNode)||t),n},v.sortStable=$.split("").sort(G).join("")===$,v.detectDuplicates=!!H,O(),v.sortDetached=a(function(e){return 1&e.compareDocumentPosition(P.createElement("fieldset"))}),a(function(e){return e.innerHTML="","#"===e.firstChild.getAttribute("href")})||s("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),v.attributes&&a(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||s("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),a(function(e){return null==e.getAttribute("disabled")})||s(te,function(e,t,n){var r;if(!n)return e[t]===!0?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),t}(n);Le.find=De,Le.expr=De.selectors,Le.expr[":"]=Le.expr.pseudos,Le.uniqueSort=Le.unique=De.uniqueSort,Le.text=De.getText,Le.isXMLDoc=De.isXML,Le.contains=De.contains,Le.escapeSelector=De.escape;var we=function(e,t,n){for(var r=[],a=void 0!==n;(e=e[t])&&9!==e.nodeType;)if(1===e.nodeType){if(a&&Le(e).is(n))break;r.push(e)}return r},Te=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},be=Le.expr.match.needsContext,Se=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i,xe=/^.[^:#\[\.,]*$/;Le.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?Le.find.matchesSelector(r,e)?[r]:[]:Le.find.matches(e,Le.grep(t,function(e){return 1===e.nodeType}))},Le.fn.extend({find:function(e){var t,n,r=this.length,a=this;if("string"!=typeof e)return this.pushStack(Le(e).filter(function(){for(t=0;t1?Le.uniqueSort(n):n},filter:function(e){return this.pushStack(u(this,e||[],!1))},not:function(e){return this.pushStack(u(this,e||[],!0))},is:function(e){return!!u(this,"string"==typeof e&&be.test(e)?Le(e):e||[],!1).length}});var je,He=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,Oe=Le.fn.init=function(e,t,n){var r,a;if(!e)return this;if(n=n||je,"string"==typeof e){if(r="<"===e[0]&&">"===e[e.length-1]&&e.length>=3?[null,e,null]:He.exec(e),!r||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof Le?t[0]:t,Le.merge(this,Le.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:ie,!0)),Se.test(r[1])&&Le.isPlainObject(t))for(r in t)Le.isFunction(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return a=ie.getElementById(r[2]),a&&(this[0]=a,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):Le.isFunction(e)?void 0!==n.ready?n.ready(e):e(Le):Le.makeArray(e,this)};Oe.prototype=Le.fn,je=Le(ie);var Pe=/^(?:parents|prev(?:Until|All))/,Ae={children:!0,contents:!0,next:!0,prev:!0};Le.fn.extend({has:function(e){var t=Le(e,this),n=t.length;return this.filter(function(){for(var e=0;e-1:1===n.nodeType&&Le.find.matchesSelector(n,e))){s.push(n);break}return this.pushStack(s.length>1?Le.uniqueSort(s):s)},index:function(e){return e?"string"==typeof e?_e.call(Le(e),this[0]):_e.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(Le.uniqueSort(Le.merge(this.get(),Le(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),Le.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return we(e,"parentNode")},parentsUntil:function(e,t,n){return we(e,"parentNode",n)},next:function(e){return l(e,"nextSibling")},prev:function(e){return l(e,"previousSibling")},nextAll:function(e){return we(e,"nextSibling")},prevAll:function(e){return we(e,"previousSibling")},nextUntil:function(e,t,n){return we(e,"nextSibling",n)},prevUntil:function(e,t,n){return we(e,"previousSibling",n)},siblings:function(e){return Te((e.parentNode||{}).firstChild,e)},children:function(e){return Te(e.firstChild)},contents:function(e){return d(e,"iframe")?e.contentDocument:(d(e,"template")&&(e=e.content||e),Le.merge([],e.childNodes))}},function(e,t){Le.fn[e]=function(n,r){var a=Le.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(a=Le.filter(r,a)),this.length>1&&(Ae[e]||Le.uniqueSort(a),Pe.test(e)&&a.reverse()),this.pushStack(a)}});var Ee=/[^\x20\t\r\n\f]+/g;Le.Callbacks=function(e){e="string"==typeof e?_(e):Le.extend({},e);var t,n,r,a,s=[],i=[],o=-1,d=function(){for(a=a||e.once,r=t=!0;i.length;o=-1)for(n=i.shift();++o-1;)s.splice(n,1),n<=o&&o--}),this},has:function(e){return e?Le.inArray(e,s)>-1:s.length>0},empty:function(){return s&&(s=[]),this},disable:function(){return a=i=[],s=n="",this},disabled:function(){return!s},lock:function(){return a=i=[],n||t||(s=n=""),this},locked:function(){return!!a},fireWith:function(e,n){return a||(n=n||[],n=[e,n.slice?n.slice():n],i.push(n),t||d()),this},fire:function(){return u.fireWith(this,arguments),this},fired:function(){return!!r}};return u},Le.extend({Deferred:function(e){var t=[["notify","progress",Le.Callbacks("memory"),Le.Callbacks("memory"),2],["resolve","done",Le.Callbacks("once memory"),Le.Callbacks("once memory"),0,"resolved"],["reject","fail",Le.Callbacks("once memory"),Le.Callbacks("once memory"),1,"rejected"]],r="pending",a={state:function(){return r},always:function(){return s.done(arguments).fail(arguments),this},"catch":function(e){return a.then(null,e)},pipe:function(){var e=arguments;return Le.Deferred(function(n){Le.each(t,function(t,r){var a=Le.isFunction(e[r[4]])&&e[r[4]];s[r[1]](function(){var e=a&&a.apply(this,arguments);e&&Le.isFunction(e.promise)?e.promise().progress(n.notify).done(n.resolve).fail(n.reject):n[r[0]+"With"](this,a?[e]:arguments)})}),e=null}).promise()},then:function(e,r,a){function s(e,t,r,a){return function(){var o=this,d=arguments,u=function(){var n,u;if(!(e=i&&(r!==m&&(o=void 0,d=[n]),t.rejectWith(o,d))}};e?l():(Le.Deferred.getStackHook&&(l.stackTrace=Le.Deferred.getStackHook()),n.setTimeout(l))}}var i=0;return Le.Deferred(function(n){t[0][3].add(s(0,n,Le.isFunction(a)?a:c,n.notifyWith)),t[1][3].add(s(0,n,Le.isFunction(e)?e:c)),t[2][3].add(s(0,n,Le.isFunction(r)?r:m))}).promise()},promise:function(e){return null!=e?Le.extend(e,a):a}},s={};return Le.each(t,function(e,n){var i=n[2],o=n[5];a[n[1]]=i.add,o&&i.add(function(){r=o},t[3-e][2].disable,t[0][2].lock),i.add(n[3].fire),s[n[0]]=function(){return s[n[0]+"With"](this===s?void 0:this,arguments),this},s[n[0]+"With"]=i.fireWith}),a.promise(s),e&&e.call(s,s),s},when:function(e){var t=arguments.length,n=t,r=Array(n),a=de.call(arguments),s=Le.Deferred(),i=function(e){return function(n){r[e]=this,a[e]=arguments.length>1?de.call(arguments):n,--t||s.resolveWith(r,a)}};if(t<=1&&(f(e,s.done(i(n)).resolve,s.reject,!t),"pending"===s.state()||Le.isFunction(a[n]&&a[n].then)))return s.then();for(;n--;)f(a[n],i(n),s.reject);return s.promise()}});var Fe=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;Le.Deferred.exceptionHook=function(e,t){n.console&&n.console.warn&&e&&Fe.test(e.name)&&n.console.warn("jQuery.Deferred exception: "+e.message,e.stack,t)},Le.readyException=function(e){n.setTimeout(function(){throw e})};var Ce=Le.Deferred();Le.fn.ready=function(e){return Ce.then(e)["catch"](function(e){Le.readyException(e)}),this},Le.extend({isReady:!1,readyWait:1,ready:function(e){(e===!0?--Le.readyWait:Le.isReady)||(Le.isReady=!0,e!==!0&&--Le.readyWait>0||Ce.resolveWith(ie,[Le]))}}),Le.ready.then=Ce.then,"complete"===ie.readyState||"loading"!==ie.readyState&&!ie.documentElement.doScroll?n.setTimeout(Le.ready):(ie.addEventListener("DOMContentLoaded",h),n.addEventListener("load",h));var We=function(e,t,n,r,a,s,i){var o=0,d=e.length,u=null==n;if("object"===Le.type(n)){a=!0;for(o in n)We(e,t,o,n[o],!0,s,i)}else if(void 0!==r&&(a=!0,Le.isFunction(r)||(i=!0),u&&(i?(t.call(e,r),t=null):(u=t,t=function(e,t,n){return u.call(Le(e),n)})),t))for(;o1,null,!0)},removeData:function(e){return this.each(function(){Ie.remove(this,e)})}}),Le.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=$e.get(e,t),n&&(!r||Array.isArray(n)?r=$e.access(e,t,Le.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=Le.queue(e,t),r=n.length,a=n.shift(),s=Le._queueHooks(e,t),i=function(){Le.dequeue(e,t)};"inprogress"===a&&(a=n.shift(),r--),a&&("fx"===t&&n.unshift("inprogress"),delete s.stop,a.call(e,i,s)),!r&&s&&s.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return $e.get(e,n)||$e.access(e,n,{empty:Le.Callbacks("once memory").add(function(){$e.remove(e,[t+"queue",n])})})}}),Le.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),arguments.length\x20\t\r\n\f]+)/i,Qe=/^$|\/(?:java|ecma)script/i,Xe={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};Xe.optgroup=Xe.option,Xe.tbody=Xe.tfoot=Xe.colgroup=Xe.caption=Xe.thead, +Xe.th=Xe.td;var et=/<|&#?\w+;/;!function(){var e=ie.createDocumentFragment(),t=e.appendChild(ie.createElement("div")),n=ie.createElement("input");n.setAttribute("type","radio"),n.setAttribute("checked","checked"),n.setAttribute("name","t"),t.appendChild(n),ye.checkClone=t.cloneNode(!0).cloneNode(!0).lastChild.checked,t.innerHTML="",ye.noCloneChecked=!!t.cloneNode(!0).lastChild.defaultValue}();var tt=ie.documentElement,nt=/^key/,rt=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,at=/^([^.]*)(?:\.(.+)|)/;Le.event={global:{},add:function(e,t,n,r,a){var s,i,o,d,u,l,_,c,m,f,h,p=$e.get(e);if(p)for(n.handler&&(s=n,n=s.handler,a=s.selector),a&&Le.find.matchesSelector(tt,a),n.guid||(n.guid=Le.guid++),(d=p.events)||(d=p.events={}),(i=p.handle)||(i=p.handle=function(t){return"undefined"!=typeof Le&&Le.event.triggered!==t.type?Le.event.dispatch.apply(e,arguments):void 0}),t=(t||"").match(Ee)||[""],u=t.length;u--;)o=at.exec(t[u])||[],m=h=o[1],f=(o[2]||"").split(".").sort(),m&&(_=Le.event.special[m]||{},m=(a?_.delegateType:_.bindType)||m,_=Le.event.special[m]||{},l=Le.extend({type:m,origType:h,data:r,handler:n,guid:n.guid,selector:a,needsContext:a&&Le.expr.match.needsContext.test(a),namespace:f.join(".")},s),(c=d[m])||(c=d[m]=[],c.delegateCount=0,_.setup&&_.setup.call(e,r,f,i)!==!1||e.addEventListener&&e.addEventListener(m,i)),_.add&&(_.add.call(e,l),l.handler.guid||(l.handler.guid=n.guid)),a?c.splice(c.delegateCount++,0,l):c.push(l),Le.event.global[m]=!0)},remove:function(e,t,n,r,a){var s,i,o,d,u,l,_,c,m,f,h,p=$e.hasData(e)&&$e.get(e);if(p&&(d=p.events)){for(t=(t||"").match(Ee)||[""],u=t.length;u--;)if(o=at.exec(t[u])||[],m=h=o[1],f=(o[2]||"").split(".").sort(),m){for(_=Le.event.special[m]||{},m=(r?_.delegateType:_.bindType)||m,c=d[m]||[],o=o[2]&&new RegExp("(^|\\.)"+f.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=s=c.length;s--;)l=c[s],!a&&h!==l.origType||n&&n.guid!==l.guid||o&&!o.test(l.namespace)||r&&r!==l.selector&&("**"!==r||!l.selector)||(c.splice(s,1),l.selector&&c.delegateCount--,_.remove&&_.remove.call(e,l));i&&!c.length&&(_.teardown&&_.teardown.call(e,f,p.handle)!==!1||Le.removeEvent(e,m,p.handle),delete d[m])}else for(m in d)Le.event.remove(e,m+t[u],n,r,!0);Le.isEmptyObject(d)&&$e.remove(e,"handle events")}},dispatch:function(e){var t,n,r,a,s,i,o=Le.event.fix(e),d=new Array(arguments.length),u=($e.get(this,"events")||{})[o.type]||[],l=Le.event.special[o.type]||{};for(d[0]=o,t=1;t=1))for(;u!==this;u=u.parentNode||this)if(1===u.nodeType&&("click"!==e.type||u.disabled!==!0)){for(s=[],i={},n=0;n-1:Le.find(a,this,null,[u]).length),i[a]&&s.push(r);s.length&&o.push({elem:u,handlers:s})}return u=this,d\x20\t\r\n\f]*)[^>]*)\/>/gi,it=/\s*$/g;Le.extend({htmlPrefilter:function(e){return e.replace(st,"<$1>")},clone:function(e,t,n){var r,a,s,i,o=e.cloneNode(!0),d=Le.contains(e.ownerDocument,e);if(!(ye.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||Le.isXMLDoc(e)))for(i=v(o),s=v(e),r=0,a=s.length;r0&&k(i,!d&&v(e,"script")),o},cleanData:function(e){for(var t,n,r,a=Le.event.special,s=0;void 0!==(n=e[s]);s++)if(Ne(n)){if(t=n[$e.expando]){if(t.events)for(r in t.events)a[r]?Le.event.remove(n,r):Le.removeEvent(n,r,t.handle);n[$e.expando]=void 0}n[Ie.expando]&&(n[Ie.expando]=void 0)}}}),Le.fn.extend({detach:function(e){return E(this,e,!0)},remove:function(e){return E(this,e)},text:function(e){return We(this,function(e){return void 0===e?Le.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return A(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=x(this,e);t.appendChild(e)}})},prepend:function(){return A(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=x(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return A(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return A(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(Le.cleanData(v(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return Le.clone(this,e,t)})},html:function(e){return We(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!it.test(e)&&!Xe[(Ke.exec(e)||["",""])[1].toLowerCase()]){e=Le.htmlPrefilter(e);try{for(;n1)}}),Le.Tween=R,R.prototype={constructor:R,init:function(e,t,n,r,a,s){this.elem=e,this.prop=n,this.easing=a||Le.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=s||(Le.cssNumber[n]?"":"px")},cur:function(){var e=R.propHooks[this.prop];return e&&e.get?e.get(this):R.propHooks._default.get(this)},run:function(e){var t,n=R.propHooks[this.prop];return this.options.duration?this.pos=t=Le.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):R.propHooks._default.set(this),this}},R.prototype.init.prototype=R.prototype,R.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=Le.css(e.elem,e.prop,""),t&&"auto"!==t?t:0)},set:function(e){Le.fx.step[e.prop]?Le.fx.step[e.prop](e):1!==e.elem.nodeType||null==e.elem.style[Le.cssProps[e.prop]]&&!Le.cssHooks[e.prop]?e.elem[e.prop]=e.now:Le.style(e.elem,e.prop,e.now+e.unit)}}},R.propHooks.scrollTop=R.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},Le.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},Le.fx=R.prototype.init,Le.fx.step={};var Lt,gt,Yt=/^(?:toggle|show|hide)$/,vt=/queueHooks$/;Le.Animation=Le.extend(Z,{tweeners:{"*":[function(e,t){var n=this.createTween(e,t);return L(n.elem,e,Ue.exec(t),n),n}]},tweener:function(e,t){Le.isFunction(e)?(t=e,e=["*"]):e=e.match(Ee);for(var n,r=0,a=e.length;r1)},removeAttr:function(e){return this.each(function(){Le.removeAttr(this,e)})}}),Le.extend({attr:function(e,t,n){var r,a,s=e.nodeType;if(3!==s&&8!==s&&2!==s)return"undefined"==typeof e.getAttribute?Le.prop(e,t,n):(1===s&&Le.isXMLDoc(e)||(a=Le.attrHooks[t.toLowerCase()]||(Le.expr.match.bool.test(t)?kt:void 0)),void 0!==n?null===n?void Le.removeAttr(e,t):a&&"set"in a&&void 0!==(r=a.set(e,n,t))?r:(e.setAttribute(t,n+""),n):a&&"get"in a&&null!==(r=a.get(e,t))?r:(r=Le.find.attr(e,t),null==r?void 0:r))},attrHooks:{type:{set:function(e,t){if(!ye.radioValue&&"radio"===t&&d(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,a=t&&t.match(Ee);if(a&&1===e.nodeType)for(;n=a[r++];)e.removeAttribute(n)}}),kt={set:function(e,t,n){return t===!1?Le.removeAttr(e,n):e.setAttribute(n,n),n}},Le.each(Le.expr.match.bool.source.match(/\w+/g),function(e,t){var n=Dt[t]||Le.find.attr;Dt[t]=function(e,t,r){var a,s,i=t.toLowerCase();return r||(s=Dt[i],Dt[i]=a,a=null!=n(e,t,r)?i:null,Dt[i]=s),a}});var wt=/^(?:input|select|textarea|button)$/i,Tt=/^(?:a|area)$/i;Le.fn.extend({prop:function(e,t){return We(this,Le.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[Le.propFix[e]||e]})}}),Le.extend({prop:function(e,t,n){var r,a,s=e.nodeType;if(3!==s&&8!==s&&2!==s)return 1===s&&Le.isXMLDoc(e)||(t=Le.propFix[t]||t,a=Le.propHooks[t]),void 0!==n?a&&"set"in a&&void 0!==(r=a.set(e,n,t))?r:e[t]=n:a&&"get"in a&&null!==(r=a.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=Le.find.attr(e,"tabindex");return t?parseInt(t,10):wt.test(e.nodeName)||Tt.test(e.nodeName)&&e.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),ye.optSelected||(Le.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),Le.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){Le.propFix[this.toLowerCase()]=this}),Le.fn.extend({addClass:function(e){var t,n,r,a,s,i,o,d=0;if(Le.isFunction(e))return this.each(function(t){Le(this).addClass(e.call(this,t,Q(this)))});if("string"==typeof e&&e)for(t=e.match(Ee)||[];n=this[d++];)if(a=Q(n),r=1===n.nodeType&&" "+K(a)+" "){for(i=0;s=t[i++];)r.indexOf(" "+s+" ")<0&&(r+=s+" ");o=K(r),a!==o&&n.setAttribute("class",o)}return this},removeClass:function(e){var t,n,r,a,s,i,o,d=0;if(Le.isFunction(e))return this.each(function(t){Le(this).removeClass(e.call(this,t,Q(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof e&&e)for(t=e.match(Ee)||[];n=this[d++];)if(a=Q(n),r=1===n.nodeType&&" "+K(a)+" "){for(i=0;s=t[i++];)for(;r.indexOf(" "+s+" ")>-1;)r=r.replace(" "+s+" "," ");o=K(r),a!==o&&n.setAttribute("class",o)}return this},toggleClass:function(e,t){var n=typeof e;return"boolean"==typeof t&&"string"===n?t?this.addClass(e):this.removeClass(e):Le.isFunction(e)?this.each(function(n){Le(this).toggleClass(e.call(this,n,Q(this),t),t)}):this.each(function(){var t,r,a,s;if("string"===n)for(r=0,a=Le(this),s=e.match(Ee)||[];t=s[r++];)a.hasClass(t)?a.removeClass(t):a.addClass(t);else void 0!==e&&"boolean"!==n||(t=Q(this),t&&$e.set(this,"__className__",t),this.setAttribute&&this.setAttribute("class",t||e===!1?"":$e.get(this,"__className__")||""))})},hasClass:function(e){var t,n,r=0;for(t=" "+e+" ";n=this[r++];)if(1===n.nodeType&&(" "+K(Q(n))+" ").indexOf(t)>-1)return!0;return!1}});var bt=/\r/g;Le.fn.extend({val:function(e){var t,n,r,a=this[0];{if(arguments.length)return r=Le.isFunction(e),this.each(function(n){var a;1===this.nodeType&&(a=r?e.call(this,n,Le(this).val()):e,null==a?a="":"number"==typeof a?a+="":Array.isArray(a)&&(a=Le.map(a,function(e){return null==e?"":e+""})),t=Le.valHooks[this.type]||Le.valHooks[this.nodeName.toLowerCase()],t&&"set"in t&&void 0!==t.set(this,a,"value")||(this.value=a))});if(a)return t=Le.valHooks[a.type]||Le.valHooks[a.nodeName.toLowerCase()],t&&"get"in t&&void 0!==(n=t.get(a,"value"))?n:(n=a.value,"string"==typeof n?n.replace(bt,""):null==n?"":n)}}}),Le.extend({valHooks:{option:{get:function(e){var t=Le.find.attr(e,"value");return null!=t?t:K(Le.text(e))}},select:{get:function(e){var t,n,r,a=e.options,s=e.selectedIndex,i="select-one"===e.type,o=i?null:[],u=i?s+1:a.length;for(r=s<0?u:i?s:0;r-1)&&(n=!0);return n||(e.selectedIndex=-1),s}}}}),Le.each(["radio","checkbox"],function(){Le.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=Le.inArray(Le(e).val(),t)>-1}},ye.checkOn||(Le.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var St=/^(?:focusinfocus|focusoutblur)$/;Le.extend(Le.event,{trigger:function(e,t,r,a){var s,i,o,d,u,l,_,c=[r||ie],m=fe.call(e,"type")?e.type:e,f=fe.call(e,"namespace")?e.namespace.split("."):[];if(i=o=r=r||ie,3!==r.nodeType&&8!==r.nodeType&&!St.test(m+Le.event.triggered)&&(m.indexOf(".")>-1&&(f=m.split("."),m=f.shift(),f.sort()),u=m.indexOf(":")<0&&"on"+m,e=e[Le.expando]?e:new Le.Event(m,"object"==typeof e&&e),e.isTrigger=a?2:3,e.namespace=f.join("."),e.rnamespace=e.namespace?new RegExp("(^|\\.)"+f.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,e.result=void 0,e.target||(e.target=r),t=null==t?[e]:Le.makeArray(t,[e]),_=Le.event.special[m]||{},a||!_.trigger||_.trigger.apply(r,t)!==!1)){if(!a&&!_.noBubble&&!Le.isWindow(r)){for(d=_.delegateType||m,St.test(d+m)||(i=i.parentNode);i;i=i.parentNode)c.push(i),o=i;o===(r.ownerDocument||ie)&&c.push(o.defaultView||o.parentWindow||n)}for(s=0;(i=c[s++])&&!e.isPropagationStopped();)e.type=s>1?d:_.bindType||m,l=($e.get(i,"events")||{})[e.type]&&$e.get(i,"handle"),l&&l.apply(i,t),l=u&&i[u],l&&l.apply&&Ne(i)&&(e.result=l.apply(i,t),e.result===!1&&e.preventDefault());return e.type=m,a||e.isDefaultPrevented()||_._default&&_._default.apply(c.pop(),t)!==!1||!Ne(r)||u&&Le.isFunction(r[m])&&!Le.isWindow(r)&&(o=r[u],o&&(r[u]=null),Le.event.triggered=m,r[m](),Le.event.triggered=void 0,o&&(r[u]=o)),e.result}},simulate:function(e,t,n){var r=Le.extend(new Le.Event,n,{type:e,isSimulated:!0});Le.event.trigger(r,null,t)}}),Le.fn.extend({trigger:function(e,t){return this.each(function(){Le.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return Le.event.trigger(e,t,n,!0)}}),Le.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,t){Le.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),Le.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),ye.focusin="onfocusin"in n,ye.focusin||Le.each({focus:"focusin",blur:"focusout"},function(e,t){var n=function(e){Le.event.simulate(t,e.target,Le.event.fix(e))};Le.event.special[t]={setup:function(){var r=this.ownerDocument||this,a=$e.access(r,t);a||r.addEventListener(e,n,!0),$e.access(r,t,(a||0)+1)},teardown:function(){var r=this.ownerDocument||this,a=$e.access(r,t)-1;a?$e.access(r,t,a):(r.removeEventListener(e,n,!0),$e.remove(r,t))}}});var xt=n.location,jt=Le.now(),Ht=/\?/;Le.parseXML=function(e){var t;if(!e||"string"!=typeof e)return null;try{t=(new n.DOMParser).parseFromString(e,"text/xml")}catch(r){t=void 0}return t&&!t.getElementsByTagName("parsererror").length||Le.error("Invalid XML: "+e),t};var Ot=/\[\]$/,Pt=/\r?\n/g,At=/^(?:submit|button|image|reset|file)$/i,Et=/^(?:input|select|textarea|keygen)/i;Le.param=function(e,t){var n,r=[],a=function(e,t){var n=Le.isFunction(t)?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(Array.isArray(e)||e.jquery&&!Le.isPlainObject(e))Le.each(e,function(){a(this.name,this.value)});else for(n in e)X(n,e[n],t,a);return r.join("&")},Le.fn.extend({serialize:function(){return Le.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=Le.prop(this,"elements");return e?Le.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!Le(this).is(":disabled")&&Et.test(this.nodeName)&&!At.test(e)&&(this.checked||!Ze.test(e))}).map(function(e,t){var n=Le(this).val();return null==n?null:Array.isArray(n)?Le.map(n,function(e){return{name:t.name,value:e.replace(Pt,"\r\n")}}):{name:t.name,value:n.replace(Pt,"\r\n")}}).get()}});var Ft=/%20/g,Ct=/#.*$/,Wt=/([?&])_=[^&]*/,Nt=/^(.*?):[ \t]*([^\r\n]*)$/gm,$t=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,It=/^(?:GET|HEAD)$/,zt=/^\/\//,Rt={},Jt={},Ut="*/".concat("*"),qt=ie.createElement("a");qt.href=xt.href,Le.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:xt.href,type:"GET",isLocal:$t.test(xt.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Ut,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":Le.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?ne(ne(e,Le.ajaxSettings),t):ne(Le.ajaxSettings,e)},ajaxPrefilter:ee(Rt),ajaxTransport:ee(Jt),ajax:function(e,t){function r(e,t,r,o){var u,c,m,g,Y,v=t;l||(l=!0,d&&n.clearTimeout(d),a=void 0,i=o||"",k.readyState=e>0?4:0,u=e>=200&&e<300||304===e,r&&(g=re(f,k,r)),g=ae(f,g,k,u),u?(f.ifModified&&(Y=k.getResponseHeader("Last-Modified"),Y&&(Le.lastModified[s]=Y),Y=k.getResponseHeader("etag"),Y&&(Le.etag[s]=Y)),204===e||"HEAD"===f.type?v="nocontent":304===e?v="notmodified":(v=g.state,c=g.data,m=g.error,u=!m)):(m=v,!e&&v||(v="error",e<0&&(e=0))),k.status=e,k.statusText=(t||v)+"",u?y.resolveWith(h,[c,v,k]):y.rejectWith(h,[k,v,m]),k.statusCode(L),L=void 0,_&&p.trigger(u?"ajaxSuccess":"ajaxError",[k,f,u?c:m]),M.fireWith(h,[k,v]),_&&(p.trigger("ajaxComplete",[k,f]),--Le.active||Le.event.trigger("ajaxStop")))}"object"==typeof e&&(t=e,e=void 0),t=t||{};var a,s,i,o,d,u,l,_,c,m,f=Le.ajaxSetup({},t),h=f.context||f,p=f.context&&(h.nodeType||h.jquery)?Le(h):Le.event,y=Le.Deferred(),M=Le.Callbacks("once memory"),L=f.statusCode||{},g={},Y={},v="canceled",k={readyState:0,getResponseHeader:function(e){var t;if(l){if(!o)for(o={};t=Nt.exec(i);)o[t[1].toLowerCase()]=t[2];t=o[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return l?i:null},setRequestHeader:function(e,t){return null==l&&(e=Y[e.toLowerCase()]=Y[e.toLowerCase()]||e,g[e]=t),this},overrideMimeType:function(e){return null==l&&(f.mimeType=e),this},statusCode:function(e){var t;if(e)if(l)k.always(e[k.status]);else for(t in e)L[t]=[L[t],e[t]];return this},abort:function(e){var t=e||v;return a&&a.abort(t),r(0,t),this}};if(y.promise(k),f.url=((e||f.url||xt.href)+"").replace(zt,xt.protocol+"//"),f.type=t.method||t.type||f.method||f.type,f.dataTypes=(f.dataType||"*").toLowerCase().match(Ee)||[""],null==f.crossDomain){u=ie.createElement("a");try{u.href=f.url,u.href=u.href,f.crossDomain=qt.protocol+"//"+qt.host!=u.protocol+"//"+u.host}catch(D){f.crossDomain=!0}}if(f.data&&f.processData&&"string"!=typeof f.data&&(f.data=Le.param(f.data,f.traditional)),te(Rt,f,t,k),l)return k;_=Le.event&&f.global,_&&0===Le.active++&&Le.event.trigger("ajaxStart"),f.type=f.type.toUpperCase(),f.hasContent=!It.test(f.type),s=f.url.replace(Ct,""),f.hasContent?f.data&&f.processData&&0===(f.contentType||"").indexOf("application/x-www-form-urlencoded")&&(f.data=f.data.replace(Ft,"+")):(m=f.url.slice(s.length),f.data&&(s+=(Ht.test(s)?"&":"?")+f.data,delete f.data),f.cache===!1&&(s=s.replace(Wt,"$1"),m=(Ht.test(s)?"&":"?")+"_="+jt++ +m),f.url=s+m),f.ifModified&&(Le.lastModified[s]&&k.setRequestHeader("If-Modified-Since",Le.lastModified[s]),Le.etag[s]&&k.setRequestHeader("If-None-Match",Le.etag[s])),(f.data&&f.hasContent&&f.contentType!==!1||t.contentType)&&k.setRequestHeader("Content-Type",f.contentType),k.setRequestHeader("Accept",f.dataTypes[0]&&f.accepts[f.dataTypes[0]]?f.accepts[f.dataTypes[0]]+("*"!==f.dataTypes[0]?", "+Ut+"; q=0.01":""):f.accepts["*"]);for(c in f.headers)k.setRequestHeader(c,f.headers[c]);if(f.beforeSend&&(f.beforeSend.call(h,k,f)===!1||l))return k.abort();if(v="abort",M.add(f.complete),k.done(f.success),k.fail(f.error),a=te(Jt,f,t,k)){if(k.readyState=1,_&&p.trigger("ajaxSend",[k,f]),l)return k;f.async&&f.timeout>0&&(d=n.setTimeout(function(){k.abort("timeout")},f.timeout));try{l=!1,a.send(g,r)}catch(D){if(l)throw D;r(-1,D)}}else r(-1,"No Transport");return k},getJSON:function(e,t,n){return Le.get(e,t,n,"json")},getScript:function(e,t){return Le.get(e,void 0,t,"script")}}),Le.each(["get","post"],function(e,t){Le[t]=function(e,n,r,a){return Le.isFunction(n)&&(a=a||r,r=n,n=void 0),Le.ajax(Le.extend({url:e,type:t,dataType:a,data:n,success:r},Le.isPlainObject(e)&&e))}}),Le._evalUrl=function(e){return Le.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},Le.fn.extend({wrapAll:function(e){var t;return this[0]&&(Le.isFunction(e)&&(e=e.call(this[0])),t=Le(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){for(var e=this;e.firstElementChild;)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(e){return Le.isFunction(e)?this.each(function(t){Le(this).wrapInner(e.call(this,t))}):this.each(function(){var t=Le(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=Le.isFunction(e);return this.each(function(n){Le(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(e){return this.parent(e).not("body").each(function(){Le(this).replaceWith(this.childNodes)}),this}}),Le.expr.pseudos.hidden=function(e){return!Le.expr.pseudos.visible(e)},Le.expr.pseudos.visible=function(e){ +return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},Le.ajaxSettings.xhr=function(){try{return new n.XMLHttpRequest}catch(e){}};var Gt={0:200,1223:204},Bt=Le.ajaxSettings.xhr();ye.cors=!!Bt&&"withCredentials"in Bt,ye.ajax=Bt=!!Bt,Le.ajaxTransport(function(e){var t,r;if(ye.cors||Bt&&!e.crossDomain)return{send:function(a,s){var i,o=e.xhr();if(o.open(e.type,e.url,e.async,e.username,e.password),e.xhrFields)for(i in e.xhrFields)o[i]=e.xhrFields[i];e.mimeType&&o.overrideMimeType&&o.overrideMimeType(e.mimeType),e.crossDomain||a["X-Requested-With"]||(a["X-Requested-With"]="XMLHttpRequest");for(i in a)o.setRequestHeader(i,a[i]);t=function(e){return function(){t&&(t=r=o.onload=o.onerror=o.onabort=o.onreadystatechange=null,"abort"===e?o.abort():"error"===e?"number"!=typeof o.status?s(0,"error"):s(o.status,o.statusText):s(Gt[o.status]||o.status,o.statusText,"text"!==(o.responseType||"text")||"string"!=typeof o.responseText?{binary:o.response}:{text:o.responseText},o.getAllResponseHeaders()))}},o.onload=t(),r=o.onerror=t("error"),void 0!==o.onabort?o.onabort=r:o.onreadystatechange=function(){4===o.readyState&&n.setTimeout(function(){t&&r()})},t=t("abort");try{o.send(e.hasContent&&e.data||null)}catch(d){if(t)throw d}},abort:function(){t&&t()}}}),Le.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),Le.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return Le.globalEval(e),e}}}),Le.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),Le.ajaxTransport("script",function(e){if(e.crossDomain){var t,n;return{send:function(r,a){t=Le(" - + \ No newline at end of file diff --git a/package.json b/package.json index 626a572..7e40093 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,13 @@ { "name": "youlikeapp", - "version": "1.0.1", + "version": "1.1.0", "repository": { "type": "git", "url": "https://github.com/youlikeapp/youlikeapp.github.io" }, "scripts": { "build": "rimraf dist && webpack --bail --progress --profile --NODE_ENV=production", - "server": "webpack-dev-server --history-api-fallback --inline --hot --progress --NODE_ENV=dev", + "server": "webpack-dev-server --https --history-api-fallback --inline --hot --progress --NODE_ENV=dev", "start": "npm run server" }, "devDependencies": { @@ -17,6 +17,7 @@ "@types/angular-cookies": "1.4.2", "@types/angular-material": "1.1.39", "@types/angular-resource": "1.5.6", + "@types/cross-storage": "^0.8.29", "@types/es6-promise": "0.0.32", "@types/gapi.auth2": "0.0.46", "@types/gapi.client.youtube": "^3.0.0", @@ -59,6 +60,7 @@ "angular-sanitize": "1.5.8", "angular-socialshare": "^2.3.11", "angular-ui-router": "1.0.0-beta.3", + "cross-storage": "^1.0.0", "moment": "^2.20.1", "query-string": "^5.0.1", "toastr": "^2.1.4", diff --git a/src/app/components/main/index.ts b/src/app/components/main/index.ts index bfcef8d..43b1a94 100644 --- a/src/app/components/main/index.ts +++ b/src/app/components/main/index.ts @@ -1,4 +1,5 @@ import * as angular from "angular"; +import { CrossStorageHub, CrossStorageClient } from "cross-storage"; import { State, StateProvider, Ng1StateDeclaration } from "angular-ui-router"; import { MainComponent } from "./main.component"; import { NavService, NavItem } from "./../../common/nav/nav.service"; @@ -21,8 +22,14 @@ function runConfig(NavService: NavService): void { label: "Восстановление", icon: "thumb_up" }; - NavService.addNavItem(page); + NavService.addNavItem(page); + CrossStorageHub.init([ + { + origin: /.*/, + allow: [ "get", "set", "del" ] + } + ]); } const Main: ng.IModule = angular diff --git a/src/app/components/main/main.component.ts b/src/app/components/main/main.component.ts index 57a1e6b..09dd20e 100644 --- a/src/app/components/main/main.component.ts +++ b/src/app/components/main/main.component.ts @@ -99,7 +99,7 @@ class MainController implements ng.IComponentController { } public saveList(): void { - localStorage.videosList = this.videosList; + localStorage.videosList = JSON.stringify(this.videosList.split("\n")); toastr.success("Список видео сохранён."); } @@ -119,7 +119,7 @@ class MainController implements ng.IComponentController { } public loadList(): void { - this.videosList = localStorage.videosList; + this.videosList = (JSON.parse(localStorage.videosList)).join("\n"); this.videosListIsEmpty = false; } diff --git a/vendor.d6ee7810cac7e6943ab8.js b/vendor.d6ee7810cac7e6943ab8.js new file mode 100644 index 0000000..1e59d72 --- /dev/null +++ b/vendor.d6ee7810cac7e6943ab8.js @@ -0,0 +1,62 @@ +!function(e){function t(n){if(r[n])return r[n].exports;var i=r[n]={exports:{},id:n,loaded:!1};return e[n].call(i.exports,i,i.exports,t),i.loaded=!0,i.exports}var n=window.webpackJsonp;window.webpackJsonp=function(o,a){for(var s,c,l=0,u=[];l=0&&(t-1 in e||e instanceof Array)||"function"==typeof e.item)}function r(e,t,i){var o,a;if(e)if(x(e))for(o in e)"prototype"==o||"length"==o||"name"==o||e.hasOwnProperty&&!e.hasOwnProperty(o)||t.call(i,e[o],o,e);else if(Gr(e)||n(e)){var s="object"!=typeof e;for(o=0,a=e.length;o=0&&e.splice(n,1),n}function L(e,t){function n(e,t){var n,r=t.$$hashKey;if(Gr(e))for(var o=0,a=e.length;o2?V(arguments,2):[];return!x(t)||t instanceof RegExp?t:n.length?function(){return arguments.length?t.apply(e,U(n,arguments,0)):t.apply(e,n)}:function(){return arguments.length?t.apply(e,arguments):t.call(e)}}function B(t,n){var r=n;return"string"==typeof t&&"$"===t.charAt(0)&&"$"===t.charAt(1)?r=void 0:M(n)?r="$WINDOW":n&&e.document===n?r="$DOCUMENT":A(n)&&(r="$SCOPE"),r}function z(e,t){if(!v(e))return C(t)||(t=t?2:null),JSON.stringify(e,B,t)}function W(e){return E(e)?JSON.parse(e):e}function Y(e,t){e=e.replace(ti,"");var n=Date.parse("Jan 01, 1970 00:00:00 "+e)/6e4;return isNaN(n)?t:n}function K(e,t){return e=new Date(e.getTime()),e.setMinutes(e.getMinutes()+t),e}function G(e,t,n){n=n?-1:1;var r=e.getTimezoneOffset(),i=Y(t,r);return K(e,n*(i-r))}function Q(e){e=Fr(e).clone();try{e.empty()}catch(t){}var n=Fr("
").append(e).html();try{return e[0].nodeType===si?Ir(n):n.match(/^(<[^>]+>)/)[1].replace(/^<([\w\-]+)/,function(e,t){return"<"+Ir(t)})}catch(t){return Ir(n)}}function X(e){try{return decodeURIComponent(e)}catch(t){}}function Z(e){var t={};return r((e||"").split("&"),function(e){var n,r,i;e&&(r=e=e.replace(/\+/g,"%20"),n=e.indexOf("="),n!==-1&&(r=e.substring(0,n),i=e.substring(n+1)),r=X(r),b(r)&&(i=!b(i)||X(i),Dr.call(t,r)?Gr(t[r])?t[r].push(i):t[r]=[t[r],i]:t[r]=i))}),t}function J(e){var t=[];return r(e,function(e,n){Gr(e)?r(e,function(e){t.push(te(n,!0)+(e===!0?"":"="+te(e,!0)))}):t.push(te(n,!0)+(e===!0?"":"="+te(e,!0)))}),t.length?t.join("&"):""}function ee(e){return te(e,!0).replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+")}function te(e,t){return encodeURIComponent(e).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%3B/gi,";").replace(/%20/g,t?"%20":"+")}function ne(e,t){var n,r,i=ni.length;for(r=0;r/,">"))}n=n||[],n.unshift(["$provide",function(e){e.value("$rootElement",t)}]),i.debugInfoEnabled&&n.push(["$compileProvider",function(e){e.debugInfoEnabled(!0)}]),n.unshift("ng");var o=rt(n,i.strictDi);return o.invoke(["$rootScope","$rootElement","$compile","$injector",function(e,t,n,r){e.$apply(function(){t.data("$injector",r),n(t)(e)})}]),o},s=/^NG_ENABLE_DEBUG_INFO!/,c=/^NG_DEFER_BOOTSTRAP!/;return e&&s.test(e.name)&&(i.debugInfoEnabled=!0,e.name=e.name.replace(s,"")),e&&!c.test(e.name)?a():(e.name=e.name.replace(c,""),Yr.resumeBootstrap=function(e){return r(e,function(e){n.push(e)}),a()},void(x(Yr.resumeDeferredBootstrap)&&Yr.resumeDeferredBootstrap()))}function oe(){e.name="NG_ENABLE_DEBUG_INFO!"+e.name,e.location.reload()}function ae(e){var t=Yr.element(e).injector();if(!t)throw Wr("test","no injector found for element argument to getTestability");return t.get("$$testability")}function se(e,t){return t=t||"_",e.replace(ri,function(e,n){return(n?t:"")+e.toLowerCase()})}function ce(){var t;if(!ii){var n=ei();Lr=v(n)?e.jQuery:n?e[n]:void 0,Lr&&Lr.fn.on?(Fr=Lr,l(Lr.fn,{scope:Mi.scope,isolateScope:Mi.isolateScope,controller:Mi.controller,injector:Mi.injector,inheritedData:Mi.inheritedData}),t=Lr.cleanData,Lr.cleanData=function(e){for(var n,r,i=0;null!=(r=e[i]);i++)n=Lr._data(r,"events"),n&&n.$destroy&&Lr(r).triggerHandler("$destroy");t(e)}):Fr=Se,Yr.element=Fr,ii=!0}}function le(e,t,n){if(!e)throw Wr("areq","Argument '{0}' is {1}",t||"?",n||"required");return e}function ue(e,t,n){return n&&Gr(e)&&(e=e[e.length-1]),le(x(e),t,"not a function, got "+(e&&"object"==typeof e?e.constructor.name||"Object":typeof e)),e}function de(e,t){if("hasOwnProperty"===e)throw Wr("badname","hasOwnProperty is not a valid {0} name",t)}function me(e,t,n){if(!t)return e;for(var r,i=t.split("."),o=e,a=i.length,s=0;s=0)return"...";t.push(n)}return n})}function be(e){return"function"==typeof e?e.toString().replace(/ \{[\s\S]*$/,""):v(e)?"undefined":"string"!=typeof e?ve(e):e}function $e(n){l(n,{bootstrap:ie,copy:L,extend:l,merge:u,equals:j,element:Fr,forEach:r,injector:rt,noop:f,bind:q,toJson:z,fromJson:W,identity:h,isUndefined:v,isDefined:b,isString:E,isFunction:x,isObject:$,isNumber:C,isElement:R,isArray:Gr,version:di,isDate:w,lowercase:Ir,uppercase:Or,callbacks:{$$counter:0},getTestability:ae,$$minErr:t,$$csp:Jr,reloadWithDebugInfo:oe}),(jr=pe(e))("ng",["ngLocale"],["$provide",function(e){e.provider({$$sanitizeUri:kn}),e.provider("$compile",ht).directive({a:Ro,input:ea,textarea:ea,form:jo,script:Ga,select:Za,style:es,option:Ja,ngBind:ra,ngBindHtml:oa,ngBindTemplate:ia,ngClass:sa,ngClassEven:la,ngClassOdd:ca,ngCloak:ua,ngController:da,ngForm:Uo,ngHide:Va,ngIf:ha,ngInclude:pa,ngInit:va,ngNonBindable:Ia,ngPluralize:Pa,ngRepeat:Fa,ngShow:Ua,ngStyle:qa,ngSwitch:Ba,ngSwitchWhen:za,ngSwitchDefault:Wa,ngOptions:Ha,ngTransclude:Ka,ngModel:_a,ngList:ba,ngChange:aa,pattern:ns,ngPattern:ns,required:ts,ngRequired:ts,minlength:is,ngMinlength:is,maxlength:rs,ngMaxlength:rs,ngValue:na,ngModelOptions:Da}).directive({ngInclude:ga}).directive(Ho).directive(ma),e.provider({$anchorScroll:it,$animate:Vi,$animateCss:zi,$$animateJs:ji,$$animateQueue:Ui,$$AnimateRunner:Bi,$$animateAsyncRun:qi,$browser:ut,$cacheFactory:dt,$controller:yt,$document:Et,$exceptionHandler:Ct,$filter:Ln,$$forceReflow:Xi,$interpolate:Ht,$interval:Pt,$http:Dt,$httpParamSerializer:xt,$httpParamSerializerJQLike:kt,$httpBackend:Ot,$xhrFactory:It,$jsonpCallbacks:ao,$location:Zt,$log:Jt,$parse:$n,$rootScope:xn,$q:yn,$$q:En,$sce:Sn,$sceDelegate:Tn,$sniffer:_n,$templateCache:mt,$templateRequest:Nn,$$testability:Dn,$timeout:In,$window:Hn,$$rAF:wn,$$jqLite:Qe,$$HashMap:_i,$$cookieReader:Fn})}])}function ye(){return++fi}function Ee(e){return e.replace(gi,function(e,t,n,r){return r?n.toUpperCase():n}).replace(vi,"Moz$1")}function Ce(e){return!Ei.test(e)}function we(e){var t=e.nodeType;return t===oi||!t||t===li}function xe(e){for(var t in mi[e.ng339])return!0;return!1}function ke(e){for(var t=0,n=e.length;t")+o[2],a=o[0];a--;)n=n.lastChild;c=U(c,n.childNodes),n=s.firstChild,n.textContent=""}return s.textContent="",s.innerHTML="",r(c,function(e){s.appendChild(e)}),s}function Ae(t,n){n=n||e.document;var r;return(r=yi.exec(t))?[n.createElement(r[1])]:(r=Me(t,n))?r.childNodes:[]}function Te(e,t){var n=e.parentNode;n&&n.replaceChild(t,e),t.appendChild(e)}function Se(e){if(e instanceof Se)return e;var t;if(E(e)&&(e=Xr(e),t=!0),!(this instanceof Se)){if(t&&"<"!=e.charAt(0))throw $i("nosel","Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element");return new Se(e)}t?Le(this,Ae(e)):Le(this,e)}function _e(e){return e.cloneNode(!0)}function Ne(e,t){if(t||Ie(e),e.querySelectorAll)for(var n=e.querySelectorAll("*"),r=0,i=n.length;r0||(pi(e,t,s),delete a[t])};r(t.split(" "),function(e){c(e),bi[e]&&c(bi[e])})}else for(t in a)"$destroy"!==t&&pi(e,t,s),delete a[t]}function Ie(e,t){var n=e.ng339,r=n&&mi[n];if(r){if(t)return void delete r.data[t];r.handle&&(r.events.$destroy&&r.handle({},"$destroy"),De(e)),delete mi[n],e.ng339=void 0}}function Oe(e,t){var n=e.ng339,r=n&&mi[n];return t&&!r&&(e.ng339=n=ye(),r=mi[n]={events:{},data:{},handle:void 0}),r}function Re(e,t,n){if(we(e)){var r=b(n),i=!r&&t&&!$(t),o=!t,a=Oe(e,!i),s=a&&a.data;if(r)s[t]=n;else{if(o)return s;if(i)return s&&s[t];l(s,t)}}}function He(e,t){return!!e.getAttribute&&(" "+(e.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ").indexOf(" "+t+" ")>-1}function Pe(e,t){t&&e.setAttribute&&r(t.split(" "),function(t){e.setAttribute("class",Xr((" "+(e.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ").replace(" "+Xr(t)+" "," ")))})}function Fe(e,t){if(t&&e.setAttribute){var n=(" "+(e.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ");r(t.split(" "),function(e){e=Xr(e),n.indexOf(" "+e+" ")===-1&&(n+=e+" ")}),e.setAttribute("class",Xr(n))}}function Le(e,t){if(t)if(t.nodeType)e[e.length++]=t;else{var n=t.length;if("number"==typeof n&&t.window!==t){if(n)for(var r=0;r1&&(i=ge(i));for(var c=0;cu&&this.remove(f.key),t}},get:function(e){if(u";var r=Ee.firstChild.attributes,i=r[0];r.removeNamedItem(i.name),i.value=n,e.attributes.setNamedItem(i)}function H(e,t){try{e.addClass(t)}catch(n){}}function L(t,n,r,i,o){t instanceof Fr||(t=Fr(t));for(var a=/\S+/,s=0,c=t.length;s").append(t).html())):n?Mi.clone.call(t):t,a)for(var l in a)c.data("$"+l+"Controller",a[l].instance);return L.$$addScopeInfo(c,e),n&&n(c,e),u&&u(e,c,c,i),c}}function U(e){var t=e&&e[0];return t&&"foreignobject"!==P(t)&&Br.call(t).match(/SVG/)?"svg":"html"}function B(e,t,n,r,i,o){function a(e,n,r,i){var o,a,s,c,l,u,d,m,p;if(f){var g=n.length;for(p=new Array(g),l=0;l0)}else r.push(e);return Fr(r)}function G(e,t,n){return function(r,i,o,a,s){return i=K(i[0],t,n),e(r,i,o,a,s)}}function X(e,t,n,r,i,o){var a;return e?L(t,n,r,i,o):function(){return a||(a=L(t,n,r,i,o),t=n=o=null),a.apply(this,arguments)}}function Z(e,t,n,o,a,s,c,u,d){function m(e,t,n,r){e&&(n&&(e=G(e,n,r)),e.require=h.require,e.directiveName=p,(k===h||h.$$isolateScope)&&(e=ge(e,{isolateScope:!0})),c.push(e)),t&&(n&&(t=G(t,n,r)),t.require=h.require,t.directiveName=p,(k===h||h.$$isolateScope)&&(t=ge(t,{isolateScope:!0})),u.push(t))}function f(e,o,a,s,d){function m(e,t,n,r){var i;if(A(e)||(r=n,n=t,t=e,e=void 0),N&&(i=y),n||(n=N?T.parent():T),!r)return d(e,t,i,n,F);var o=d.$$slots[r];if(o)return o(e,t,i,n,F);if(v(o))throw Wi("noslot",'No parent directive that requires a transclusion with slot name "{0}". Element: {1}',r,Q(T))}var f,h,p,g,b,y,E,T,S,_;t===a?(S=n,T=n.$$element):(T=Fr(a),S=new O(T,n)),b=o,k?g=o.$new(!0):C&&(b=o.$parent),d&&(E=m,E.$$boundTransclude=d,E.isSlotFilled=function(e){return!!d.$$slots[e]}),w&&(y=ee(T,S,E,w,g,o,k)),k&&(L.$$addScopeInfo(T,g,!0,!(M&&(M===k||M===k.$$originalDirective))),L.$$addScopeClass(T,!0),g.$$isolateBindings=k.$$isolateBindings,_=be(o,S,g,g.$$isolateBindings,k),_.removeWatches&&g.$on("$destroy",_.removeWatches));for(var D in y){var I=w[D],R=y[D],H=I.$$bindings.bindToController;R.identifier&&H?R.bindingInfo=be(b,S,R.instance,H,I):R.bindingInfo={};var P=R();P!==R.instance&&(R.instance=P,T.data("$"+I.name+"Controller",P),R.bindingInfo.removeWatches&&R.bindingInfo.removeWatches(),R.bindingInfo=be(b,S,R.instance,H,I))}for(r(w,function(e,t){var n=e.require;e.bindToController&&!Gr(n)&&$(n)&&l(y[t].instance,J(t,n,T,y))}),r(y,function(e){var t=e.instance;if(x(t.$onChanges))try{t.$onChanges(e.bindingInfo.initialChanges)}catch(n){i(n)}if(x(t.$onInit))try{t.$onInit()}catch(n){i(n)}x(t.$doCheck)&&(b.$watch(function(){t.$doCheck()}),t.$doCheck()),x(t.$onDestroy)&&b.$on("$destroy",function(){t.$onDestroy()})}),f=0,h=c.length;f=0;f--)p=u[f],ve(p,p.isolateScope?g:o,T,S,p.require&&J(p.directiveName,p.require,T,y),E);r(y,function(e){var t=e.instance;x(t.$postLink)&&t.$postLink()})}d=d||{};for(var h,p,g,b,y,E=-Number.MAX_VALUE,C=d.newScopeDirective,w=d.controllerDirectives,k=d.newIsolateScopeDirective,M=d.templateDirective,T=d.nonTlbTranscludeDirective,S=!1,_=!1,N=d.hasElementTranscludeDirective,D=n.$$element=Fr(t),I=s,R=o,H=!1,F=!1,j=0,U=e.length;jh.priority)break;if((y=h.scope)&&(h.templateUrl||($(y)?(ce("new/isolated scope",k||C,h,D),k=h):ce("new/isolated scope",k,h,D)),C=C||h),p=h.name,!H&&(h.replace&&(h.templateUrl||h.template)||h.transclude&&!h.$$tlb)){for(var Y,Z=j+1;Y=e[Z++];)if(Y.transclude&&!Y.$$tlb||Y.replace&&(Y.templateUrl||Y.template)){F=!0;break}H=!0}if(!h.templateUrl&&h.controller&&(y=h.controller,w=w||he(),ce("'"+p+"' controller",w[p],h,D),w[p]=h),y=h.transclude)if(S=!0,h.$$tlb||(ce("transclusion",T,h,D),T=h),"element"==y)N=!0,E=h.priority,g=D,D=n.$$element=Fr(L.$$createComment(p,n[p])),t=D[0],pe(a,V(g),t),g[0].$$parentNode=g[0].parentNode,R=X(F,g,o,E,I&&I.name,{nonTlbTranscludeDirective:T});else{var ne=he();if(g=Fr(_e(t)).contents(),$(y)){g=[];var re=he(),ae=he();r(y,function(e,t){var n="?"===e.charAt(0);e=n?e.substring(1):e,re[e]=t,ne[t]=null,ae[t]=n}),r(D.contents(),function(e){var t=re[gt(P(e))];t?(ae[t]=!0,ne[t]=ne[t]||[],ne[t].push(e)):g.push(e)}),r(ae,function(e,t){if(!e)throw Wi("reqslot","Required transclusion slot `{0}` was not filled.",t)});for(var se in ne)ne[se]&&(ne[se]=X(F,ne[se],o))}D.empty(),R=X(F,g,o,void 0,void 0,{needsNewScope:h.$$isolateScope||h.$$newScope}),R.$$slots=ne}if(h.template)if(_=!0,ce("template",M,h,D),M=h,y=x(h.template)?h.template(D,n):h.template,y=Me(y),h.replace){if(I=h,g=Ce(y)?[]:bt(de(h.templateNamespace,Xr(y))),t=g[0],1!=g.length||t.nodeType!==oi)throw Wi("tplrt","Template for directive '{0}' must have exactly one root element. {1}",p,"");pe(a,D,t);var le={$attr:{}},ue=W(t,[],le),me=e.splice(j+1,e.length-(j+1));(k||C)&&te(ue,k,C),e=e.concat(ue).concat(me),ie(n,le),U=e.length}else D.html(y);if(h.templateUrl)_=!0,ce("template",M,h,D),M=h,h.replace&&(I=h),f=oe(e.splice(j,e.length-j),D,n,a,S&&R,c,u,{controllerDirectives:w,newScopeDirective:C!==h&&C,newIsolateScopeDirective:k,templateDirective:M,nonTlbTranscludeDirective:T}),U=e.length;else if(h.compile)try{b=h.compile(D,n,R);var fe=h.$$originalDirective||h;x(b)?m(null,q(fe,b),B,z):b&&m(q(fe,b.pre),q(fe,b.post),B,z)}catch($e){i($e,Q(D))}h.terminal&&(f.terminal=!0,E=Math.max(E,h.priority))}return f.scope=C&&C.scope===!0,f.transcludeOnThisElement=S,f.templateOnThisElement=_,f.transclude=R,d.hasElementTranscludeDirective=N,f}function J(e,t,n,i){var o;if(E(t)){var a=t.match(w),s=t.substring(a[0].length),c=a[1]||a[3],l="?"===a[2];if("^^"===c?n=n.parent():(o=i&&i[s],o=o&&o.instance),!o){var u="$"+s+"Controller";o=c?n.inheritedData(u):n.data(u)}if(!o&&!l)throw Wi("ctreq","Controller '{0}', required by directive '{1}', can't be found!",s,e)}else if(Gr(t)){o=[];for(var d=0,m=t.length;dh.priority)&&h.restrict.indexOf(r)!=-1){if(c&&(h=m(h,{$$start:c,$$end:l})),!h.$$bindings){var y=h.$$bindings=a(h,h.name);$(y.isolateScope)&&(h.$$isolateBindings=y.isolateScope)}e.push(h),f=h}}catch(E){i(E)}return f}function re(e){if(u.hasOwnProperty(e))for(var n,r=t.get(e+d),i=0,o=r.length;i"+n+"",r.childNodes[0].childNodes;default:return n}}function me(e,t){if("srcdoc"==t)return M.HTML;var n=P(e);return"xlinkHref"==t||"form"==n&&"action"==t||"img"!=n&&("src"==t||"ngSrc"==t)?M.RESOURCE_URL:void 0}function fe(e,t,r,i,o){var a=me(e,i);o=C[i]||o;var s=n(r,!0,a,o);if(s){if("multiple"===i&&"select"===P(e))throw Wi("selmulti","Binding to the 'multiple' attribute is not supported. Element: {0}",Q(e));t.push({priority:100,compile:function(){return{pre:function(e,t,c){var l=c.$$observers||(c.$$observers=he());if(k.test(i))throw Wi("nodomevents","Interpolations for HTML DOM event attributes are disallowed. Please use the ng- versions (such as ng-click instead of onclick) instead.");var u=c[i];u!==r&&(s=u&&n(u,!0,a,o),r=u),s&&(c[i]=s(e),(l[i]||(l[i]=[])).$$inter=!0,(c.$$observers&&c.$$observers[i].$$scope||e).$watch(s,function(e,t){"class"===i&&e!=t?c.$updateClass(e,t):c.$set(i,e)}))}}}})}}function pe(t,n,r){var i,o,a=n[0],s=n.length,c=a.parentNode;if(t)for(i=0,o=t.length;i0&&_.addClass(this.$$element,e)},$removeClass:function(e){e&&e.length>0&&_.removeClass(this.$$element,e)},$updateClass:function(e,t){var n=vt(e,t);n&&n.length&&_.addClass(this.$$element,n);var r=vt(t,e);r&&r.length&&_.removeClass(this.$$element,r)},$set:function(e,t,n,o){var a,s=this.$$element[0],c=ze(s,e),l=We(e),u=e;if(c?(this.$$element.prop(e,t),o=c):l&&(this[l]=t,u=l),this[e]=t,o?this.$attr[e]=o:(o=this.$attr[e],o||(this.$attr[e]=o=se(e,"-"))),a=P(this.$$element),"a"===a&&("href"===e||"xlinkHref"===e)||"img"===a&&"src"===e)this[e]=t=D(t,"src"===e);else if("img"===a&&"srcset"===e&&b(t)){for(var d="",m=Xr(t),f=/(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/,h=/\s/.test(m)?f:/(,)/,p=m.split(h),g=Math.floor(p.length/2),$=0;$0?" ":"")+a}return n}function bt(e){e=Fr(e);var t=e.length;if(t<=1)return e;for(;t--;){var n=e[t];n.nodeType===ci&&Vr.call(e,t,1)}return e}function $t(e,t){if(t&&E(t))return t;if(E(e)){var n=Qi.exec(e);if(n)return n[3]}}function yt(){var e={},n=!1;this.has=function(t){return e.hasOwnProperty(t)},this.register=function(t,n){de(t,"controller"),$(t)?l(e,t):e[t]=n},this.allowGlobals=function(){n=!0},this.$get=["$injector","$window",function(r,i){function o(e,n,r,i){if(!e||!$(e.$scope))throw t("$controller")("noscp","Cannot export controller '{0}' as '{1}'! No $scope object provided via `locals`.",i,n);e.$scope[n]=r}return function(t,a,s,c){var u,d,m,f;if(s=s===!0,c&&E(c)&&(f=c),E(t)){if(d=t.match(Qi),!d)throw Gi("ctrlfmt","Badly formed controller string '{0}'. Must match `__name__ as __id__` or `__name__`.",t);m=d[1],f=f||d[3],t=e.hasOwnProperty(m)?e[m]:me(a.$scope,m,!0)||(n?me(i,m,!0):void 0),ue(t,m,!0)}if(s){var h=(Gr(t)?t[t.length-1]:t).prototype;u=Object.create(h||null),f&&o(a,f,u,m||t.name);var p;return p=l(function(){var e=r.invoke(t,u,a,m);return e!==u&&($(e)||x(e))&&(u=e,f&&o(a,f,u,m||t.name)),u},{instance:u,identifier:f})}return u=r.instantiate(t,a,m),f&&o(a,f,u,m||t.name),u}}]}function Et(){this.$get=["$window",function(e){return Fr(e.document)}]}function Ct(){this.$get=["$log",function(e){return function(t,n){e.error.apply(e,arguments)}}]}function wt(e){return $(e)?w(e)?e.toISOString():z(e):e}function xt(){this.$get=function(){return function(e){if(!e)return"";var t=[];return i(e,function(e,n){null===e||v(e)||(Gr(e)?r(e,function(e){t.push(te(n)+"="+te(wt(e)))}):t.push(te(n)+"="+te(wt(e))))}),t.join("&")}}}function kt(){this.$get=function(){return function(e){function t(e,o,a){null===e||v(e)||(Gr(e)?r(e,function(e,n){t(e,o+"["+($(e)?n:"")+"]")}):$(e)&&!w(e)?i(e,function(e,n){t(e,o+(a?"":"[")+n+(a?"":"]"))}):n.push(te(o)+"="+te(wt(e))))}if(!e)return"";var n=[];return t(e,"",!0),n.join("&")}}}function Mt(e,t){if(E(e)){var n=e.replace(no,"").trim();if(n){var r=t("Content-Type");(r&&0===r.indexOf(Zi)||At(n))&&(e=W(n))}}return e}function At(e){var t=e.match(eo);return t&&to[t[0]].test(e)}function Tt(e){function t(e,t){e&&(i[e]=i[e]?i[e]+", "+t:t)}var n,i=he();return E(e)?r(e.split("\n"),function(e){n=e.indexOf(":"),t(Ir(Xr(e.substr(0,n))),Xr(e.substr(n+1)))}):$(e)&&r(e,function(e,n){t(Ir(n),Xr(e))}),i}function St(e){var t;return function(n){if(t||(t=Tt(e)),n){var r=t[Ir(n)];return void 0===r&&(r=null),r}return t}}function _t(e,t,n,i){return x(i)?i(e,t,n):(r(i,function(r){e=r(e,t,n)}),e)}function Nt(e){return 200<=e&&e<300}function Dt(){var e=this.defaults={transformResponse:[Mt],transformRequest:[function(e){return!$(e)||T(e)||_(e)||S(e)?e:z(e)}],headers:{common:{Accept:"application/json, text/plain, */*"},post:ge(Ji),put:ge(Ji),patch:ge(Ji)},xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",paramSerializer:"$httpParamSerializer"},n=!1;this.useApplyAsync=function(e){return b(e)?(n=!!e,this):n};var i=!0;this.useLegacyPromiseExtensions=function(e){return b(e)?(i=!!e,this):i};var o=this.interceptors=[];this.$get=["$httpBackend","$$cookieReader","$cacheFactory","$rootScope","$q","$injector",function(a,s,c,u,d,m){function f(n){function o(e,t){for(var n=0,r=t.length;n=-1?n:0,(Nt(n)?E.resolve:E.reject)({data:e,status:n,headers:St(r),config:t,statusText:i})}function m(e){l(e.data,e.status,ge(e.headers()),e.statusText)}function h(){var e=f.pendingRequests.indexOf(t);e!==-1&&f.pendingRequests.splice(e,1)}var p,g,E=d.defer(),w=E.promise,x=t.headers,k=y(t.url,t.paramSerializer(t.params));if(f.pendingRequests.push(t),w.then(h,h),!t.cache&&!e.cache||t.cache===!1||"GET"!==t.method&&"JSONP"!==t.method||(p=$(t.cache)?t.cache:$(e.cache)?e.cache:C),p&&(g=p.get(k),b(g)?D(g)?g.then(m,m):Gr(g)?l(g[1],g[0],ge(g[2]),g[3]):l(g,200,{},"OK"):p.put(k,w)),v(g)){var M=Rn(t.url)?s()[t.xsrfCookieName||e.xsrfCookieName]:void 0;M&&(x[t.xsrfHeaderName||e.xsrfHeaderName]=M),a(t.method,k,i,c,x,t.timeout,t.withCredentials,t.responseType,o(t.eventHandlers),o(t.uploadEventHandlers))}return w}function y(e,t){return t.length>0&&(e+=(e.indexOf("?")==-1?"?":"&")+t),e}var C=c("$http");e.paramSerializer=E(e.paramSerializer)?m.get(e.paramSerializer):e.paramSerializer;var w=[];return r(o,function(e){w.unshift(E(e)?m.get(e):m.invoke(e))}),f.pendingRequests=[],h("get","delete","head","jsonp"),p("post","put","patch"),f.defaults=e,f}]}function It(){this.$get=function(){return function(){return new e.XMLHttpRequest}}}function Ot(){this.$get=["$browser","$jsonpCallbacks","$document","$xhrFactory",function(e,t,n,r){return Rt(e,r,e.defer,t,n[0])}]}function Rt(e,t,n,i,o){function a(e,t,n){e=e.replace("JSON_CALLBACK",t);var r=o.createElement("script"),a=null;return r.type="text/javascript",r.src=e,r.async=!0,a=function(e){pi(r,"load",a),pi(r,"error",a),o.body.removeChild(r),r=null;var s=-1,c="unknown";e&&("load"!==e.type||i.wasCalled(t)||(e={type:"error"}),c=e.type,s="error"===e.type?404:200),n&&n(s,c)},hi(r,"load",a),hi(r,"error",a),o.body.appendChild(r),a}return function(o,s,c,l,u,d,m,h,p,g){function $(){C&&C(),w&&w.abort()}function y(t,r,i,o,a){b(M)&&n.cancel(M),C=w=null,t(r,i,o,a),e.$$completeOutstandingRequest(f)}if(e.$$incOutstandingRequestCount(),s=s||e.url(),"jsonp"===Ir(o))var E=i.createCallback(s),C=a(s,E,function(e,t){var n=200===e&&i.getResponse(E);y(l,e,n,"",t),i.removeCallback(E)});else{var w=t(o,s);w.open(o,s,!0),r(u,function(e,t){b(e)&&w.setRequestHeader(t,e)}),w.onload=function(){var e=w.statusText||"",t="response"in w?w.response:w.responseText,n=1223===w.status?204:w.status;0===n&&(n=t?200:"file"==On(s).protocol?404:0),y(l,n,t,w.getAllResponseHeaders(),e)};var x=function(){y(l,-1,null,null,"")};if(w.onerror=x,w.onabort=x,r(p,function(e,t){w.addEventListener(t,e)}),r(g,function(e,t){w.upload.addEventListener(t,e)}),m&&(w.withCredentials=!0),h)try{w.responseType=h}catch(k){if("json"!==h)throw k}w.send(v(c)?null:c)}if(d>0)var M=n($,d);else D(d)&&d.then($)}}function Ht(){var e="{{",t="}}";this.startSymbol=function(t){return t?(e=t,this):e},this.endSymbol=function(e){return e?(t=e,this):t},this.$get=["$parse","$exceptionHandler","$sce",function(n,r,i){function o(e){return"\\\\\\"+e}function a(n){return n.replace(f,e).replace(h,t)}function s(e){if(null==e)return"";switch(typeof e){case"string":break;case"number":e=""+e;break;default:e=z(e)}return e}function c(e,t,n,r){var i;return i=e.$watch(function(e){return i(),r(e)},t,n)}function u(o,u,f,h){function g(e){try{return e=D(e),h&&!b(e)?e:s(e)}catch(t){r(oo.interr(o,t))}}if(!o.length||o.indexOf(e)===-1){var $;if(!u){var y=a(o);$=p(y),$.exp=o,$.expressions=[],$.$$watchDelegate=c}return $}h=!!h;for(var E,C,w,k=0,M=[],A=[],T=o.length,S=[],_=[];k1&&oo.throwNoconcat(o),!u||M.length){var N=function(e){for(var t=0,n=M.length;t4,m=d?V(arguments,4):[],f=t.setInterval,h=t.clearInterval,p=0,g=b(l)&&!l,v=(g?r:n).defer(),$=v.promise;return c=b(c)?c:0,$.$$intervalId=f(function(){g?i.defer(u):e.$evalAsync(u),v.notify(p++),c>0&&p>=c&&(v.resolve(p),h($.$$intervalId),delete a[$.$$intervalId]),g||e.$apply()},s),a[$.$$intervalId]=v,$}var a={};return o.cancel=function(e){return!!(e&&e.$$intervalId in a)&&(a[e.$$intervalId].reject("canceled"),t.clearInterval(e.$$intervalId),delete a[e.$$intervalId],!0)},o}]}function Ft(e){for(var t=e.split("/"),n=t.length;n--;)t[n]=ee(t[n]);return t.join("/")}function Lt(e,t){var n=On(e);t.$$protocol=n.protocol,t.$$host=n.hostname,t.$$port=d(n.port)||co[n.protocol]||null}function jt(e,t){var n="/"!==e.charAt(0);n&&(e="/"+e);var r=On(e);t.$$path=decodeURIComponent(n&&"/"===r.pathname.charAt(0)?r.pathname.substring(1):r.pathname),t.$$search=Z(r.search),t.$$hash=decodeURIComponent(r.hash),t.$$path&&"/"!=t.$$path.charAt(0)&&(t.$$path="/"+t.$$path)}function Ut(e,t){return 0===e.lastIndexOf(t,0)}function Vt(e,t){if(Ut(t,e))return t.substr(e.length)}function qt(e){var t=e.indexOf("#");return t==-1?e:e.substr(0,t)}function Bt(e){return e.replace(/(#.+)|#$/,"$1")}function zt(e){return e.substr(0,qt(e).lastIndexOf("/")+1)}function Wt(e){return e.substring(0,e.indexOf("/",e.indexOf("//")+2))}function Yt(e,t,n){this.$$html5=!0,n=n||"",Lt(e,this),this.$$parse=function(e){var n=Vt(t,e);if(!E(n))throw lo("ipthprfx",'Invalid url "{0}", missing path prefix "{1}".',e,t);jt(n,this),this.$$path||(this.$$path="/"),this.$$compose()},this.$$compose=function(){var e=J(this.$$search),n=this.$$hash?"#"+ee(this.$$hash):"";this.$$url=Ft(this.$$path)+(e?"?"+e:"")+n,this.$$absUrl=t+this.$$url.substr(1)},this.$$parseLinkUrl=function(r,i){if(i&&"#"===i[0])return this.hash(i.slice(1)),!0;var o,a,s;return b(o=Vt(e,r))?(a=o,s=b(o=Vt(n,o))?t+(Vt("/",o)||o):e+a):b(o=Vt(t,r))?s=t+o:t==r+"/"&&(s=t),s&&this.$$parse(s),!!s}}function Kt(e,t,n){Lt(e,this),this.$$parse=function(r){function i(e,t,n){var r,i=/^\/[A-Z]:(\/.*)/;return Ut(t,n)&&(t=t.replace(n,"")),i.exec(t)?e:(r=i.exec(e),r?r[1]:e)}var o,a=Vt(e,r)||Vt(t,r);v(a)||"#"!==a.charAt(0)?this.$$html5?o=a:(o="",v(a)&&(e=r,this.replace())):(o=Vt(n,a),v(o)&&(o=a)),jt(o,this),this.$$path=i(this.$$path,o,e),this.$$compose()},this.$$compose=function(){var t=J(this.$$search),r=this.$$hash?"#"+ee(this.$$hash):"";this.$$url=Ft(this.$$path)+(t?"?"+t:"")+r,this.$$absUrl=e+(this.$$url?n+this.$$url:"")},this.$$parseLinkUrl=function(t,n){return qt(e)==qt(t)&&(this.$$parse(t),!0)}}function Gt(e,t,n){this.$$html5=!0,Kt.apply(this,arguments),this.$$parseLinkUrl=function(r,i){if(i&&"#"===i[0])return this.hash(i.slice(1)),!0;var o,a;return e==qt(r)?o=r:(a=Vt(t,r))?o=e+n+a:t===r+"/"&&(o=t),o&&this.$$parse(o),!!o},this.$$compose=function(){var t=J(this.$$search),r=this.$$hash?"#"+ee(this.$$hash):"";this.$$url=Ft(this.$$path)+(t?"?"+t:"")+r,this.$$absUrl=e+n+this.$$url}}function Qt(e){return function(){return this[e]}}function Xt(e,t){return function(n){return v(n)?this[e]:(this[e]=t(n),this.$$compose(),this)}}function Zt(){var e="",t={enabled:!1,requireBase:!0,rewriteLinks:!0};this.hashPrefix=function(t){return b(t)?(e=t,this):e},this.html5Mode=function(e){return N(e)?(t.enabled=e,this):$(e)?(N(e.enabled)&&(t.enabled=e.enabled),N(e.requireBase)&&(t.requireBase=e.requireBase),N(e.rewriteLinks)&&(t.rewriteLinks=e.rewriteLinks),this):t},this.$get=["$rootScope","$browser","$sniffer","$rootElement","$window",function(n,r,i,o,a){function s(e,t,n){var i=l.url(),o=l.$$state;try{r.url(e,t,n),l.$$state=r.state()}catch(a){throw l.url(i),l.$$state=o,a}}function c(e,t){n.$broadcast("$locationChangeSuccess",l.absUrl(),e,l.$$state,t)}var l,u,d,m=r.baseHref(),f=r.url();if(t.enabled){if(!m&&t.requireBase)throw lo("nobase","$location in HTML5 mode requires a tag to be present!");d=Wt(f)+(m||"/"),u=i.history?Yt:Gt}else d=qt(f),u=Kt;var h=zt(d);l=new u(d,h,"#"+e),l.$$parseLinkUrl(f,f),l.$$state=r.state();var p=/^\s*(javascript|mailto):/i;o.on("click",function(e){if(t.rewriteLinks&&!e.ctrlKey&&!e.metaKey&&!e.shiftKey&&2!=e.which&&2!=e.button){for(var i=Fr(e.target);"a"!==P(i[0]);)if(i[0]===o[0]||!(i=i.parent())[0])return;var s=i.prop("href"),c=i.attr("href")||i.attr("xlink:href");$(s)&&"[object SVGAnimatedString]"===s.toString()&&(s=On(s.animVal).href),p.test(s)||!s||i.attr("target")||e.isDefaultPrevented()||l.$$parseLinkUrl(s,c)&&(e.preventDefault(),l.absUrl()!=r.url()&&(n.$apply(),a.angular["ff-684208-preventDefault"]=!0))}}),Bt(l.absUrl())!=Bt(f)&&r.url(l.absUrl(),!0);var g=!0;return r.onUrlChange(function(e,t){return v(Vt(h,e))?void(a.location.href=e):(n.$evalAsync(function(){var r,i=l.absUrl(),o=l.$$state;e=Bt(e),l.$$parse(e),l.$$state=t,r=n.$broadcast("$locationChangeStart",e,i,t,o).defaultPrevented,l.absUrl()===e&&(r?(l.$$parse(i),l.$$state=o,s(i,!1,o)):(g=!1,c(i,o)))}),void(n.$$phase||n.$digest()))}),n.$watch(function(){var e=Bt(r.url()),t=Bt(l.absUrl()),o=r.state(),a=l.$$replace,u=e!==t||l.$$html5&&i.history&&o!==l.$$state;(g||u)&&(g=!1,n.$evalAsync(function(){var t=l.absUrl(),r=n.$broadcast("$locationChangeStart",t,e,l.$$state,o).defaultPrevented;l.absUrl()===t&&(r?(l.$$parse(e),l.$$state=o):(u&&s(t,a,o===l.$$state?null:l.$$state),c(e,o)))})),l.$$replace=!1}),l}]}function Jt(){var e=!0,t=this;this.debugEnabled=function(t){return b(t)?(e=t,this):e},this.$get=["$window",function(n){function i(e){return e instanceof Error&&(e.stack?e=e.message&&e.stack.indexOf(e.message)===-1?"Error: "+e.message+"\n"+e.stack:e.stack:e.sourceURL&&(e=e.message+"\n"+e.sourceURL+":"+e.line)),e}function o(e){var t=n.console||{},o=t[e]||t.log||f,a=!1;try{a=!!o.apply}catch(s){}return a?function(){var e=[];return r(arguments,function(t){e.push(i(t))}),o.apply(t,e)}:function(e,t){o(e,null==t?"":t)}}return{log:o("log"),info:o("info"),warn:o("warn"),error:o("error"),debug:function(){var n=o("debug");return function(){e&&n.apply(t,arguments)}}()}}]}function en(e,t){if("__defineGetter__"===e||"__defineSetter__"===e||"__lookupGetter__"===e||"__lookupSetter__"===e||"__proto__"===e)throw mo("isecfld","Attempting to access a disallowed field in Angular expressions! Expression: {0}",t);return e}function tn(e){return e+""}function nn(e,t){if(e){if(e.constructor===e)throw mo("isecfn","Referencing Function in Angular expressions is disallowed! Expression: {0}",t);if(e.window===e)throw mo("isecwindow","Referencing the Window in Angular expressions is disallowed! Expression: {0}",t);if(e.children&&(e.nodeName||e.prop&&e.attr&&e.find))throw mo("isecdom","Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}",t);if(e===Object)throw mo("isecobj","Referencing Object in Angular expressions is disallowed! Expression: {0}",t)}return e}function rn(e,t){if(e){if(e.constructor===e)throw mo("isecfn","Referencing Function in Angular expressions is disallowed! Expression: {0}",t);if(e===fo||e===ho||e===po)throw mo("isecff","Referencing call, apply or bind in Angular expressions is disallowed! Expression: {0}",t)}}function on(e,t){if(e&&(e===(0).constructor||e===(!1).constructor||e==="".constructor||e==={}.constructor||e===[].constructor||e===Function.constructor))throw mo("isecaf","Assigning to a constructor is disallowed! Expression: {0}",t)}function an(e,t){return"undefined"!=typeof e?e:t}function sn(e,t){return"undefined"==typeof e?t:"undefined"==typeof t?e:e+t}function cn(e,t){var n=e(t);return!n.$stateful}function ln(e,t){var n,i;switch(e.type){case $o.Program:n=!0,r(e.body,function(e){ln(e.expression,t),n=n&&e.expression.constant}),e.constant=n;break;case $o.Literal:e.constant=!0,e.toWatch=[];break;case $o.UnaryExpression:ln(e.argument,t),e.constant=e.argument.constant,e.toWatch=e.argument.toWatch;break;case $o.BinaryExpression:ln(e.left,t),ln(e.right,t),e.constant=e.left.constant&&e.right.constant,e.toWatch=e.left.toWatch.concat(e.right.toWatch);break;case $o.LogicalExpression:ln(e.left,t),ln(e.right,t),e.constant=e.left.constant&&e.right.constant,e.toWatch=e.constant?[]:[e];break;case $o.ConditionalExpression:ln(e.test,t),ln(e.alternate,t),ln(e.consequent,t),e.constant=e.test.constant&&e.alternate.constant&&e.consequent.constant,e.toWatch=e.constant?[]:[e];break;case $o.Identifier:e.constant=!1,e.toWatch=[e];break;case $o.MemberExpression:ln(e.object,t),e.computed&&ln(e.property,t),e.constant=e.object.constant&&(!e.computed||e.property.constant),e.toWatch=[e];break;case $o.CallExpression: +n=!!e.filter&&cn(t,e.callee.name),i=[],r(e.arguments,function(e){ln(e,t),n=n&&e.constant,e.constant||i.push.apply(i,e.toWatch)}),e.constant=n,e.toWatch=e.filter&&cn(t,e.callee.name)?i:[e];break;case $o.AssignmentExpression:ln(e.left,t),ln(e.right,t),e.constant=e.left.constant&&e.right.constant,e.toWatch=[e];break;case $o.ArrayExpression:n=!0,i=[],r(e.elements,function(e){ln(e,t),n=n&&e.constant,e.constant||i.push.apply(i,e.toWatch)}),e.constant=n,e.toWatch=i;break;case $o.ObjectExpression:n=!0,i=[],r(e.properties,function(e){ln(e.value,t),n=n&&e.value.constant&&!e.computed,e.value.constant||i.push.apply(i,e.value.toWatch)}),e.constant=n,e.toWatch=i;break;case $o.ThisExpression:e.constant=!1,e.toWatch=[];break;case $o.LocalsExpression:e.constant=!1,e.toWatch=[]}}function un(e){if(1==e.length){var t=e[0].expression,n=t.toWatch;return 1!==n.length?n:n[0]!==t?n:void 0}}function dn(e){return e.type===$o.Identifier||e.type===$o.MemberExpression}function mn(e){if(1===e.body.length&&dn(e.body[0].expression))return{type:$o.AssignmentExpression,left:e.body[0].expression,right:{type:$o.NGValueParameter},operator:"="}}function fn(e){return 0===e.body.length||1===e.body.length&&(e.body[0].expression.type===$o.Literal||e.body[0].expression.type===$o.ArrayExpression||e.body[0].expression.type===$o.ObjectExpression)}function hn(e){return e.constant}function pn(e,t){this.astBuilder=e,this.$filter=t}function gn(e,t){this.astBuilder=e,this.$filter=t}function vn(e){return"constructor"==e}function bn(e){return x(e.valueOf)?e.valueOf():Eo.call(e)}function $n(){var e,t,n=he(),i=he(),o={"true":!0,"false":!1,"null":null,undefined:void 0};this.addLiteral=function(e,t){o[e]=t},this.setIdentifierFns=function(n,r){return e=n,t=r,this},this.$get=["$filter",function(a){function s(e,t,r){var o,s,l;switch(r=r||y,typeof e){case"string":e=e.trim(),l=e;var g=r?i:n;if(o=g[l],!o){":"===e.charAt(0)&&":"===e.charAt(1)&&(s=!0,e=e.substring(2));var b=r?$:v,E=new bo(b),C=new yo(E,a,b);o=C.parse(e),o.constant?o.$$watchDelegate=h:s?o.$$watchDelegate=o.literal?m:d:o.inputs&&(o.$$watchDelegate=u),r&&(o=c(o)),g[l]=o}return p(o,t);case"function":return p(e,t);default:return p(f,t)}}function c(e){function t(t,n,r,i){var o=y;y=!0;try{return e(t,n,r,i)}finally{y=o}}if(!e)return e;t.$$watchDelegate=e.$$watchDelegate,t.assign=c(e.assign),t.constant=e.constant,t.literal=e.literal;for(var n=0;e.inputs&&n0&&s(this.$$state),r.promise},"catch":function(e){return this.then(null,e)},"finally":function(e,t){return this.then(function(t){return g(t,!0,e)},function(t){return g(t,!1,e)},t)}}),l(c.prototype,{resolve:function(e){this.promise.$$state.status||(e===this.promise?this.$$reject(m("qcycle","Expected promise to be resolved with value other than itself '{0}'",e)):this.$$resolve(e))},$$resolve:function(e){function t(e){c||(c=!0,a.$$resolve(e))}function r(e){c||(c=!0,a.$$reject(e))}var i,a=this,c=!1;try{($(e)||x(e))&&(i=e&&e.then),x(i)?(this.promise.$$state.status=-1,i.call(e,t,r,o(this,this.notify))):(this.promise.$$state.value=e,this.promise.$$state.status=1,s(this.promise.$$state))}catch(l){r(l),n(l)}},reject:function(e){this.promise.$$state.status||this.$$reject(e)},$$reject:function(e){this.promise.$$state.value=e,this.promise.$$state.status=2,s(this.promise.$$state)},notify:function(t){var r=this.promise.$$state.pending;this.promise.$$state.status<=0&&r&&r.length&&e(function(){for(var e,i,o=0,a=r.length;o=0&&b(o,-1),s=null}},$watchGroup:function(e,t){function n(){c=!1,l?(l=!1,t(o,o,s)):t(o,i,s)}var i=new Array(e.length),o=new Array(e.length),a=[],s=this,c=!1,l=!0;if(!e.length){var u=!0;return s.$evalAsync(function(){u&&t(o,o,s)}),function(){u=!1}}return 1===e.length?this.$watch(e[0],function(e,n,r){o[0]=e,i[0]=n,t(o,e===n?o:i,r)}):(r(e,function(e,t){var r=s.$watch(e,function(e,r){o[t]=e,i[t]=r,c||(c=!0,s.$evalAsync(n))});a.push(r)}),function(){for(;a.length;)a.shift()()})},$watchCollection:function(e,t){function r(e){o=e;var t,r,i,s,c;if(!v(o)){if($(o))if(n(o)){a!==f&&(a=f,g=a.length=0,d++),t=o.length,g!==t&&(d++,a.length=g=t);for(var l=0;lt){d++;for(r in a)Dr.call(o,r)||(g--,delete a[r])}}else a!==o&&(a=o,d++);return d}}function i(){if(p?(p=!1,t(o,o,c)):t(o,s,c),u)if($(o))if(n(o)){s=new Array(o.length);for(var e=0;e1,d=0,m=l(e,r),f=[],h={},p=!0,g=0;return this.$watch(m,i)},$digest:function(){var e,n,r,a,l,d,m,f,h,v,b,$,y=i,w=this,T=[];p("$digest"),u.$$checkUrlChange(),this===k&&null!==c&&(u.defer.cancel(c),C()),s=null;do{f=!1,v=w;for(var _=0;_-1)throw Co("iwcard","Illegal sequence *** in string matcher. String: {0}",e);return e=Zr(e).replace("\\*\\*",".*").replace("\\*","[^:/.?&;]*"),new RegExp("^"+e+"$")}if(k(e))return new RegExp("^"+e.source+"$");throw Co("imatcher",'Matchers may only be "self", string patterns or RegExp objects')}function An(e){var t=[];return b(e)&&r(e,function(e){t.push(Mn(e))}),t}function Tn(){this.SCE_CONTEXTS=wo;var e=["self"],t=[];this.resourceUrlWhitelist=function(t){return arguments.length&&(e=An(t)),e},this.resourceUrlBlacklist=function(e){return arguments.length&&(t=An(e)),t},this.$get=["$injector",function(n){function r(e,t){return"self"===e?Rn(t):!!e.exec(t.href)}function i(n){var i,o,a=On(n.toString()),s=!1;for(i=0,o=e.length;i to the top of your HTML document. See http://docs.angularjs.org/api/ng.$sce for more information.");var i=ge(wo);i.isEnabled=function(){return e},i.trustAs=n.trustAs,i.getTrusted=n.getTrusted,i.valueOf=n.valueOf,e||(i.trustAs=i.getTrusted=function(e,t){return t},i.valueOf=h),i.parseAs=function(e,n){var r=t(n);return r.literal&&r.constant?r:t(n,function(t){return i.getTrusted(e,t)})};var o=i.parseAs,a=i.getTrusted,s=i.trustAs;return r(wo,function(e,t){var n=Ir(t);i[Ee("parse_as_"+n)]=function(t){return o(e,t)},i[Ee("get_trusted_"+n)]=function(t){return a(e,t)},i[Ee("trust_as_"+n)]=function(t){return s(e,t)}}),i}]}function _n(){this.$get=["$window","$document",function(e,t){var n,r,i={},o=e.chrome&&e.chrome.app&&e.chrome.app.runtime,a=!o&&e.history&&e.history.pushState,s=d((/android (\d+)/.exec(Ir((e.navigator||{}).userAgent))||[])[1]),c=/Boxee/i.test((e.navigator||{}).userAgent),l=t[0]||{},u=/^(Moz|webkit|ms)(?=[A-Z])/,m=l.body&&l.body.style,f=!1,h=!1;if(m){for(var p in m)if(r=u.exec(p)){n=r[0],n=n[0].toUpperCase()+n.substr(1);break}n||(n="WebkitOpacity"in m&&"webkit"),f=!!("transition"in m||n+"Transition"in m),h=!!("animation"in m||n+"Animation"in m),!s||f&&h||(f=E(m.webkitTransition),h=E(m.webkitAnimation))}return{history:!(!a||s<4||c),hasEvent:function(e){if("input"===e&&Pr<=11)return!1;if(v(i[e])){var t=l.createElement("div");i[e]="on"+e in t}return i[e]},csp:Jr(),vendorPrefix:n,transitions:f,animations:h,android:s}}]}function Nn(){var e;this.httpOptions=function(t){return t?(e=t,this):e},this.$get=["$templateCache","$http","$q","$sce",function(t,n,r,i){function o(a,s){function c(e){if(!s)throw xo("tpload","Failed to load template: {0} (HTTP status: {1} {2})",a,e.status,e.statusText);return r.reject(e)}o.totalPendingRequests++,E(a)&&!v(t.get(a))||(a=i.getTrustedResourceUrl(a));var u=n.defaults&&n.defaults.transformResponse;return Gr(u)?u=u.filter(function(e){return e!==Mt}):u===Mt&&(u=null),n.get(a,l({cache:t,transformResponse:u},e))["finally"](function(){o.totalPendingRequests--}).then(function(e){return t.put(a,e.data),e.data},c)}return o.totalPendingRequests=0,o}]}function Dn(){this.$get=["$rootScope","$browser","$location",function(e,t,n){var i={};return i.findBindings=function(e,t,n){var i=e.getElementsByClassName("ng-binding"),o=[];return r(i,function(e){var i=Yr.element(e).data("$binding");i&&r(i,function(r){if(n){var i=new RegExp("(^|\\s)"+Zr(t)+"(\\s|\\||$)");i.test(r)&&o.push(e)}else r.indexOf(t)!=-1&&o.push(e)})}),o},i.findModels=function(e,t,n){for(var r=["ng-","data-ng-","ng\\:"],i=0;i0&&(c=t(o.substring(0,s)),v(r[c])&&(r[c]=t(o.substring(s+1))));return r}}function Fn(){this.$get=Pn}function Ln(e){function t(i,o){if($(i)){var a={};return r(i,function(e,n){a[n]=t(n,e)}),a}return e.factory(i+n,o)}var n="Filter";this.register=t,this.$get=["$injector",function(e){return function(t){return e.get(t+n)}}],t("currency",Bn),t("date",or),t("filter",jn),t("json",ar),t("limitTo",sr),t("lowercase",Io),t("number",zn),t("orderBy",lr),t("uppercase",Oo)}function jn(){return function(e,r,i,o){if(!n(e)){if(null==e)return e;throw t("filter")("notarray","Expected array but received: {0}",e)}o=o||"$";var a,s,c=qn(r);switch(c){case"function":a=r;break;case"boolean":case"null":case"number":case"string":s=!0;case"object":a=Un(r,i,o,s);break;default:return e}return Array.prototype.filter.call(e,a)}}function Un(e,t,n,r){var i,o=$(e)&&n in e;return t===!0?t=j:x(t)||(t=function(e,t){return!v(e)&&(null===e||null===t?e===t:!($(t)||$(e)&&!g(e))&&(e=Ir(""+e),t=Ir(""+t),e.indexOf(t)!==-1))}),i=function(i){return o&&!$(i)?Vn(i,e[n],t,n,!1):Vn(i,e,t,n,r)}}function Vn(e,t,n,r,i,o){var a=qn(e),s=qn(t);if("string"===s&&"!"===t.charAt(0))return!Vn(e,t.substring(1),n,r,i);if(Gr(e))return e.some(function(e){return Vn(e,t,n,r,i)});switch(a){case"object":var c;if(i){for(c in e)if("$"!==c.charAt(0)&&Vn(e[c],t,n,r,!0))return!0;return!o&&Vn(e,t,n,r,!1)}if("object"===s){for(c in t){var l=t[c];if(!x(l)&&!v(l)){var u=c===r,d=u?e:e[c];if(!Vn(d,l,n,r,u,u))return!1}}return!0}return n(e,t);case"function":return!1;default:return n(e,t)}}function qn(e){return null===e?"null":typeof e}function Bn(e){var t=e.NUMBER_FORMATS;return function(e,n,r){return v(n)&&(n=t.CURRENCY_SYM),v(r)&&(r=t.PATTERNS[1].maxFrac),null==e?e:Kn(e,t.PATTERNS[1],t.GROUP_SEP,t.DECIMAL_SEP,r).replace(/\u00A4/g,n)}}function zn(e){var t=e.NUMBER_FORMATS;return function(e,n){return null==e?e:Kn(e,t.PATTERNS[0],t.GROUP_SEP,t.DECIMAL_SEP,n)}}function Wn(e){var t,n,r,i,o,a=0;for((n=e.indexOf(To))>-1&&(e=e.replace(To,"")),(r=e.search(/e/i))>0?(n<0&&(n=r),n+=+e.slice(r+1),e=e.substring(0,r)):n<0&&(n=e.length),r=0;e.charAt(r)==So;r++);if(r==(o=e.length))t=[0],n=1;else{for(o--;e.charAt(o)==So;)o--;for(n-=r,t=[],i=0;r<=o;r++,i++)t[i]=+e.charAt(r)}return n>Ao&&(t=t.splice(0,Ao-1),a=n-1,n=1),{d:t,e:a,i:n}}function Yn(e,t,n,r){var i=e.d,o=i.length-e.i;t=v(t)?Math.min(Math.max(n,o),r):+t;var a=t+e.i,s=i[a];if(a>0){i.splice(Math.max(e.i,a));for(var c=a;c=5)if(a-1<0){for(var u=0;u>a;u--)i.unshift(0),e.i++;i.unshift(1),e.i++}else i[a-1]++;for(;o0?f=u.splice(d,u.length):(f=u,u=[0]);var h=[];for(u.length>=t.lgSize&&h.unshift(u.splice(-t.lgSize,u.length).join(""));u.length>t.gSize;)h.unshift(u.splice(-t.gSize,u.length).join(""));u.length&&h.unshift(u.join("")),l=h.join(n),f.length&&(l+=r+f.join("")),m&&(l+="e+"+m)}return e<0&&!s?t.negPre+l+t.negSuf:t.posPre+l+t.posSuf}function Gn(e,t,n,r){var i="";for((e<0||r&&e<=0)&&(r?e=-e+1:(e=-e,i="-")),e=""+e;e.length0||a>-n)&&(a+=n),0===a&&n==-12&&(a=12),Gn(a,t,r,i)}}function Xn(e,t,n){return function(r,i){var o=r["get"+e](),a=(n?"STANDALONE":"")+(t?"SHORT":""),s=Or(a+e);return i[s][o]}}function Zn(e,t,n){var r=-1*n,i=r>=0?"+":"";return i+=Gn(Math[r>0?"floor":"ceil"](r/60),2)+Gn(Math.abs(r%60),2)}function Jn(e){var t=new Date(e,0,1).getDay();return new Date(e,0,(t<=4?5:12)-t)}function er(e){return new Date(e.getFullYear(),e.getMonth(),e.getDate()+(4-e.getDay()))}function tr(e){return function(t){var n=Jn(t.getFullYear()),r=er(t),i=+r-+n,o=1+Math.round(i/6048e5);return Gn(o,e)}}function nr(e,t){return e.getHours()<12?t.AMPMS[0]:t.AMPMS[1]}function rr(e,t){return e.getFullYear()<=0?t.ERAS[0]:t.ERAS[1]}function ir(e,t){return e.getFullYear()<=0?t.ERANAMES[0]:t.ERANAMES[1]}function or(e){function t(e){var t;if(t=e.match(n)){var r=new Date(0),i=0,o=0,a=t[8]?r.setUTCFullYear:r.setFullYear,s=t[8]?r.setUTCHours:r.setHours;t[9]&&(i=d(t[9]+t[10]),o=d(t[9]+t[11])),a.call(r,d(t[1]),d(t[2])-1,d(t[3]));var c=d(t[4]||0)-i,l=d(t[5]||0)-o,u=d(t[6]||0),m=Math.round(1e3*parseFloat("0."+(t[7]||0)));return s.call(r,c,l,u,m),r}return e}var n=/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;return function(n,i,o){var a,s,c="",l=[];if(i=i||"mediumDate",i=e.DATETIME_FORMATS[i]||i,E(n)&&(n=Do.test(n)?d(n):t(n)),C(n)&&(n=new Date(n)),!w(n)||!isFinite(n.getTime()))return n;for(;i;)s=No.exec(i),s?(l=U(l,s,1),i=l.pop()):(l.push(i),i=null);var u=n.getTimezoneOffset();return o&&(u=Y(o,u),n=G(n,o,!0)),r(l,function(t){a=_o[t],c+=a?a(n,e.DATETIME_FORMATS,u):"''"===t?"'":t.replace(/(^'|'$)/g,"").replace(/''/g,"'")}),c}}function ar(){return function(e,t){return v(t)&&(t=2),z(e,t)}}function sr(){return function(e,t,r){return t=Math.abs(Number(t))===1/0?Number(t):d(t),isNaN(t)?e:(C(e)&&(e=e.toString()),n(e)?(r=!r||isNaN(r)?0:d(r),r=r<0?Math.max(0,e.length+r):r,t>=0?cr(e,r,r+t):0===r?cr(e,t,e.length):cr(e,Math.max(0,r+t),r)):e)}}function cr(e,t,n){return E(e)?e.slice(t,n):Ur.call(e,t,n)}function lr(e){function r(t){return t.map(function(t){var n=1,r=h;if(x(t))r=t;else if(E(t)&&("+"!=t.charAt(0)&&"-"!=t.charAt(0)||(n="-"==t.charAt(0)?-1:1,t=t.substring(1)),""!==t&&(r=e(t),r.constant))){var i=r();r=function(e){return e[i]}}return{get:r,descending:n}})}function i(e){switch(typeof e){case"number":case"boolean":case"string":return!0;default:return!1}}function o(e){return x(e.valueOf)&&(e=e.valueOf(),i(e))?e:g(e)&&(e=e.toString(),i(e))?e:e}function a(e,t){var n=typeof e;return null===e?(n="string",e="null"):"object"===n&&(e=o(e)),{value:e,type:n,index:t}}function s(e,t){var n=0,r=e.type,i=t.type;if(r===i){var o=e.value,a=t.value;"string"===r?(o=o.toLowerCase(),a=a.toLowerCase()):"object"===r&&($(o)&&(o=e.index),$(a)&&(a=t.index)),o!==a&&(n=o=p},a.$observe("min",function(e){ +p=m(e),s.$validate()})}if(b(a.max)||a.ngMax){var g;s.$validators.max=function(e){return!d(e)||v(g)||n(e)<=g},a.$observe("max",function(e){g=m(e),s.$validate()})}}}function $r(e,t,n,r){var i=t[0],o=r.$$hasNativeValidators=$(i.validity);o&&r.$parsers.push(function(e){var n=t.prop(Nr)||{};return n.badInput||n.typeMismatch?void 0:e})}function yr(e,t,n,r,i,o){if($r(e,t,n,r),pr(e,t,n,r,i,o),r.$$parserName="number",r.$parsers.push(function(e){return r.$isEmpty(e)?null:zo.test(e)?parseFloat(e):void 0}),r.$formatters.push(function(e){if(!r.$isEmpty(e)){if(!C(e))throw Ta("numfmt","Expected `{0}` to be a number",e);e=e.toString()}return e}),b(n.min)||n.ngMin){var a;r.$validators.min=function(e){return r.$isEmpty(e)||v(a)||e>=a},n.$observe("min",function(e){b(e)&&!C(e)&&(e=parseFloat(e)),a=C(e)&&!isNaN(e)?e:void 0,r.$validate()})}if(b(n.max)||n.ngMax){var s;r.$validators.max=function(e){return r.$isEmpty(e)||v(s)||e<=s},n.$observe("max",function(e){b(e)&&!C(e)&&(e=parseFloat(e)),s=C(e)&&!isNaN(e)?e:void 0,r.$validate()})}}function Er(e,t,n,r,i,o){pr(e,t,n,r,i,o),fr(r),r.$$parserName="url",r.$validators.url=function(e,t){var n=e||t;return r.$isEmpty(n)||qo.test(n)}}function Cr(e,t,n,r,i,o){pr(e,t,n,r,i,o),fr(r),r.$$parserName="email",r.$validators.email=function(e,t){var n=e||t;return r.$isEmpty(n)||Bo.test(n)}}function wr(e,t,n,r){v(n.name)&&t.attr("name",a());var i=function(e){t[0].checked&&r.$setViewValue(n.value,e&&e.type)};t.on("click",i),r.$render=function(){var e=n.value;t[0].checked=e==r.$viewValue},n.$observe("value",r.$render)}function xr(e,t,n,r,i){var o;if(b(r)){if(o=e(r),!o.constant)throw Ta("constexpr","Expected constant expression for `{0}`, but saw `{1}`.",n,r);return o(t)}return i}function kr(e,t,n,r,i,o,a,s){var c=xr(s,e,"ngTrueValue",n.ngTrueValue,!0),l=xr(s,e,"ngFalseValue",n.ngFalseValue,!1),u=function(e){r.$setViewValue(t[0].checked,e&&e.type)};t.on("click",u),r.$render=function(){t[0].checked=r.$viewValue},r.$isEmpty=function(e){return e===!1},r.$formatters.push(function(e){return j(e,c)}),r.$parsers.push(function(e){return e?c:l})}function Mr(e,t){return e="ngClass"+e,["$animate",function(n){function i(e,t){var n=[];e:for(var r=0;r0||n[e])&&(n[e]=(n[e]||0)+t,n[e]===+(t>0)&&i.push(e))}),s.data("$classCounts",n),i.join(" ")}function m(e,t){var r=i(t,e),o=i(e,t);r=d(r,1),o=d(o,-1),r&&r.length&&n.addClass(s,r),o&&o.length&&n.removeClass(s,o)}function f(e){if(t===!0||(1&a.$index)===t){var n=o(e||[]);if(h){if(!j(e,h)){var r=o(h);m(r,n)}}else l(n)}h=Gr(e)?e.map(function(e){return ge(e)}):ge(e)}var h;a.$watch(c[e],f,!0),c.$observe("class",function(t){f(a.$eval(c[e]))}),"ngClass"!==e&&a.$watch("$index",function(n,r){var i=1&n;if(i!==(1&r)){var s=o(a.$eval(c[e]));i===t?l(s):u(s)}})}}}]}function Ar(e){function t(e,t,s){v(t)?n("$pending",e,s):r("$pending",e,s),N(t)?t?(u(a.$error,e,s),l(a.$$success,e,s)):(l(a.$error,e,s),u(a.$$success,e,s)):(u(a.$error,e,s),u(a.$$success,e,s)),a.$pending?(i(ka,!0),a.$valid=a.$invalid=void 0,o("",null)):(i(ka,!1),a.$valid=Tr(a.$error),a.$invalid=!a.$valid,o("",a.$valid));var c;c=a.$pending&&a.$pending[e]?void 0:!a.$error[e]&&(!!a.$$success[e]||null),o(e,c),a.$$parentForm.$setValidity(e,c,a)}function n(e,t,n){a[e]||(a[e]={}),l(a[e],t,n)}function r(e,t,n){a[e]&&u(a[e],t,n),Tr(a[e])&&(a[e]=void 0)}function i(e,t){t&&!c[e]?(d.addClass(s,e),c[e]=!0):!t&&c[e]&&(d.removeClass(s,e),c[e]=!1)}function o(e,t){e=e?"-"+se(e,"-"):"",i($a+e,t===!0),i(ya+e,t===!1)}var a=e.ctrl,s=e.$element,c={},l=e.set,u=e.unset,d=e.$animate;c[ya]=!(c[$a]=s.hasClass($a)),a.$setValidity=t}function Tr(e){if(e)for(var t in e)if(e.hasOwnProperty(t))return!1;return!0}function Sr(e){e[0].hasAttribute("selected")&&(e[0].selected=!0)}var _r=/^\/(.+)\/([a-z]*)$/,Nr="validity",Dr=Object.prototype.hasOwnProperty,Ir=function(e){return E(e)?e.toLowerCase():e},Or=function(e){return E(e)?e.toUpperCase():e},Rr=function(e){return E(e)?e.replace(/[A-Z]/g,function(e){return String.fromCharCode(32|e.charCodeAt(0))}):e},Hr=function(e){return E(e)?e.replace(/[a-z]/g,function(e){return String.fromCharCode(e.charCodeAt(0)&-33)}):e};"i"!=="I".toLowerCase()&&(Ir=Rr,Or=Hr);var Pr,Fr,Lr,jr,Ur=[].slice,Vr=[].splice,qr=[].push,Br=Object.prototype.toString,zr=Object.getPrototypeOf,Wr=t("ng"),Yr=e.angular||(e.angular={}),Kr=0;Pr=e.document.documentMode,f.$inject=[],h.$inject=[];var Gr=Array.isArray,Qr=/^\[object (?:Uint8|Uint8Clamped|Uint16|Uint32|Int8|Int16|Int32|Float32|Float64)Array\]$/,Xr=function(e){return E(e)?e.trim():e},Zr=function(e){return e.replace(/([-()\[\]{}+?*.$\^|,:#(?:<\/\1>|)$/,Ei=/<|&#?\w+;/,Ci=/<([\w:-]+)/,wi=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,xi={option:[1,'"],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};xi.optgroup=xi.option,xi.tbody=xi.tfoot=xi.colgroup=xi.caption=xi.thead,xi.th=xi.td;var ki=e.Node.prototype.contains||function(e){return!!(16&this.compareDocumentPosition(e))},Mi=Se.prototype={ready:function(t){function n(){r||(r=!0,t())}var r=!1;"complete"===e.document.readyState?e.setTimeout(n):(this.on("DOMContentLoaded",n),Se(e).on("load",n))},toString:function(){var e=[];return r(this,function(t){e.push(""+t)}),"["+e.join(", ")+"]"},eq:function(e){return Fr(e>=0?this[e]:this[this.length+e])},length:0,push:qr,sort:[].sort,splice:[].splice},Ai={};r("multiple,selected,checked,disabled,readOnly,required,open".split(","),function(e){Ai[Ir(e)]=e});var Ti={};r("input,select,option,textarea,button,form,details".split(","),function(e){Ti[e]=!0});var Si={ngMinlength:"minlength",ngMaxlength:"maxlength",ngMin:"min",ngMax:"max",ngPattern:"pattern"};r({data:Re,removeData:Ie,hasData:xe,cleanData:ke},function(e,t){Se[t]=e}),r({data:Re,inheritedData:Ue,scope:function(e){return Fr.data(e,"$scope")||Ue(e.parentNode||e,["$isolateScope","$scope"])},isolateScope:function(e){return Fr.data(e,"$isolateScope")||Fr.data(e,"$isolateScopeNoTemplate")},controller:je,injector:function(e){return Ue(e,"$injector")},removeAttr:function(e,t){e.removeAttribute(t)},hasClass:He,css:function(e,t,n){return t=Ee(t),b(n)?void(e.style[t]=n):e.style[t]},attr:function(e,t,n){var r=e.nodeType;if(r!==si&&r!==ai&&r!==ci){var i=Ir(t);if(Ai[i]){if(!b(n))return e[t]||(e.attributes.getNamedItem(t)||f).specified?i:void 0;n?(e[t]=!0,e.setAttribute(t,i)):(e[t]=!1,e.removeAttribute(i))}else if(b(n))e.setAttribute(t,n);else if(e.getAttribute){var o=e.getAttribute(t,2);return null===o?void 0:o}}},prop:function(e,t,n){return b(n)?void(e[t]=n):e[t]},text:function(){function e(e,t){if(v(t)){var n=e.nodeType;return n===oi||n===si?e.textContent:""}e.textContent=t}return e.$dv="",e}(),val:function(e,t){if(v(t)){if(e.multiple&&"select"===P(e)){var n=[];return r(e.options,function(e){e.selected&&n.push(e.value||e.text)}),0===n.length?null:n}return e.value}e.value=t},html:function(e,t){return v(t)?e.innerHTML:(Ne(e,!0),void(e.innerHTML=t))},empty:Ve},function(e,t){Se.prototype[t]=function(t,n){var r,i,o=this.length;if(e!==Ve&&v(2==e.length&&e!==He&&e!==je?t:n)){if($(t)){for(r=0;r=0?t.split(" "):[t],c=s.length,l=function(t,r,i){var s=o[t];s||(s=o[t]=[],s.specialHandlerWrapper=r,"$destroy"===t||i||hi(e,t,a)),s.push(n)};c--;)t=s[c],bi[t]?(l(bi[t],Ge),l(t,void 0,!0)):l(t)}},off:De,one:function(e,t,n){e=Fr(e),e.on(t,function r(){e.off(t,n),e.off(t,r)}),e.on(t,n)},replaceWith:function(e,t){var n,i=e.parentNode;Ne(e),r(new Se(t),function(t){n?i.insertBefore(t,n.nextSibling):i.replaceChild(t,e),n=t})},children:function(e){var t=[];return r(e.childNodes,function(e){e.nodeType===oi&&t.push(e)}),t},contents:function(e){return e.contentDocument||e.childNodes||[]},append:function(e,t){var n=e.nodeType;if(n===oi||n===ui){t=new Se(t);for(var r=0,i=t.length;r/,Di=/^[^\(]*\(\s*([^\)]*)\)/m,Ii=/,/,Oi=/^\s*(_?)(\S+?)\1\s*$/,Ri=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm,Hi=t("$injector");rt.$$annotate=nt;var Pi=t("$animate"),Fi=1,Li="ng-animate",ji=function(){this.$get=f},Ui=function(){var e=new Ze,t=[];this.$get=["$$AnimateRunner","$rootScope",function(n,i){function o(e,t,n){var i=!1;return t&&(t=E(t)?t.split(" "):Gr(t)?t:[],r(t,function(t){t&&(i=!0,e[t]=n)})),i}function a(){r(t,function(t){var n=e.get(t);if(n){var i=st(t.attr("class")),o="",a="";r(n,function(e,t){var n=!!i[t];e!==n&&(e?o+=(o.length?" ":"")+t:a+=(a.length?" ":"")+t)}),r(t,function(e){o&&Fe(e,o),a&&Pe(e,a)}),e.remove(t)}}),t.length=0}function s(n,r,s){var c=e.get(n)||{},l=o(c,r,!0),u=o(c,s,!1);(l||u)&&(e.put(n,c),t.push(n),1===t.length&&i.$$postDigest(a))}return{enabled:f,on:f,off:f,pin:f,push:function(e,t,r,i){i&&i(),r=r||{},r.from&&e.css(r.from),r.to&&e.css(r.to),(r.addClass||r.removeClass)&&s(e,r.addClass,r.removeClass);var o=new n;return o.complete(),o}}}]},Vi=["$provide",function(e){var t=this;this.$$registeredAnimations=Object.create(null),this.register=function(n,r){if(n&&"."!==n.charAt(0))throw Pi("notcsel","Expecting class selector starting with '.' got '{0}'.",n);var i=n+"-animation";t.$$registeredAnimations[n.substr(1)]=i,e.factory(i,r)},this.classNameFilter=function(e){if(1===arguments.length&&(this.$$classNameFilter=e instanceof RegExp?e:null,this.$$classNameFilter)){var t=new RegExp("(\\s+|\\/)"+Li+"(\\s+|\\/)");if(t.test(this.$$classNameFilter.toString()))throw Pi("nongcls",'$animateProvider.classNameFilter(regex) prohibits accepting a regex value which matches/contains the "{0}" CSS class.',Li)}return this.$$classNameFilter},this.$get=["$$animateQueue",function(e){function t(e,t,n){if(n){var r=at(n);!r||r.parentNode||r.previousElementSibling||(n=null)}n?n.after(e):t.prepend(e)}return{on:e.on,off:e.off,pin:e.pin,enabled:e.enabled,cancel:function(e){e.end&&e.end()},enter:function(n,r,i,o){return r=r&&Fr(r),i=i&&Fr(i),r=r||i.parent(),t(n,r,i),e.push(n,"enter",ct(o))},move:function(n,r,i,o){return r=r&&Fr(r),i=i&&Fr(i),r=r||i.parent(),t(n,r,i),e.push(n,"move",ct(o))},leave:function(t,n){return e.push(t,"leave",ct(n),function(){t.remove()})},addClass:function(t,n,r){return r=ct(r),r.addClass=ot(r.addclass,n),e.push(t,"addClass",r)},removeClass:function(t,n,r){return r=ct(r),r.removeClass=ot(r.removeClass,n),e.push(t,"removeClass",r)},setClass:function(t,n,r,i){return i=ct(i),i.addClass=ot(i.addClass,n),i.removeClass=ot(i.removeClass,r),e.push(t,"setClass",i)},animate:function(t,n,r,i,o){return o=ct(o),o.from=o.from?l(o.from,n):n,o.to=o.to?l(o.to,r):r,i=i||"ng-inline-animate",o.tempClasses=ot(o.tempClasses,i),e.push(t,"animate",o)}}}]}],qi=function(){this.$get=["$$rAF",function(e){function t(t){n.push(t),n.length>1||e(function(){for(var e=0;e <= >= && || ! = |".split(" "),function(e){go[e]=!0});var vo={n:"\n",f:"\f",r:"\r",t:"\t",v:"\x0B","'":"'",'"':'"'},bo=function(e){this.options=e};bo.prototype={constructor:bo,lex:function(e){for(this.text=e,this.index=0,this.tokens=[];this.index=55296&&n<=56319&&r>=56320&&r<=57343?e+t:e},isExpOperator:function(e){return"-"===e||"+"===e||this.isNumber(e)},throwError:function(e,t,n){n=n||this.index;var r=b(t)?"s "+t+"-"+this.index+" ["+this.text.substring(t,n)+"]":" "+n;throw mo("lexerr","Lexer Error: {0} at column{1} in expression [{2}].",e,r,this.text)},readNumber:function(){for(var e="",t=this.index;this.index0&&!this.peek("}",")",";","]")&&e.push(this.expressionStatement()),!this.expect(";"))return{type:$o.Program,body:e}},expressionStatement:function(){return{type:$o.ExpressionStatement,expression:this.filterChain()}},filterChain:function(){for(var e,t=this.expression();e=this.expect("|");)t=this.filter(t);return t},expression:function(){return this.assignment()},assignment:function(){var e=this.ternary();return this.expect("=")&&(e={type:$o.AssignmentExpression,left:e,right:this.assignment(),operator:"="}),e},ternary:function(){var e,t,n=this.logicalOR();return this.expect("?")&&(e=this.expression(),this.consume(":"))?(t=this.expression(),{type:$o.ConditionalExpression,test:n,alternate:e,consequent:t}):n},logicalOR:function(){for(var e=this.logicalAND();this.expect("||");)e={type:$o.LogicalExpression,operator:"||",left:e,right:this.logicalAND()};return e},logicalAND:function(){for(var e=this.equality();this.expect("&&");)e={type:$o.LogicalExpression,operator:"&&",left:e,right:this.equality()};return e},equality:function(){for(var e,t=this.relational();e=this.expect("==","!=","===","!==");)t={type:$o.BinaryExpression,operator:e.text,left:t,right:this.relational()};return t},relational:function(){for(var e,t=this.additive();e=this.expect("<",">","<=",">=");)t={type:$o.BinaryExpression,operator:e.text,left:t,right:this.additive()};return t},additive:function(){for(var e,t=this.multiplicative();e=this.expect("+","-");)t={type:$o.BinaryExpression,operator:e.text,left:t,right:this.multiplicative()};return t},multiplicative:function(){for(var e,t=this.unary();e=this.expect("*","/","%");)t={type:$o.BinaryExpression,operator:e.text,left:t,right:this.unary()};return t},unary:function(){var e;return(e=this.expect("+","-","!"))?{type:$o.UnaryExpression,operator:e.text,prefix:!0,argument:this.unary()}:this.primary()},primary:function(){var e;this.expect("(")?(e=this.filterChain(),this.consume(")")):this.expect("[")?e=this.arrayDeclaration():this.expect("{")?e=this.object():this.selfReferential.hasOwnProperty(this.peek().text)?e=L(this.selfReferential[this.consume().text]):this.options.literals.hasOwnProperty(this.peek().text)?e={type:$o.Literal,value:this.options.literals[this.consume().text]}:this.peek().identifier?e=this.identifier():this.peek().constant?e=this.constant():this.throwError("not a primary expression",this.peek());for(var t;t=this.expect("(","[",".");)"("===t.text?(e={type:$o.CallExpression,callee:e,arguments:this.parseArguments()},this.consume(")")):"["===t.text?(e={type:$o.MemberExpression,object:e,property:this.expression(),computed:!0},this.consume("]")):"."===t.text?e={type:$o.MemberExpression,object:e,property:this.identifier(),computed:!1}:this.throwError("IMPOSSIBLE");return e},filter:function(e){for(var t=[e],n={type:$o.CallExpression,callee:this.identifier(),arguments:t,filter:!0};this.expect(":");)t.push(this.expression());return n},parseArguments:function(){var e=[];if(")"!==this.peekToken().text)do e.push(this.filterChain());while(this.expect(","));return e},identifier:function(){var e=this.consume();return e.identifier||this.throwError("is not a valid identifier",e),{type:$o.Identifier,name:e.text}},constant:function(){return{type:$o.Literal,value:this.consume().value}},arrayDeclaration:function(){var e=[];if("]"!==this.peekToken().text)do{if(this.peek("]"))break;e.push(this.expression())}while(this.expect(","));return this.consume("]"),{type:$o.ArrayExpression,elements:e}},object:function(){var e,t=[];if("}"!==this.peekToken().text)do{if(this.peek("}"))break;e={type:$o.Property,kind:"init"},this.peek().constant?(e.key=this.constant(),e.computed=!1,this.consume(":"),e.value=this.expression()):this.peek().identifier?(e.key=this.identifier(),e.computed=!1,this.peek(":")?(this.consume(":"),e.value=this.expression()):e.value=e.key):this.peek("[")?(this.consume("["),e.key=this.expression(),this.consume("]"),e.computed=!0,this.consume(":"),e.value=this.expression()):this.throwError("invalid key",this.peek()),t.push(e)}while(this.expect(","));return this.consume("}"),{type:$o.ObjectExpression,properties:t}},throwError:function(e,t){throw mo("syntax","Syntax Error: Token '{0}' {1} at column {2} of the expression [{3}] starting at [{4}].",t.text,e,t.index+1,this.text,this.text.substring(t.index))},consume:function(e){if(0===this.tokens.length)throw mo("ueoe","Unexpected end of expression: {0}",this.text);var t=this.expect(e);return t||this.throwError("is unexpected, expecting ["+e+"]",this.peek()),t},peekToken:function(){if(0===this.tokens.length)throw mo("ueoe","Unexpected end of expression: {0}",this.text);return this.tokens[0]},peek:function(e,t,n,r){return this.peekAhead(0,e,t,n,r)},peekAhead:function(e,t,n,r,i){if(this.tokens.length>e){var o=this.tokens[e],a=o.text;if(a===t||a===n||a===r||a===i||!t&&!n&&!r&&!i)return o}return!1},expect:function(e,t,n,r){var i=this.peek(e,t,n,r);return!!i&&(this.tokens.shift(),i)},selfReferential:{"this":{type:$o.ThisExpression},$locals:{type:$o.LocalsExpression}}},pn.prototype={compile:function(e,t){var n=this,i=this.astBuilder.ast(e);this.state={nextId:0,filters:{},expensiveChecks:t,fn:{vars:[],body:[],own:{}},assign:{vars:[],body:[],own:{}},inputs:[]},ln(i,n.$filter);var o,a="";if(this.stage="assign",o=mn(i)){this.state.computing="assign";var s=this.nextId();this.recurse(o,s),this.return_(s),a="fn.assign="+this.generateFunction("assign","s,v,l")}var c=un(i.body);n.stage="inputs",r(c,function(e,t){var r="fn"+t;n.state[r]={vars:[],body:[],own:{}},n.state.computing=r;var i=n.nextId();n.recurse(e,i),n.return_(i),n.state.inputs.push(r),e.watchId=t}),this.state.computing="fn",this.stage="main",this.recurse(i);var l='"'+this.USE+" "+this.STRICT+'";\n'+this.filterPrefix()+"var fn="+this.generateFunction("fn","s,l,a,i")+a+this.watchFns()+"return fn;",u=new Function("$filter","ensureSafeMemberName","ensureSafeObject","ensureSafeFunction","getStringValue","ensureSafeAssignContext","ifDefined","plus","text",l)(this.$filter,en,nn,rn,tn,on,an,sn,e);return this.state=this.stage=void 0,u.literal=fn(i),u.constant=hn(i),u},USE:"use",STRICT:"strict",watchFns:function(){var e=[],t=this.state.inputs,n=this;return r(t,function(t){e.push("var "+t+"="+n.generateFunction(t,"s"))}),t.length&&e.push("fn.inputs=["+t.join(",")+"];"),e.join("")},generateFunction:function(e,t){return"function("+t+"){"+this.varsPrefix(e)+this.body(e)+"};"},filterPrefix:function(){var e=[],t=this;return r(this.state.filters,function(n,r){e.push(n+"=$filter("+t.escape(r)+")")}),e.length?"var "+e.join(",")+";":""},varsPrefix:function(e){return this.state[e].vars.length?"var "+this.state[e].vars.join(",")+";":""},body:function(e){return this.state[e].body.join("")},recurse:function(e,t,n,i,o,a){var s,c,l,u,d,m=this;if(i=i||f,!a&&b(e.watchId))return t=t||this.nextId(),void this.if_("i",this.lazyAssign(t,this.computedMember("i",e.watchId)),this.lazyRecurse(e,t,n,i,o,!0));switch(e.type){case $o.Program:r(e.body,function(t,n){m.recurse(t.expression,void 0,void 0,function(e){c=e}),n!==e.body.length-1?m.current().body.push(c,";"):m.return_(c)});break;case $o.Literal:u=this.escape(e.value),this.assign(t,u),i(u);break;case $o.UnaryExpression:this.recurse(e.argument,void 0,void 0,function(e){c=e}),u=e.operator+"("+this.ifDefined(c,0)+")",this.assign(t,u),i(u);break;case $o.BinaryExpression:this.recurse(e.left,void 0,void 0,function(e){s=e}),this.recurse(e.right,void 0,void 0,function(e){c=e}),u="+"===e.operator?this.plus(s,c):"-"===e.operator?this.ifDefined(s,0)+e.operator+this.ifDefined(c,0):"("+s+")"+e.operator+"("+c+")",this.assign(t,u),i(u);break;case $o.LogicalExpression:t=t||this.nextId(),m.recurse(e.left,t),m.if_("&&"===e.operator?t:m.not(t),m.lazyRecurse(e.right,t)),i(t);break;case $o.ConditionalExpression:t=t||this.nextId(),m.recurse(e.test,t),m.if_(t,m.lazyRecurse(e.alternate,t),m.lazyRecurse(e.consequent,t)),i(t);break;case $o.Identifier:t=t||this.nextId(),n&&(n.context="inputs"===m.stage?"s":this.assign(this.nextId(),this.getHasOwnProperty("l",e.name)+"?l:s"),n.computed=!1,n.name=e.name),en(e.name),m.if_("inputs"===m.stage||m.not(m.getHasOwnProperty("l",e.name)),function(){ +m.if_("inputs"===m.stage||"s",function(){o&&1!==o&&m.if_(m.not(m.nonComputedMember("s",e.name)),m.lazyAssign(m.nonComputedMember("s",e.name),"{}")),m.assign(t,m.nonComputedMember("s",e.name))})},t&&m.lazyAssign(t,m.nonComputedMember("l",e.name))),(m.state.expensiveChecks||vn(e.name))&&m.addEnsureSafeObject(t),i(t);break;case $o.MemberExpression:s=n&&(n.context=this.nextId())||this.nextId(),t=t||this.nextId(),m.recurse(e.object,s,void 0,function(){m.if_(m.notNull(s),function(){o&&1!==o&&m.addEnsureSafeAssignContext(s),e.computed?(c=m.nextId(),m.recurse(e.property,c),m.getStringValue(c),m.addEnsureSafeMemberName(c),o&&1!==o&&m.if_(m.not(m.computedMember(s,c)),m.lazyAssign(m.computedMember(s,c),"{}")),u=m.ensureSafeObject(m.computedMember(s,c)),m.assign(t,u),n&&(n.computed=!0,n.name=c)):(en(e.property.name),o&&1!==o&&m.if_(m.not(m.nonComputedMember(s,e.property.name)),m.lazyAssign(m.nonComputedMember(s,e.property.name),"{}")),u=m.nonComputedMember(s,e.property.name),(m.state.expensiveChecks||vn(e.property.name))&&(u=m.ensureSafeObject(u)),m.assign(t,u),n&&(n.computed=!1,n.name=e.property.name))},function(){m.assign(t,"undefined")}),i(t)},!!o);break;case $o.CallExpression:t=t||this.nextId(),e.filter?(c=m.filter(e.callee.name),l=[],r(e.arguments,function(e){var t=m.nextId();m.recurse(e,t),l.push(t)}),u=c+"("+l.join(",")+")",m.assign(t,u),i(t)):(c=m.nextId(),s={},l=[],m.recurse(e.callee,c,s,function(){m.if_(m.notNull(c),function(){m.addEnsureSafeFunction(c),r(e.arguments,function(e){m.recurse(e,m.nextId(),void 0,function(e){l.push(m.ensureSafeObject(e))})}),s.name?(m.state.expensiveChecks||m.addEnsureSafeObject(s.context),u=m.member(s.context,s.name,s.computed)+"("+l.join(",")+")"):u=c+"("+l.join(",")+")",u=m.ensureSafeObject(u),m.assign(t,u)},function(){m.assign(t,"undefined")}),i(t)}));break;case $o.AssignmentExpression:if(c=this.nextId(),s={},!dn(e.left))throw mo("lval","Trying to assign a value to a non l-value");this.recurse(e.left,void 0,s,function(){m.if_(m.notNull(s.context),function(){m.recurse(e.right,c),m.addEnsureSafeObject(m.member(s.context,s.name,s.computed)),m.addEnsureSafeAssignContext(s.context),u=m.member(s.context,s.name,s.computed)+e.operator+c,m.assign(t,u),i(t||u)})},1);break;case $o.ArrayExpression:l=[],r(e.elements,function(e){m.recurse(e,m.nextId(),void 0,function(e){l.push(e)})}),u="["+l.join(",")+"]",this.assign(t,u),i(u);break;case $o.ObjectExpression:l=[],d=!1,r(e.properties,function(e){e.computed&&(d=!0)}),d?(t=t||this.nextId(),this.assign(t,"{}"),r(e.properties,function(e){e.computed?(s=m.nextId(),m.recurse(e.key,s)):s=e.key.type===$o.Identifier?e.key.name:""+e.key.value,c=m.nextId(),m.recurse(e.value,c),m.assign(m.member(t,s,e.computed),c)})):(r(e.properties,function(t){m.recurse(t.value,e.constant?void 0:m.nextId(),void 0,function(e){l.push(m.escape(t.key.type===$o.Identifier?t.key.name:""+t.key.value)+":"+e)})}),u="{"+l.join(",")+"}",this.assign(t,u)),i(t||u);break;case $o.ThisExpression:this.assign(t,"s"),i("s");break;case $o.LocalsExpression:this.assign(t,"l"),i("l");break;case $o.NGValueParameter:this.assign(t,"v"),i("v")}},getHasOwnProperty:function(e,t){var n=e+"."+t,r=this.current().own;return r.hasOwnProperty(n)||(r[n]=this.nextId(!1,e+"&&("+this.escape(t)+" in "+e+")")),r[n]},assign:function(e,t){if(e)return this.current().body.push(e,"=",t,";"),e},filter:function(e){return this.state.filters.hasOwnProperty(e)||(this.state.filters[e]=this.nextId(!0)),this.state.filters[e]},ifDefined:function(e,t){return"ifDefined("+e+","+this.escape(t)+")"},plus:function(e,t){return"plus("+e+","+t+")"},return_:function(e){this.current().body.push("return ",e,";")},if_:function(e,t,n){if(e===!0)t();else{var r=this.current().body;r.push("if(",e,"){"),t(),r.push("}"),n&&(r.push("else{"),n(),r.push("}"))}},not:function(e){return"!("+e+")"},notNull:function(e){return e+"!=null"},nonComputedMember:function(e,t){var n=/[$_a-zA-Z][$_a-zA-Z0-9]*/,r=/[^$_a-zA-Z0-9]/g;return n.test(t)?e+"."+t:e+'["'+t.replace(r,this.stringEscapeFn)+'"]'},computedMember:function(e,t){return e+"["+t+"]"},member:function(e,t,n){return n?this.computedMember(e,t):this.nonComputedMember(e,t)},addEnsureSafeObject:function(e){this.current().body.push(this.ensureSafeObject(e),";")},addEnsureSafeMemberName:function(e){this.current().body.push(this.ensureSafeMemberName(e),";")},addEnsureSafeFunction:function(e){this.current().body.push(this.ensureSafeFunction(e),";")},addEnsureSafeAssignContext:function(e){this.current().body.push(this.ensureSafeAssignContext(e),";")},ensureSafeObject:function(e){return"ensureSafeObject("+e+",text)"},ensureSafeMemberName:function(e){return"ensureSafeMemberName("+e+",text)"},ensureSafeFunction:function(e){return"ensureSafeFunction("+e+",text)"},getStringValue:function(e){this.assign(e,"getStringValue("+e+")")},ensureSafeAssignContext:function(e){return"ensureSafeAssignContext("+e+",text)"},lazyRecurse:function(e,t,n,r,i,o){var a=this;return function(){a.recurse(e,t,n,r,i,o)}},lazyAssign:function(e,t){var n=this;return function(){n.assign(e,t)}},stringEscapeRegex:/[^ a-zA-Z0-9]/g,stringEscapeFn:function(e){return"\\u"+("0000"+e.charCodeAt(0).toString(16)).slice(-4)},escape:function(e){if(E(e))return"'"+e.replace(this.stringEscapeRegex,this.stringEscapeFn)+"'";if(C(e))return e.toString();if(e===!0)return"true";if(e===!1)return"false";if(null===e)return"null";if("undefined"==typeof e)return"undefined";throw mo("esc","IMPOSSIBLE")},nextId:function(e,t){var n="v"+this.state.nextId++;return e||this.current().vars.push(n+(t?"="+t:"")),n},current:function(){return this.state[this.state.computing]}},gn.prototype={compile:function(e,t){var n=this,i=this.astBuilder.ast(e);this.expression=e,this.expensiveChecks=t,ln(i,n.$filter);var o,a;(o=mn(i))&&(a=this.recurse(o));var s,c=un(i.body);c&&(s=[],r(c,function(e,t){var r=n.recurse(e);e.input=r,s.push(r),e.watchId=t}));var l=[];r(i.body,function(e){l.push(n.recurse(e.expression))});var u=0===i.body.length?f:1===i.body.length?l[0]:function(e,t){var n;return r(l,function(r){n=r(e,t)}),n};return a&&(u.assign=function(e,t,n){return a(e,n,t)}),s&&(u.inputs=s),u.literal=fn(i),u.constant=hn(i),u},recurse:function(e,t,n){var i,o,a,s=this;if(e.input)return this.inputs(e.input,e.watchId);switch(e.type){case $o.Literal:return this.value(e.value,t);case $o.UnaryExpression:return o=this.recurse(e.argument),this["unary"+e.operator](o,t);case $o.BinaryExpression:return i=this.recurse(e.left),o=this.recurse(e.right),this["binary"+e.operator](i,o,t);case $o.LogicalExpression:return i=this.recurse(e.left),o=this.recurse(e.right),this["binary"+e.operator](i,o,t);case $o.ConditionalExpression:return this["ternary?:"](this.recurse(e.test),this.recurse(e.alternate),this.recurse(e.consequent),t);case $o.Identifier:return en(e.name,s.expression),s.identifier(e.name,s.expensiveChecks||vn(e.name),t,n,s.expression);case $o.MemberExpression:return i=this.recurse(e.object,!1,!!n),e.computed||(en(e.property.name,s.expression),o=e.property.name),e.computed&&(o=this.recurse(e.property)),e.computed?this.computedMember(i,o,t,n,s.expression):this.nonComputedMember(i,o,s.expensiveChecks,t,n,s.expression);case $o.CallExpression:return a=[],r(e.arguments,function(e){a.push(s.recurse(e))}),e.filter&&(o=this.$filter(e.callee.name)),e.filter||(o=this.recurse(e.callee,!0)),e.filter?function(e,n,r,i){for(var s=[],c=0;c":function(e,t,n){return function(r,i,o,a){var s=e(r,i,o,a)>t(r,i,o,a);return n?{value:s}:s}},"binary<=":function(e,t,n){return function(r,i,o,a){var s=e(r,i,o,a)<=t(r,i,o,a);return n?{value:s}:s}},"binary>=":function(e,t,n){return function(r,i,o,a){var s=e(r,i,o,a)>=t(r,i,o,a);return n?{value:s}:s}},"binary&&":function(e,t,n){return function(r,i,o,a){var s=e(r,i,o,a)&&t(r,i,o,a);return n?{value:s}:s}},"binary||":function(e,t,n){return function(r,i,o,a){var s=e(r,i,o,a)||t(r,i,o,a);return n?{value:s}:s}},"ternary?:":function(e,t,n,r){return function(i,o,a,s){var c=e(i,o,a,s)?t(i,o,a,s):n(i,o,a,s);return r?{value:c}:c}},value:function(e,t){return function(){return t?{context:void 0,name:void 0,value:e}:e}},identifier:function(e,t,n,r,i){return function(o,a,s,c){var l=a&&e in a?a:o;r&&1!==r&&l&&!l[e]&&(l[e]={});var u=l?l[e]:void 0;return t&&nn(u,i),n?{context:l,name:e,value:u}:u}},computedMember:function(e,t,n,r,i){return function(o,a,s,c){var l,u,d=e(o,a,s,c);return null!=d&&(l=t(o,a,s,c),l=tn(l),en(l,i),r&&1!==r&&(on(d),d&&!d[l]&&(d[l]={})),u=d[l],nn(u,i)),n?{context:d,name:l,value:u}:u}},nonComputedMember:function(e,t,n,r,i,o){return function(a,s,c,l){var u=e(a,s,c,l);i&&1!==i&&(on(u),u&&!u[t]&&(u[t]={}));var d=null!=u?u[t]:void 0;return(n||vn(t))&&nn(d,o),r?{context:u,name:t,value:d}:d}},inputs:function(e,t){return function(n,r,i,o){return o?o[t]:e(n,r,i)}}};var yo=function(e,t,n){this.lexer=e,this.$filter=t,this.options=n,this.ast=new $o(e,n),this.astCompiler=n.csp?new gn(this.ast,t):new pn(this.ast,t)};yo.prototype={constructor:yo,parse:function(e){return this.astCompiler.compile(e,this.options.expensiveChecks)}};var Eo=Object.prototype.valueOf,Co=t("$sce"),wo={HTML:"html",CSS:"css",URL:"url",RESOURCE_URL:"resourceUrl",JS:"js"},xo=t("$compile"),ko=e.document.createElement("a"),Mo=On(e.location.href);Pn.$inject=["$document"],Ln.$inject=["$provide"];var Ao=22,To=".",So="0";Bn.$inject=["$locale"],zn.$inject=["$locale"];var _o={yyyy:Qn("FullYear",4,0,!1,!0),yy:Qn("FullYear",2,0,!0,!0),y:Qn("FullYear",1,0,!1,!0),MMMM:Xn("Month"),MMM:Xn("Month",!0),MM:Qn("Month",2,1),M:Qn("Month",1,1),LLLL:Xn("Month",!1,!0),dd:Qn("Date",2),d:Qn("Date",1),HH:Qn("Hours",2),H:Qn("Hours",1),hh:Qn("Hours",2,-12),h:Qn("Hours",1,-12),mm:Qn("Minutes",2),m:Qn("Minutes",1),ss:Qn("Seconds",2),s:Qn("Seconds",1),sss:Qn("Milliseconds",3),EEEE:Xn("Day"),EEE:Xn("Day",!0),a:nr,Z:Zn,ww:tr(2),w:tr(1),G:rr,GG:rr,GGG:rr,GGGG:ir},No=/((?:[^yMLdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|L+|d+|H+|h+|m+|s+|a|Z|G+|w+))(.*)/,Do=/^\-?\d+$/;or.$inject=["$locale"];var Io=p(Ir),Oo=p(Or);lr.$inject=["$parse"];var Ro=p({restrict:"E",compile:function(e,t){if(!t.href&&!t.xlinkHref)return function(e,t){if("a"===t[0].nodeName.toLowerCase()){var n="[object SVGAnimatedString]"===Br.call(t.prop("href"))?"xlink:href":"href";t.on("click",function(e){t.attr(n)||e.preventDefault()})}}}}),Ho={};r(Ai,function(e,t){function n(e,n,i){e.$watch(i[r],function(e){i.$set(t,!!e)})}if("multiple"!=e){var r=gt("ng-"+t),i=n;"checked"===e&&(i=function(e,t,i){i.ngModel!==i[r]&&n(e,t,i)}),Ho[r]=function(){return{restrict:"A",priority:100,link:i}}}}),r(Si,function(e,t){Ho[t]=function(){return{priority:100,link:function(e,n,r){if("ngPattern"===t&&"/"==r.ngPattern.charAt(0)){var i=r.ngPattern.match(_r);if(i)return void r.$set("ngPattern",new RegExp(i[1],i[2]))}e.$watch(r[t],function(e){r.$set(t,e)})}}}}),r(["src","srcset","href"],function(e){var t=gt("ng-"+e);Ho[t]=function(){return{priority:99,link:function(n,r,i){var o=e,a=e;"href"===e&&"[object SVGAnimatedString]"===Br.call(r.prop("href"))&&(a="xlinkHref",i.$attr[a]="xlink:href",o=null),i.$observe(t,function(t){return t?(i.$set(a,t),void(Pr&&o&&r.prop(o,i[a]))):void("href"===e&&i.$set(a,null))})}}}});var Po={$addControl:f,$$renameControl:dr,$removeControl:f,$setValidity:f,$setDirty:f,$setPristine:f,$setSubmitted:f},Fo="ng-submitted";mr.$inject=["$element","$attrs","$scope","$animate","$interpolate"];var Lo=function(e){return["$timeout","$parse",function(t,n){function r(e){return""===e?n('this[""]').assign:n(e).assign||f}var i={name:"form",restrict:e?"EAC":"E",require:["form","^^?form"],controller:mr,compile:function(n,i){n.addClass(Ea).addClass($a);var o=i.name?"name":!(!e||!i.ngForm)&&"ngForm";return{pre:function(e,n,i,a){var s=a[0];if(!("action"in i)){var c=function(t){e.$apply(function(){s.$commitViewValue(),s.$setSubmitted()}),t.preventDefault()};hi(n[0],"submit",c),n.on("$destroy",function(){t(function(){pi(n[0],"submit",c)},0,!1)})}var u=a[1]||s.$$parentForm;u.$addControl(s);var d=o?r(s.$name):f;o&&(d(e,s),i.$observe(o,function(t){s.$name!==t&&(d(e,void 0),s.$$parentForm.$$renameControl(s,t),(d=r(s.$name))(e,s))})),n.on("$destroy",function(){s.$$parentForm.$removeControl(s),d(e,void 0),l(s,Po)})}}}};return i}]},jo=Lo(),Uo=Lo(!0),Vo=/^\d{4,}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+(?:[+-][0-2]\d:[0-5]\d|Z)$/,qo=/^[a-z][a-z\d.+-]*:\/*(?:[^:@]+(?::[^@]+)?@)?(?:[^\s:\/?#]+|\[[a-f\d:]+\])(?::\d+)?(?:\/[^?#]*)?(?:\?[^#]*)?(?:#.*)?$/i,Bo=/^(?=.{1,254}$)(?=.{1,64}@)[-!#$%&'*+\/0-9=?A-Z^_`a-z{|}~]+(\.[-!#$%&'*+\/0-9=?A-Z^_`a-z{|}~]+)*@[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$/,zo=/^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/,Wo=/^(\d{4,})-(\d{2})-(\d{2})$/,Yo=/^(\d{4,})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,Ko=/^(\d{4,})-W(\d\d)$/,Go=/^(\d{4,})-(\d\d)$/,Qo=/^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,Xo="keydown wheel mousedown",Zo=he();r("date,datetime-local,month,time,week".split(","),function(e){Zo[e]=!0});var Jo={text:hr,date:br("date",Wo,vr(Wo,["yyyy","MM","dd"]),"yyyy-MM-dd"),"datetime-local":br("datetimelocal",Yo,vr(Yo,["yyyy","MM","dd","HH","mm","ss","sss"]),"yyyy-MM-ddTHH:mm:ss.sss"),time:br("time",Qo,vr(Qo,["HH","mm","ss","sss"]),"HH:mm:ss.sss"),week:br("week",Ko,gr,"yyyy-Www"),month:br("month",Go,vr(Go,["yyyy","MM"]),"yyyy-MM"),number:yr,url:Er,email:Cr,radio:wr,checkbox:kr,hidden:f,button:f,submit:f,reset:f,file:f},ea=["$browser","$sniffer","$filter","$parse",function(e,t,n,r){return{restrict:"E",require:["?ngModel"],link:{pre:function(i,o,a,s){s[0]&&(Jo[Ir(a.type)]||Jo.text)(i,o,a,s[0],t,e,n,r)}}}}],ta=/^(true|false|\d+)$/,na=function(){return{restrict:"A",priority:100,compile:function(e,t){return ta.test(t.ngValue)?function(e,t,n){n.$set("value",e.$eval(n.ngValue))}:function(e,t,n){e.$watch(n.ngValue,function(e){n.$set("value",e)})}}}},ra=["$compile",function(e){return{restrict:"AC",compile:function(t){return e.$$addBindingClass(t),function(t,n,r){e.$$addBindingInfo(n,r.ngBind),n=n[0],t.$watch(r.ngBind,function(e){n.textContent=v(e)?"":e})}}}}],ia=["$interpolate","$compile",function(e,t){return{compile:function(n){return t.$$addBindingClass(n),function(n,r,i){var o=e(r.attr(i.$attr.ngBindTemplate));t.$$addBindingInfo(r,o.expressions),r=r[0],i.$observe("ngBindTemplate",function(e){r.textContent=v(e)?"":e})}}}}],oa=["$sce","$parse","$compile",function(e,t,n){return{restrict:"A",compile:function(r,i){var o=t(i.ngBindHtml),a=t(i.ngBindHtml,function(t){return e.valueOf(t)});return n.$$addBindingClass(r),function(t,r,i){n.$$addBindingInfo(r,i.ngBindHtml),t.$watch(a,function(){var n=o(t);r.html(e.getTrustedHtml(n)||"")})}}}}],aa=p({restrict:"A",require:"ngModel",link:function(e,t,n,r){r.$viewChangeListeners.push(function(){e.$eval(n.ngChange)})}}),sa=Mr("",!0),ca=Mr("Odd",0),la=Mr("Even",1),ua=ur({compile:function(e,t){t.$set("ngCloak",void 0),e.removeClass("ng-cloak")}}),da=[function(){return{restrict:"A",scope:!0,controller:"@",priority:500}}],ma={},fa={blur:!0,focus:!0};r("click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste".split(" "),function(e){var t=gt("ng-"+e);ma[t]=["$parse","$rootScope",function(n,r){return{restrict:"A",compile:function(i,o){var a=n(o[t],null,!0);return function(t,n){n.on(e,function(n){var i=function(){a(t,{$event:n})};fa[e]&&r.$$phase?t.$evalAsync(i):t.$apply(i)})}}}}]});var ha=["$animate","$compile",function(e,t){return{multiElement:!0,transclude:"element",priority:600,terminal:!0,restrict:"A",$$tlb:!0,link:function(n,r,i,o,a){var s,c,l;n.$watch(i.ngIf,function(n){n?c||a(function(n,o){c=o,n[n.length++]=t.$$createComment("end ngIf",i.ngIf),s={clone:n},e.enter(n,r.parent(),r)}):(l&&(l.remove(),l=null),c&&(c.$destroy(),c=null),s&&(l=fe(s.clone),e.leave(l).then(function(){l=null}),s=null))})}}}],pa=["$templateRequest","$anchorScroll","$animate",function(e,t,n){return{restrict:"ECA",priority:400,terminal:!0,transclude:"element",controller:Yr.noop,compile:function(r,i){var o=i.ngInclude||i.src,a=i.onload||"",s=i.autoscroll;return function(r,i,c,l,u){var d,m,f,h=0,p=function(){m&&(m.remove(),m=null),d&&(d.$destroy(),d=null),f&&(n.leave(f).then(function(){m=null}),m=f,f=null)};r.$watch(o,function(o){var c=function(){!b(s)||s&&!r.$eval(s)||t()},m=++h;o?(e(o,!0).then(function(e){if(!r.$$destroyed&&m===h){var t=r.$new();l.template=e;var s=u(t,function(e){p(),n.enter(e,null,i).then(c)});d=t,f=s,d.$emit("$includeContentLoaded",o),r.$eval(a)}},function(){r.$$destroyed||m===h&&(p(),r.$emit("$includeContentError",o))}),r.$emit("$includeContentRequested",o)):(p(),l.template=null)})}}}}],ga=["$compile",function(t){return{restrict:"ECA",priority:-400,require:"ngInclude",link:function(n,r,i,o){return Br.call(r[0]).match(/SVG/)?(r.empty(),void t(Me(o.template,e.document).childNodes)(n,function(e){r.append(e)},{futureParentElement:r})):(r.html(o.template),void t(r.contents())(n))}}}],va=ur({priority:450,compile:function(){return{pre:function(e,t,n){e.$eval(n.ngInit)}}}}),ba=function(){return{restrict:"A",priority:100,require:"ngModel",link:function(e,t,n,i){var o=t.attr(n.$attr.ngList)||", ",a="false"!==n.ngTrim,s=a?Xr(o):o,c=function(e){if(!v(e)){var t=[];return e&&r(e.split(s),function(e){e&&t.push(a?Xr(e):e)}),t}};i.$parsers.push(c),i.$formatters.push(function(e){if(Gr(e))return e.join(o)}),i.$isEmpty=function(e){return!e||!e.length}}}},$a="ng-valid",ya="ng-invalid",Ea="ng-pristine",Ca="ng-dirty",wa="ng-untouched",xa="ng-touched",ka="ng-pending",Ma="ng-empty",Aa="ng-not-empty",Ta=t("ngModel"),Sa=["$scope","$exceptionHandler","$attrs","$element","$parse","$animate","$timeout","$rootScope","$q","$interpolate",function(e,t,n,i,o,a,s,c,l,u){this.$viewValue=Number.NaN,this.$modelValue=Number.NaN,this.$$rawModelValue=void 0,this.$validators={},this.$asyncValidators={},this.$parsers=[],this.$formatters=[],this.$viewChangeListeners=[],this.$untouched=!0,this.$touched=!1,this.$pristine=!0,this.$dirty=!1,this.$valid=!0,this.$invalid=!1,this.$error={},this.$$success={},this.$pending=void 0,this.$name=u(n.name||"",!1)(e),this.$$parentForm=Po;var d,m=o(n.ngModel),h=m.assign,p=m,g=h,$=null,y=this;this.$$setOptions=function(e){if(y.$options=e,e&&e.getterSetter){var t=o(n.ngModel+"()"),r=o(n.ngModel+"($$$p)");p=function(e){var n=m(e);return x(n)&&(n=t(e)),n},g=function(e,t){x(m(e))?r(e,{$$$p:t}):h(e,t)}}else if(!m.assign)throw Ta("nonassign","Expression '{0}' is non-assignable. Element: {1}",n.ngModel,Q(i))},this.$render=f,this.$isEmpty=function(e){return v(e)||""===e||null===e||e!==e},this.$$updateEmptyClasses=function(e){y.$isEmpty(e)?(a.removeClass(i,Aa),a.addClass(i,Ma)):(a.removeClass(i,Ma),a.addClass(i,Aa))};var E=0;Ar({ctrl:this,$element:i,set:function(e,t){e[t]=!0},unset:function(e,t){delete e[t]},$animate:a}),this.$setPristine=function(){y.$dirty=!1,y.$pristine=!0,a.removeClass(i,Ca),a.addClass(i,Ea)},this.$setDirty=function(){y.$dirty=!0,y.$pristine=!1,a.removeClass(i,Ea),a.addClass(i,Ca),y.$$parentForm.$setDirty()},this.$setUntouched=function(){y.$touched=!1,y.$untouched=!0,a.setClass(i,wa,xa)},this.$setTouched=function(){y.$touched=!0,y.$untouched=!1,a.setClass(i,xa,wa)},this.$rollbackViewValue=function(){s.cancel($),y.$viewValue=y.$$lastCommittedViewValue,y.$render()},this.$validate=function(){if(!C(y.$modelValue)||!isNaN(y.$modelValue)){var e=y.$$lastCommittedViewValue,t=y.$$rawModelValue,n=y.$valid,r=y.$modelValue,i=y.$options&&y.$options.allowInvalid;y.$$runValidators(t,e,function(e){i||n===e||(y.$modelValue=e?t:void 0,y.$modelValue!==r&&y.$$writeModelToScope())})}},this.$$runValidators=function(e,t,n){function i(){var e=y.$$parserName||"parse";return v(d)?(s(e,null),!0):(d||(r(y.$validators,function(e,t){s(t,null)}),r(y.$asyncValidators,function(e,t){s(t,null)})),s(e,d),d)}function o(){var n=!0;return r(y.$validators,function(r,i){var o=r(e,t);n=n&&o,s(i,o)}),!!n||(r(y.$asyncValidators,function(e,t){s(t,null)}),!1)}function a(){var n=[],i=!0;r(y.$asyncValidators,function(r,o){var a=r(e,t);if(!D(a))throw Ta("nopromise","Expected asynchronous validator to return a promise but got '{0}' instead.",a);s(o,void 0),n.push(a.then(function(){s(o,!0)},function(){i=!1,s(o,!1)}))}),n.length?l.all(n).then(function(){c(i)},f):c(!0)}function s(e,t){u===E&&y.$setValidity(e,t)}function c(e){u===E&&n(e)}E++;var u=E;return i()&&o()?void a():void c(!1)},this.$commitViewValue=function(){var e=y.$viewValue;s.cancel($),(y.$$lastCommittedViewValue!==e||""===e&&y.$$hasNativeValidators)&&(y.$$updateEmptyClasses(e),y.$$lastCommittedViewValue=e,y.$pristine&&this.$setDirty(),this.$$parseAndValidate())},this.$$parseAndValidate=function(){function t(){y.$modelValue!==o&&y.$$writeModelToScope()}var n=y.$$lastCommittedViewValue,r=n;if(d=!v(r)||void 0)for(var i=0;i=0;t--){var r=w.items[t];qe(b(r.group)?r.element.parentNode:r.element)}w=x.getOptions();var i={};if(E&&n.prepend(f),w.items.forEach(function(e){var t;b(e.group)?(t=i[e.group],t||(t=l.cloneNode(!1),k.appendChild(t),t.label=null===e.group?"null":e.group,i[e.group]=t),u(e,t)):u(e,k)}),n[0].appendChild(k),p.$render(),!p.$isEmpty(e)){var o=h.readValue(),a=x.trackBy||g;(a?j(e,o):e===o)||(p.$setViewValue(o),p.$render())}}for(var f,h=s[0],p=s[1],g=o.multiple,v=0,$=n.children(),y=$.length;v0&&(e=new RegExp("^"+e+"$")),e&&!e.test)throw t("ngPattern")("noregexp","Expected {0} to be a RegExp but was {1}. Element: {2}",a,e,Q(n));o=e||void 0,i.$validate()}),i.$validators.pattern=function(e,t){return i.$isEmpty(t)||v(o)||o.test(t)}}}}},rs=function(){return{restrict:"A",require:"?ngModel",link:function(e,t,n,r){if(r){var i=-1;n.$observe("maxlength",function(e){var t=d(e);i=isNaN(t)?-1:t,r.$validate()}),r.$validators.maxlength=function(e,t){return i<0||r.$isEmpty(t)||t.length<=i}}}}},is=function(){return{restrict:"A",require:"?ngModel",link:function(e,t,n,r){if(r){var i=0;n.$observe("minlength",function(e){i=d(e)||0,r.$validate()}),r.$validators.minlength=function(e,t){return r.$isEmpty(t)||t.length>=i}}}}};return e.angular.bootstrap?void(e.console&&console.log("WARNING: Tried to load angular more than once.")):(ce(),$e(Yr),Yr.module("ngLocale",[],["$provide",function(e){function t(e){e+="";var t=e.indexOf(".");return t==-1?0:e.length-t-1}function n(e,n){var r=n;void 0===r&&(r=Math.min(t(e),3));var i=Math.pow(10,r),o=(e*i|0)%i;return{v:r,f:o}}var r={ZERO:"zero",ONE:"one",TWO:"two",FEW:"few",MANY:"many",OTHER:"other"};e.value("$locale",{DATETIME_FORMATS:{AMPMS:["AM","PM"],DAY:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],ERANAMES:["Before Christ","Anno Domini"],ERAS:["BC","AD"],FIRSTDAYOFWEEK:6,MONTH:["January","February","March","April","May","June","July","August","September","October","November","December"],SHORTDAY:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],SHORTMONTH:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],STANDALONEMONTH:["January","February","March","April","May","June","July","August","September","October","November","December"],WEEKENDRANGE:[5,6],fullDate:"EEEE, MMMM d, y",longDate:"MMMM d, y",medium:"MMM d, y h:mm:ss a",mediumDate:"MMM d, y",mediumTime:"h:mm:ss a","short":"M/d/yy h:mm a",shortDate:"M/d/yy",shortTime:"h:mm a"},NUMBER_FORMATS:{CURRENCY_SYM:"$",DECIMAL_SEP:".",GROUP_SEP:",",PATTERNS:[{gSize:3,lgSize:3,maxFrac:3,minFrac:0,minInt:1,negPre:"-",negSuf:"",posPre:"",posSuf:""},{gSize:3,lgSize:3,maxFrac:2,minFrac:2,minInt:1,negPre:"-¤",negSuf:"",posPre:"¤",posSuf:""}]},id:"en-us",localeID:"en_US",pluralCat:function(e,t){var i=0|e,o=n(e,t);return 1==i&&0==o.v?r.ONE:r.OTHER}})}]),void Fr(e.document).ready(function(){re(e.document,ie)}))}(window),!window.angular.$$csp().noInlineStyle&&window.angular.element(document.head).prepend('')},15:function(e,t){e.exports=function(e){return e.webpackPolyfill||(e.deprecate=function(){},e.paths=[],e.children=[],e.webpackPolyfill=1),e}},236:function(e,t,n){/*! + * State-based routing for AngularJS + * @version v1.0.0-beta.3 + * @link https://ui-router.github.io + * @license MIT License, http://www.opensource.org/licenses/MIT + */ +!function(t,r){e.exports=r(n(1))}(this,function(e){return function(e){function t(r){if(n[r])return n[r].exports;var i=n[r]={exports:{},id:r,loaded:!1};return e[r].call(i.exports,i,i.exports,t),i.loaded=!0,i.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){"use strict";function r(e){for(var n in e)t.hasOwnProperty(n)||(t[n]=e[n])}r(n(1)),r(n(53)),r(n(55)),r(n(58)),n(60),n(61),n(62),n(63),Object.defineProperty(t,"__esModule",{value:!0}),t["default"]="ui.router"},function(e,t,n){"use strict";function r(e){for(var n in e)t.hasOwnProperty(n)||(t[n]=e[n])}r(n(2)),r(n(46)),r(n(47)),r(n(48)),r(n(49)),r(n(50)),r(n(51)),r(n(52)),r(n(44));var i=n(25);t.UIRouter=i.UIRouter},function(e,t,n){"use strict";function r(e){for(var n in e)t.hasOwnProperty(n)||(t[n]=e[n])}r(n(3)),r(n(6)),r(n(7)),r(n(5)),r(n(4)),r(n(8)),r(n(9)),r(n(12))},function(e,t,n){"use strict";function r(e,t,n,r){return void 0===r&&(r=Object.keys(e)),r.filter(function(t){return"function"==typeof e[t]}).forEach(function(r){return t[r]=e[r].bind(n)})}function i(e){void 0===e&&(e={});for(var n=[],r=1;r=0&&e.splice(n,1),e}),t.defaults=i,t.merge=o,t.mergeR=function(e,n){return t.extend(e,n)},t.ancestors=a,t.equalForKeys=s,t.pick=l,t.omit=u,t.pluck=d,t.filter=m,t.find=f,t.mapObj=h,t.map=h,t.values=function(e){return Object.keys(e).map(function(t){return e[t]})},t.allTrueR=function(e,t){return e&&t},t.anyTrueR=function(e,t){return e||t},t.unnestR=function(e,t){return e.concat(t)},t.flattenR=function(e,n){return M.isArray(n)?e.concat(n.reduce(t.flattenR,[])):p(e,n)},t.pushR=p,t.uniqR=function(e,n){return t.inArray(e,n)?e:p(e,n)},t.unnest=function(e){return e.reduce(t.unnestR,[])},t.flatten=function(e){return e.reduce(t.flattenR,[])},t.assertPredicate=g,t.pairs=function(e){return Object.keys(e).map(function(t){return[t,e[t]]})},t.arrayTuples=v,t.applyPairs=b,t.tail=$,t.silenceUncaughtInPromise=function(e){return e["catch"](function(e){return 0})&&e},t.silentRejection=function(e){return t.silenceUncaughtInPromise(T.services.$q.reject(e))}},function(e,t,n){"use strict";function r(e){if(t.isArray(e)&&e.length){var n=e.slice(0,-1),r=e.slice(-1);return!(n.filter(i.not(t.isString)).length||r.filter(i.not(t.isFunction)).length)}return t.isFunction(e)}var i=n(5),o=Object.prototype.toString,a=function(e){return function(t){return typeof t===e}};t.isUndefined=a("undefined"),t.isDefined=i.not(t.isUndefined),t.isNull=function(e){return null===e},t.isFunction=a("function"),t.isNumber=a("number"),t.isString=a("string"),t.isObject=function(e){return null!==e&&"object"==typeof e},t.isArray=Array.isArray,t.isDate=function(e){return"[object Date]"===o.call(e)},t.isRegExp=function(e){return"[object RegExp]"===o.call(e)},t.isInjectable=r,t.isPromise=i.and(t.isObject,i.pipe(i.prop("then"),t.isFunction))},function(e,t){"use strict";function n(e){function t(n){return n.length>=r?e.apply(null,n):function(){return t(n.concat([].slice.apply(arguments)))}}var n=[].slice.apply(arguments,[1]),r=e.length;return t(n)}function r(){var e=arguments,t=e.length-1;return function(){for(var n=t,r=e[t].apply(this,arguments);n--;)r=e[n].call(this,r);return r}}function i(){for(var e=[],t=0;t-1},e.fromString=function(t){return this.is(t)?new e(t):null},e}();t.Glob=n},function(e,t){"use strict";var n=function(){function e(e,t){void 0===e&&(e=[]),void 0===t&&(t=null),this._items=e,this._limit=t}return e.prototype.enqueue=function(e){var t=this._items;return t.push(e),this._limit&&t.length>this._limit&&t.shift(),e},e.prototype.dequeue=function(){if(this.size())return this._items.splice(0,1)[0]},e.prototype.clear=function(){var e=this._items;return this._items=[],e},e.prototype.size=function(){return this._items.length},e.prototype.remove=function(e){var t=this._items.indexOf(e);return t>-1&&this._items.splice(t,1)[0]},e.prototype.peekTail=function(){return this._items[this._items.length-1]},e.prototype.peekHead=function(){if(this.size())return this._items[0]},e}();t.Queue=n},function(e,t,n){"use strict";function r(e,t){return t.length<=e?t:t.substr(0,e-3)+"..."}function i(e,t){for(;t.length20)return"Too many Transition redirects (20+)";return e.self["abstract"]?"Cannot transition to abstract state '"+e.name+"'":p.Param.validates(e.parameters(),this.params())?this.success===!1?this._error:void 0:"Param values not valid for state '"+e.name+"'"},e.prototype.toString=function(){var e=this.from(),t=this.to(),n=function(e){return null!==e["#"]&&void 0!==e["#"]?e:a.omit(e,"#")},r=this.$id,i=s.isObject(e)?e.name:e,o=a.toJson(n(this._treeChanges.from.map(c.prop("paramValues")).reduce(a.mergeR,{}))),l=this.valid()?"":"(X) ",u=s.isObject(t)?t.name:t,d=a.toJson(n(this.params()));return"Transition#"+r+"( '"+i+"'"+o+" -> "+l+"'"+u+"'"+d+" )"},e.diToken=e,e}();t.Transition=C},function(e,t,n){"use strict";function r(e){return e?"[ui-view#"+e.id+" tag "+("in template from '"+(e.creationContext&&e.creationContext.name||"(root)")+"' state]: ")+("fqn: '"+e.fqn+"', ")+("name: '"+e.name+"@"+e.creationContext+"')"):"ui-view (defunct)"}function i(e){return a.isNumber(e)?l[e]:l[l[e]]}var o=n(5),a=n(4),s=n(9),c=function(e){return"[ViewConfig#"+e.$id+" from '"+(e.viewDecl.$context.name||"(root)")+"' state]: target ui-view: '"+e.viewDecl.$uiViewName+"@"+e.viewDecl.$uiViewContextAnchor+"'"};!function(e){e[e.RESOLVE=0]="RESOLVE",e[e.TRANSITION=1]="TRANSITION",e[e.HOOK=2]="HOOK",e[e.UIVIEW=3]="UIVIEW",e[e.VIEWCONFIG=4]="VIEWCONFIG"}(t.Category||(t.Category={}));var l=t.Category,u=function(){function e(){this._enabled={},this.approximateDigests=0}return e.prototype._set=function(e,t){var n=this;t.length||(t=Object.keys(l).map(function(e){return parseInt(e,10)}).filter(function(e){return!isNaN(e)}).map(function(e){return l[e]})),t.map(i).forEach(function(t){return n._enabled[t]=e})},e.prototype.enable=function(){for(var e=[],t=0;t "+r)}},e.prototype.traceTransitionIgnored=function(e){if(this.enabled(l.TRANSITION)){var t=e&&e.$id,n=this.approximateDigests,r=s.stringify(e);console.log("Transition #"+t+" Digest #"+n+": Ignored <> "+r)}},e.prototype.traceHookInvocation=function(e,t){if(this.enabled(l.HOOK)){var n=o.parse("transition.$id")(t),r=this.approximateDigests,i=o.parse("traceData.hookType")(t)||"internal",a=o.parse("traceData.context.state.name")(t)||o.parse("traceData.context")(t)||"unknown",c=s.functionToString(e.eventHook.callback);console.log("Transition #"+n+" Digest #"+r+": Hook -> "+i+" context: "+a+", "+s.maxLength(200,c))}},e.prototype.traceHookResult=function(e,t){if(this.enabled(l.HOOK)){var n=o.parse("transition.$id")(t),r=this.approximateDigests,i=s.stringify(e);console.log("Transition #"+n+" Digest #"+r+": <- Hook returned: "+s.maxLength(200,i))}},e.prototype.traceResolvePath=function(e,t,n){if(this.enabled(l.RESOLVE)){var r=n&&n.$id,i=this.approximateDigests,o=e&&e.toString();console.log("Transition #"+r+" Digest #"+i+": Resolving "+o+" ("+t+")")}},e.prototype.traceResolvableResolved=function(e,t){if(this.enabled(l.RESOLVE)){var n=t&&t.$id,r=this.approximateDigests,i=e&&e.toString(),o=s.stringify(e.data);console.log("Transition #"+n+" Digest #"+r+": <- Resolved "+i+" to: "+s.maxLength(200,o))}},e.prototype.traceError=function(e,t){if(this.enabled(l.TRANSITION)){var n=t&&t.$id,r=this.approximateDigests,i=s.stringify(t);console.log("Transition #"+n+" Digest #"+r+": <- Rejected "+i+", reason: "+e)}},e.prototype.traceSuccess=function(e,t){if(this.enabled(l.TRANSITION)){var n=t&&t.$id,r=this.approximateDigests,i=e.name,o=s.stringify(t);console.log("Transition #"+n+" Digest #"+r+": <- Success "+o+", final state: "+i)}},e.prototype.traceUIViewEvent=function(e,t,n){void 0===n&&(n=""),this.enabled(l.UIVIEW)&&console.log("ui-view: "+s.padString(30,e)+" "+r(t)+n)},e.prototype.traceUIViewConfigUpdated=function(e,t){this.enabled(l.UIVIEW)&&this.traceUIViewEvent("Updating",e," with ViewConfig from context='"+t+"'")},e.prototype.traceUIViewFill=function(e,t){this.enabled(l.UIVIEW)&&this.traceUIViewEvent("Fill",e," with: "+s.maxLength(200,t))},e.prototype.traceViewServiceEvent=function(e,t){this.enabled(l.VIEWCONFIG)&&console.log("VIEWCONFIG: "+e+" "+c(t))},e.prototype.traceViewServiceUIViewEvent=function(e,t){this.enabled(l.VIEWCONFIG)&&console.log("VIEWCONFIG: "+e+" "+r(t))},e}();t.Trace=u;var d=new u;t.trace=d},function(e,t,n){"use strict";var r=n(3),i=n(9),o=n(4),a=n(5),s=n(12),c=n(6),l=n(10),u=n(14),d={async:!0,rejectIfSuperseded:!0,current:r.noop,transition:null,traceData:{},bind:null},m=function(){function e(e,t,n,i){var o=this;this.transition=e,this.stateContext=t,this.eventHook=n,this.options=i,this.isSuperseded=function(){return o.options.current()!==o.options.transition},this.options=r.defaults(i,d)}return e.prototype.invokeHook=function(){var e=this,t=e.options,n=e.eventHook;if(s.trace.traceHookInvocation(this,t),t.rejectIfSuperseded&&this.isSuperseded())return l.Rejection.superseded(t.current()).toPromise();var r=n._deregistered?void 0:n.callback.call(t.bind,this.transition,this.stateContext);return this.handleHookResult(r)},e.prototype.handleHookResult=function(e){if(this.isSuperseded())return l.Rejection.superseded(this.options.current()).toPromise();if(o.isPromise(e))return e.then(this.handleHookResult.bind(this));if(s.trace.traceHookResult(e,this.options),e===!1)return l.Rejection.aborted("Hook aborted transition").toPromise();var t=a.is(u.TargetState);return t(e)?l.Rejection.redirected(e).toPromise():void 0},e.prototype.toString=function(){var e=this,t=e.options,n=e.eventHook,r=a.parse("traceData.hookType")(t)||"internal",o=a.parse("traceData.context.state.name")(t)||a.parse("traceData.context")(t)||"unknown",s=i.fnToString(n.callback);return r+" context: "+o+", "+i.maxLength(200,s)},e.runSynchronousHooks=function(e,t){void 0===t&&(t=!1);for(var n=[],r=0;r=0));)g(u.id),this._params.push(s.Param.fromPath(u.id,u.type,this.config.paramMap(u.cfg,!1),n)),this._segments.push(u.segment),p.push([u.segment,i.tail(this._params)]),h=m.lastIndex;d=t.substring(h);var b=d.indexOf("?");if(b>=0){var $=d.substring(b);if(d=d.substring(0,b),$.length>0)for(h=0;l=f.exec($);)u=v(l,!0),g(u.id),this._params.push(s.Param.fromSearch(u.id,u.type,this.config.paramMap(u.cfg,!0),n)),h=m.lastIndex}this._segments.push(d),i.extend(this,{_compiled:p.map(function(e){return r.apply(null,e)}).concat(r(d)),prefix:this._segments[0]}),Object.freeze(this)}return e.prototype.append=function(e){return this._children.push(e),i.forEach(e._cache,function(t,n){return e._cache[n]=a.isArray(t)?[]:null}),e._cache.path=this._cache.path.concat(this),e},e.prototype.isRoot=function(){return 0===this._cache.path.length},e.prototype.toString=function(){return this.pattern},e.prototype.exec=function(e,t,n,r){function a(e){var t=function(e){return e.split("").reverse().join("")},n=function(e){return e.replace(/\\-/g,"-")},r=t(e).split(/-(?!\\)/),o=i.map(r,t);return i.map(o,n).reverse()}var s=this;void 0===t&&(t={}),void 0===r&&(r={});var l=m(this._cache,"pattern",function(){return new RegExp(["^",i.unnest(s._cache.path.concat(s).map(o.prop("_compiled"))).join(""),s.config.strict===!1?"/?":"","$"].join(""),s.config.caseInsensitive?"i":void 0)}).exec(e);if(!l)return null;var u=this.parameters(),d=u.filter(function(e){return!e.isSearch()}),f=u.filter(function(e){return e.isSearch()}),h=this._cache.path.concat(this).map(function(e){return e._segments.length-1}).reduce(function(e,t){return e+t}),p={};if(h!==l.length-1)throw new Error("Unbalanced capture group in route '"+this.pattern+"'");for(var g=0;g1&&r.sort(s(n,-1)),[t,r[0]]},l=function(t){var n=t[0],r=t[1];e.uiViews.indexOf(n)!==-1&&n.configUpdated(r)};e.uiViews.sort(s(t,1)).map(c).forEach(l)}}return e.prototype.rootContext=function(e){return this._rootContext=e||this._rootContext},e.prototype.viewConfigFactory=function(e,t){this._viewConfigFactories[e]=t},e.prototype.createViewConfig=function(e,t){var n=this._viewConfigFactories[t.$type];if(!n)throw new Error("ViewService: No view config factory registered for type "+t.$type);var r=n(e,t);return o.isArray(r)?r:[r]},e.prototype.deactivateViewConfig=function(e){a.trace.traceViewServiceEvent("<- Removing",e),r.removeFrom(this.viewConfigs,e)},e.prototype.activateViewConfig=function(e){a.trace.traceViewServiceEvent("-> Registering",e),this.viewConfigs.push(e)},e.prototype.registerUIView=function(e){a.trace.traceViewServiceUIViewEvent("-> Registering",e);var t=this.uiViews,n=function(t){return t.fqn===e.fqn};return t.filter(n).length&&a.trace.traceViewServiceUIViewEvent("!!!! duplicate uiView named:",e),t.push(e),this.sync(),function(){var n=t.indexOf(e);return n===-1?void a.trace.traceViewServiceUIViewEvent("Tried removing non-registered uiView",e):(a.trace.traceViewServiceUIViewEvent("<- Deregistering",e),void r.removeFrom(t)(e))}},e.prototype.available=function(){return this.uiViews.map(i.prop("fqn"))},e.prototype.active=function(){return this.uiViews.filter(i.prop("$config")).map(i.prop("name"))},e.normalizeUIViewTarget=function(e,t){void 0===t&&(t="");var n=t.split("@"),r=n[0]||"$default",i=o.isString(n[1])?n[1]:"^",a=/^(\^(?:\.\^)*)\.(.*$)/.exec(r);a&&(i=a[1],r=a[2]),"!"===r.charAt(0)&&(r=r.substr(1),i="");var s=/^(\^(?:\.\^)*)$/;if(s.exec(i)){var c=i.split(".").reduce(function(e,t){return e.parent},e);i=c.name}return{uiViewName:r,uiViewContextAnchor:i}},e}();t.ViewService=s},function(e,t,n){"use strict";var r=n(39),i=n(40),o=n(41),a=n(3),s=function(){function e(e,t){this.urlRouterProvider=t,this.states={},this.listeners=[],this.matcher=new r.StateMatcher(this.states),this.builder=new i.StateBuilder(this.matcher,e),this.stateQueue=new o.StateQueueManager(this.states,this.builder,t,this.listeners);var n={name:"",url:"^",views:null,params:{"#":{value:null,type:"hash",dynamic:!0}},"abstract":!0},a=this._root=this.stateQueue.register(n);a.navigable=null}return e.prototype.onStatesChanged=function(e){return this.listeners.push(e),function(){a.removeFrom(this.listeners)(e); +}.bind(this)},e.prototype.root=function(){return this._root},e.prototype.register=function(e){return this.stateQueue.register(e)},e.prototype._deregisterTree=function(e){var t=this,n=this.get().map(function(e){return e.$$state()}),r=function(e){var t=n.filter(function(t){return e.indexOf(t.parent)!==-1});return 0===t.length?t:t.concat(r(t))},i=r([e]),o=[e].concat(i).reverse();return o.forEach(function(e){t.urlRouterProvider.removeRule(e._urlRule),delete t.states[e.name]}),o},e.prototype.deregister=function(e){var t=this.get(e);if(!t)throw new Error("Can't deregister state; not found: "+e);var n=this._deregisterTree(t.$$state());return this.listeners.forEach(function(e){return e("deregistered",n.map(function(e){return e.self}))}),n},e.prototype.get=function(e,t){var n=this;if(0===arguments.length)return Object.keys(this.states).map(function(e){return n.states[e].self});var r=this.matcher.find(e,t);return r&&r.self||null},e.prototype.decorator=function(e,t){return this.builder.builder(e,t)},e}();t.StateRegistry=s},function(e,t,n){"use strict";var r=n(4),i=n(7),o=n(3),a=function(){function e(e){this._states=e}return e.prototype.isRelative=function(e){return e=e||"",0===e.indexOf(".")||0===e.indexOf("^")},e.prototype.find=function(e,t){if(e||""===e){var n=r.isString(e),a=n?e:e.name;this.isRelative(a)&&(a=this.resolvePath(a,t));var s=this._states[a];if(s&&(n||!(n||s!==e&&s.self!==e)))return s;if(n){var c=o.values(this._states).filter(function(e){return new i.Glob(e.name).matches(a)});return c.length>1&&console.log("stateMatcher.find: Found multiple matches for "+a+" using glob: ",c.map(function(e){return e.name})),c[0]}}},e.prototype.resolvePath=function(e,t){if(!t)throw new Error("No reference point given for path '"+e+"'");for(var n=this.find(t),r=e.split("."),i=0,o=r.length,a=n;i1?r:r[0]:u.isString(e)&&u.isFunction(t)?(n[e]=r,n[e].push(t),function(){return n[e].splice(n[e].indexOf(t,1))&&null}):void 0},e.prototype.build=function(e){var t=this,n=t.matcher,r=t.builders,i=this.parentName(e);if(i&&!n.find(i))return null;for(var o in r)if(r.hasOwnProperty(o)){var a=r[o].reduce(function(e,t){return function(n){return t(n,e)}},l.noop);e[o]=a(e)}return e},e.prototype.parentName=function(e){var t=e.name||"",n=t.split(".");if(n.length>1){if(e.parent)throw new Error("States that specify the 'parent:' property should not have a '.' in their name ("+t+")");var r=n.pop();return"**"===r&&n.pop(),n.join(".")}return e.parent?u.isString(e.parent)?e.parent:e.parent.name:""},e.prototype.name=function(e){var t=e.name;if(t.indexOf(".")!==-1||!e.parent)return t;var n=u.isString(e.parent)?e.parent:e.parent.name;return n?n+"."+t:t},e}();t.StateBuilder=y},function(e,t,n){"use strict";var r=n(3),i=n(4),o=n(42),a=function(){function e(e,t,n,r){this.states=e,this.builder=t,this.$urlRouterProvider=n,this.listeners=r,this.queue=[]}return e.prototype.register=function(e){var t=this,n=t.states,a=t.queue,s=t.$state,c=r.inherit(new o.State,r.extend({},e,{self:e,resolve:e.resolve||[],toString:function(){return e.name}}));if(!i.isString(c.name))throw new Error("State must have a valid name");if(n.hasOwnProperty(c.name)||r.pluck(a,"name").indexOf(c.name)!==-1)throw new Error("State '"+c.name+"' is already defined");return a.push(c),this.$state&&this.flush(s),c},e.prototype.flush=function(e){for(var t=this,n=t.queue,r=t.states,i=t.builder,o=[],a=[],s={};n.length>0;){var c=n.shift(),l=i.build(c),u=a.indexOf(c);if(l){if(r.hasOwnProperty(c.name))throw new Error("State '"+name+"' is already defined");r[c.name]=c,this.attachRoute(e,c),u>=0&&a.splice(u,1),o.push(c)}else{var d=s[c.name];if(s[c.name]=n.length,u>=0&&d===n.length)return n.push(c),r;u<0&&a.push(c),n.push(c)}}return o.length&&this.listeners.forEach(function(e){return e("registered",o.map(function(e){return e.self}))}),r},e.prototype.autoFlush=function(e){this.$state=e,this.flush(e)},e.prototype.attachRoute=function(e,t){var n=this.$urlRouterProvider;!t["abstract"]&&t.url&&n.when(t.url,["$match","$stateParams",function(n,i){e.$current.navigable===t&&r.equalForKeys(n,i)||e.transitionTo(t,n,{inherit:!0,source:"url"})}],function(e){return t._urlRule=e})},e}();t.StateQueueManager=a},function(e,t,n){"use strict";var r=n(3),i=n(5),o=function(){function e(e){r.extend(this,e)}return e.prototype.is=function(e){return this===e||this.self===e||this.fqn()===e},e.prototype.fqn=function(){if(!(this.parent&&this.parent instanceof this.constructor))return this.name;var e=this.parent.fqn();return e?e+"."+this.name:this.name},e.prototype.root=function(){return this.parent&&this.parent.root()||this},e.prototype.parameters=function(e){e=r.defaults(e,{inherit:!0});var t=e.inherit&&this.parent&&this.parent.parameters()||[];return t.concat(r.values(this.params))},e.prototype.parameter=function(e,t){return void 0===t&&(t={}),this.url&&this.url.parameter(e,t)||r.find(r.values(this.params),i.propEq("id",e))||t.inherit&&this.parent&&this.parent.parameter(e)},e.prototype.toString=function(){return this.fqn()},e}();t.State=o},function(e,t,n){"use strict";var r=n(3),i=n(4),o=n(8),a=n(6),s=n(20),c=n(21),l=n(30),u=n(10),d=n(14),m=n(22),f=n(7),h=n(3),p=n(3),g=n(17),v=function(){function e(t){this.router=t,this.invalidCallbacks=[],this._defaultErrorHandler=function(e){e instanceof Error&&e.stack?(console.error(e),console.error(e.stack)):e instanceof u.Rejection?(console.error(e.toString()),e.detail&&e.detail.stack&&console.error(e.detail.stack)):console.error(e)};var n=["current","$current","params","transition"],r=Object.keys(e.prototype).filter(function(e){return n.indexOf(e)===-1});p.bindFunctions(e.prototype,this,this,r)}return Object.defineProperty(e.prototype,"transition",{get:function(){return this.router.globals.transition},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"params",{get:function(){return this.router.globals.params},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"current",{get:function(){return this.router.globals.current},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"$current",{get:function(){return this.router.globals.$current},enumerable:!0,configurable:!0}),e.prototype._handleInvalidTargetState=function(e,t){function n(){var e=f.dequeue();if(void 0===e)return u.Rejection.invalid(t.error()).toPromise();var r=a.services.$q.when(e(t,i,h));return r.then(p).then(function(e){return e||n()})}var r=this,i=s.PathFactory.makeTargetState(e),c=this.router.globals,l=function(){return c.transitionHistory.peekTail()},m=l(),f=new o.Queue(this.invalidCallbacks.slice()),h=new g.ResolveContext(e).injector(),p=function(e){if(e instanceof d.TargetState){var t=e;return t=r.target(t.identifier(),t.params(),t.options()),t.valid()?l()!==m?u.Rejection.superseded().toPromise():r.transitionTo(t.identifier(),t.params(),t.options()):u.Rejection.invalid(t.error()).toPromise()}};return n()},e.prototype.onInvalid=function(e){return this.invalidCallbacks.push(e),function(){r.removeFrom(this.invalidCallbacks)(e)}.bind(this)},e.prototype.reload=function(e){return this.transitionTo(this.current,this.params,{reload:!i.isDefined(e)||e,inherit:!1,notify:!1})},e.prototype.go=function(e,t,n){var i={relative:this.$current,inherit:!0},o=r.defaults(n,i,l.defaultTransOpts);return this.transitionTo(e,t,o)},e.prototype.target=function(e,t,n){if(void 0===n&&(n={}),i.isObject(n.reload)&&!n.reload.name)throw new Error("Invalid reload state object");var r=this.router.stateRegistry;if(n.reloadState=n.reload===!0?r.root():r.matcher.find(n.reload,n.relative),n.reload&&!n.reloadState)throw new Error("No such reload state '"+(i.isString(n.reload)?n.reload:n.reload.name)+"'");var o=r.matcher.find(e,n.relative);return new d.TargetState(e,o,t,n)},e.prototype.transitionTo=function(e,t,n){var i=this;void 0===t&&(t={}),void 0===n&&(n={});var o=this.router,s=o.globals,m=s.transitionHistory;n=r.defaults(n,l.defaultTransOpts),n=r.extend(n,{current:m.peekTail.bind(m)});var f=this.target(e,t,n),h=s.successfulTransitions.peekTail(),p=function(){return[new c.PathNode(i.router.stateRegistry.root())]},g=h?h.treeChanges().to:p();if(!f.exists())return this._handleInvalidTargetState(g,f);if(!f.valid())return r.silentRejection(f.error());var v=function(e){return function(t){if(t instanceof u.Rejection){if(t.type===u.RejectType.IGNORED)return o.urlRouter.update(),a.services.$q.when(s.current);var n=t.detail;if(t.type===u.RejectType.SUPERSEDED&&t.redirected&&n instanceof d.TargetState){var r=e.redirect(n);return r.run()["catch"](v(r))}t.type===u.RejectType.ABORTED&&o.urlRouter.update()}var c=i.defaultErrorHandler();return c(t),a.services.$q.reject(t)}},b=this.router.transitionService.create(g,f),$=b.run()["catch"](v(b));return r.silenceUncaughtInPromise($),r.extend($,{transition:b})},e.prototype.is=function(e,t,n){n=r.defaults(n,{relative:this.$current});var o=this.router.stateRegistry.matcher.find(e,n.relative);if(i.isDefined(o))return this.$current===o&&(!i.isDefined(t)||null===t||m.Param.equals(o.parameters(),this.params,t))},e.prototype.includes=function(e,t,n){n=r.defaults(n,{relative:this.$current});var o=i.isString(e)&&f.Glob.fromString(e);if(o){if(!o.matches(this.$current.name))return!1;e=this.$current.name}var a=this.router.stateRegistry.matcher.find(e,n.relative),s=this.$current.includes;if(i.isDefined(a))return!!i.isDefined(s[a.name])&&(!t||h.equalForKeys(m.Param.values(a.parameters(),t),this.params,Object.keys(t)))},e.prototype.href=function(e,t,n){var o={lossy:!0,inherit:!0,absolute:!1,relative:this.$current};n=r.defaults(n,o),t=t||{};var a=this.router.stateRegistry.matcher.find(e,n.relative);if(!i.isDefined(a))return null;n.inherit&&(t=this.params.$inherit(t,this.$current,a));var s=a&&n.lossy?a.navigable:a;return s&&void 0!==s.url&&null!==s.url?this.router.urlRouter.href(s.url,m.Param.values(a.parameters(),t),{absolute:n.absolute}):null},e.prototype.defaultErrorHandler=function(e){return this._defaultErrorHandler=e||this._defaultErrorHandler},e.prototype.get=function(e,t){var n=this.router.stateRegistry;return 0===arguments.length?n.get():n.get(e,t||this.$current)},e}();t.StateService=v},function(e,t,n){"use strict";var r=n(45),i=n(8),o=n(3),a=function(){function e(e){var t=this;this.params=new r.StateParams,this.transitionHistory=new i.Queue([],1),this.successfulTransitions=new i.Queue([],1);var n=function(e){t.transition=e,t.transitionHistory.enqueue(e);var n=function(){t.successfulTransitions.enqueue(e),t.$current=e.$to(),t.current=t.$current.self,o.copy(e.params(),t.params)};e.onSuccess({},n,{priority:1e4});var r=function(){t.transition===e&&(t.transition=null)};e.promise.then(r,r)};e.onBefore({},n)}return e}();t.Globals=a},function(e,t,n){"use strict";var r=n(3),i=function(){function e(e){void 0===e&&(e={}),r.extend(this,e)}return e.prototype.$inherit=function(e,t,n){var i,o=r.ancestors(t,n),a={},s=[];for(var c in o)if(o[c]&&o[c].params&&(i=Object.keys(o[c].params),i.length))for(var l in i)s.indexOf(i[l])>=0||(s.push(i[l]),a[i[l]]=this[i[l]]);return r.extend({},a,e)},e}();t.StateParams=i},function(e,t,n){"use strict";function r(e){for(var n in e)t.hasOwnProperty(n)||(t[n]=e[n])}r(n(22)),r(n(28)),r(n(45)),r(n(24))},function(e,t,n){"use strict";function r(e){for(var n in e)t.hasOwnProperty(n)||(t[n]=e[n])}r(n(21)),r(n(20))},function(e,t,n){"use strict";function r(e){for(var n in e)t.hasOwnProperty(n)||(t[n]=e[n])}r(n(18)),r(n(19)),r(n(17))},function(e,t,n){"use strict";function r(e){for(var n in e)t.hasOwnProperty(n)||(t[n]=e[n])}r(n(40)),r(n(42)),r(n(39)),r(n(41)),r(n(38)),r(n(43)),r(n(14))},function(e,t,n){"use strict";function r(e){for(var n in e)t.hasOwnProperty(n)||(t[n]=e[n])}r(n(16)),r(n(15)),r(n(10)),r(n(11)),r(n(13)),r(n(30))},function(e,t,n){"use strict";function r(e){for(var n in e)t.hasOwnProperty(n)||(t[n]=e[n])}r(n(27)),r(n(23)),r(n(26)),r(n(29))},function(e,t,n){"use strict";function r(e){for(var n in e)t.hasOwnProperty(n)||(t[n]=e[n])}r(n(37))},function(e,t,n){"use strict";function r(e){var t=d.services.$injector,n=t.get("$controller"),r=t.instantiate;try{var i;return t.instantiate=function(e){t.instantiate=r,i=t.annotate(e)},n(e,{$scope:{}}),i}finally{t.instantiate=r}}function i(e){function t(t,r,i,o,a,s){return o.$on("$locationChangeSuccess",function(e){return n.forEach(function(t){return t(e)})}),d.services.locationConfig.html5Mode=function(){var t=e.html5Mode();return t=h.isObject(t)?t.enabled:t,t&&i.history},d.services.location.setUrl=function(e,n){void 0===n&&(n=!1),t.url(e),n&&t.replace()},d.services.template.get=function(e){return a.get(e,{cache:s,headers:{Accept:"text/html"}}).then(f.prop("data"))},m.bindFunctions(t,d.services.location,t,["replace","url","path","search","hash"]),m.bindFunctions(t,d.services.locationConfig,t,["port","protocol","host"]),m.bindFunctions(r,d.services.locationConfig,r,["baseHref"]),C}C=new u.UIRouter,C.stateProvider=new $.StateProvider(C.stateRegistry,C.stateService),C.stateRegistry.decorator("views",v.ng1ViewsBuilder),C.stateRegistry.decorator("onExit",y.getStateHookBuilder("onExit")),C.stateRegistry.decorator("onRetain",y.getStateHookBuilder("onRetain")),C.stateRegistry.decorator("onEnter",y.getStateHookBuilder("onEnter")),C.viewService.viewConfigFactory("ng1",v.ng1ViewConfigFactory),m.bindFunctions(e,d.services.locationConfig,e,["hashPrefix"]);var n=[];d.services.location.onChange=function(e){return n.push(e),function(){return m.removeFrom(n)(e)}},this.$get=t,t.$inject=["$location","$browser","$sniffer","$rootScope","$http","$templateCache"]}function o(e,t){d.services.$injector=e,d.services.$q=t}function a(){return C.urlRouterProvider.$get=function(){return C.urlRouter.update(!0),this.interceptDeferred||C.urlRouter.listen(),C.urlRouter},C.urlRouterProvider}function s(){return C.stateProvider.$get=function(){return C.stateRegistry.stateQueue.autoFlush(C.stateService),C.stateService},C.stateProvider}function c(){return C.transitionService.$get=function(){return C.transitionService},C.transitionService}function l(e){e.$watch(function(){g.trace.approximateDigests++})}var u=n(25),d=n(6),m=n(3),f=n(5),h=n(4),p=n(54),g=n(12),v=n(55),b=n(56),$=n(58),y=n(59),E=n(57);E.module("ui.router.angular1",[]);E.module("ui.router.util",["ng","ui.router.init"]),E.module("ui.router.router",["ui.router.util"]),E.module("ui.router.state",["ui.router.router","ui.router.util","ui.router.angular1"]),E.module("ui.router",["ui.router.init","ui.router.state","ui.router.angular1"]),E.module("ui.router.compat",["ui.router"]),t.annotateController=r;var C=null;i.$inject=["$locationProvider"],E.module("ui.router.init",[]).provider("$uiRouter",i),o.$inject=["$injector","$q"],E.module("ui.router.init").run(o),E.module("ui.router.init").run(["$uiRouter",function(e){}]),E.module("ui.router.util").provider("$urlMatcherFactory",["$uiRouterProvider",function(){return C.urlMatcherFactory}]),E.module("ui.router.util").run(["$urlMatcherFactory",function(e){}]),E.module("ui.router.router").provider("$urlRouter",["$uiRouterProvider",a]),E.module("ui.router.router").run(["$urlRouter",function(e){}]),E.module("ui.router.state").provider("$state",["$uiRouterProvider",s]),E.module("ui.router.state").run(["$state",function(e){}]),E.module("ui.router.state").factory("$stateParams",["$uiRouter",function(e){return e.globals.params}]),E.module("ui.router.state").provider("$transitions",["$uiRouterProvider",c]),E.module("ui.router.util").factory("$templateFactory",["$uiRouter",function(){return new b.TemplateFactory}]),E.module("ui.router").factory("$view",function(){return C.viewService}),E.module("ui.router").factory("$resolve",p.resolveFactory),E.module("ui.router").service("$trace",function(){return g.trace}),l.$inject=["$rootScope"],t.watchDigests=l,E.module("ui.router").run(l),t.getLocals=function(e){var t=e.getTokens().filter(h.isString),n=t.map(function(t){return[t,e.getResolvable(t).data]});return n.reduce(m.applyPairs,{})}},function(e,t,n){"use strict";var r=n(42),i=n(21),o=n(17),a=n(3),s=n(40),c={resolve:function(e,t,n){void 0===t&&(t={});var c=new i.PathNode(new r.State({params:{},resolvables:[]})),l=new i.PathNode(new r.State({params:{},resolvables:[]})),u=new o.ResolveContext([c,l]);u.addResolvables(s.resolvablesBuilder({resolve:e}),l.state);var d=function(e){var n=function(e){return s.resolvablesBuilder({resolve:a.mapObj(e,function(e){return function(){return e}})})};u.addResolvables(n(e),c.state),u.addResolvables(n(t),l.state);var r=function(e,t){return e[t.token]=t.value,e};return u.resolvePath().then(function(e){return e.reduce(r,{})})};return n?n.then(d):d({})}};t.resolveFactory=function(){return c}},function(e,t,n){"use strict";function r(e){var t=["templateProvider","templateUrl","template","notify","async"],n=["controller","controllerProvider","controllerAs","resolveAs"],r=["component","bindings"],l=t.concat(n),u=r.concat(l),d={},m=e.views||{$default:o.pick(e,u)};return o.forEach(m,function(t,n){if(n=n||"$default",c.isString(t)&&(t={component:t}),Object.keys(t).length){if(t.component){if(l.map(function(e){return c.isDefined(t[e])}).reduce(o.anyTrueR,!1))throw new Error("Cannot combine: "+r.join("|")+" with: "+l.join("|")+" in stateview: 'name@"+e.name+"'");t.templateProvider=["$injector",function(e){var n=function(e){return t.bindings&&t.bindings[e]||e},r=h.version.minor>=3?"::":"",o=function(e){var t=a.kebobString(e.name),i=n(e.name);return"@"===e.type?t+"='{{"+r+"$resolve."+i+"}}'":t+"='"+r+"$resolve."+i+"'"},s=i(e,t.component).map(o).join(" "),c=a.kebobString(t.component);return"<"+c+" "+s+">"}]}t.resolveAs=t.resolveAs||"$resolve",t.$type="ng1",t.$context=e,t.$name=n;var u=s.ViewService.normalizeUIViewTarget(t.$context,t.$name);t.$uiViewName=u.uiViewName,t.$uiViewContextAnchor=u.uiViewContextAnchor,d[n]=t}}),d}function i(e,t){var n=e.get(t+"Directive");if(!n||!n.length)throw new Error("Unable to find component named '"+t+"'");return n.map(g).reduce(o.unnestR,[])}var o=n(3),a=n(9),s=n(37),c=n(4),l=n(6),u=n(12),d=n(56),m=n(17),f=n(19),h=n(57);t.ng1ViewConfigFactory=function(e,t){return[new b(e,t)]},t.ng1ViewsBuilder=r;var p=function(e){return Object.keys(e||{}).map(function(t){return[t,/^([=<@])[?]?(.*)/.exec(e[t])]}).filter(function(e){return c.isDefined(e)&&c.isDefined(e[1])}).map(function(e){return{name:e[1][2]||e[0],type:e[1][1]}})},g=function(e){return p(c.isObject(e.bindToController)?e.bindToController:e.scope)},v=0,b=function(){function e(e,t){this.path=e,this.viewDecl=t,this.$id=v++,this.loaded=!1}return e.prototype.load=function(){var e=this,t=l.services.$q;if(!this.hasTemplate())throw new Error("No template configuration specified for '"+this.viewDecl.$uiViewName+"@"+this.viewDecl.$uiViewContextAnchor+"'");var n=new m.ResolveContext(this.path),r=this.path.reduce(function(e,t){return o.extend(e,t.paramValues)},{}),i={template:t.when(this.getTemplate(r,new d.TemplateFactory,n)),controller:t.when(this.getController(n))};return t.all(i).then(function(t){return u.trace.traceViewServiceEvent("Loaded",e),e.controller=t.controller,e.template=t.template,e})},e.prototype.hasTemplate=function(){return!!(this.viewDecl.template||this.viewDecl.templateUrl||this.viewDecl.templateProvider)},e.prototype.getTemplate=function(e,t,n){return t.fromConfig(this.viewDecl,e,n)},e.prototype.getController=function(e){var t=this.viewDecl.controllerProvider;if(!c.isInjectable(t))return this.viewDecl.controller;var n=l.services.$injector.annotate(t),r=c.isArray(t)?o.tail(t):t,i=new f.Resolvable("",r,n);return i.get(e)},e}();t.Ng1ViewConfig=b},function(e,t,n){"use strict";var r=n(4),i=n(6),o=n(3),a=n(19),s=function(){function e(){}return e.prototype.fromConfig=function(e,t,n){return r.isDefined(e.template)?this.fromString(e.template,t):r.isDefined(e.templateUrl)?this.fromUrl(e.templateUrl,t):r.isDefined(e.templateProvider)?this.fromProvider(e.templateProvider,t,n):null},e.prototype.fromString=function(e,t){return r.isFunction(e)?e(t):e},e.prototype.fromUrl=function(e,t){return r.isFunction(e)&&(e=e(t)),null==e?null:i.services.template.get(e)},e.prototype.fromProvider=function(e,t,n){var s=i.services.$injector.annotate(e),c=r.isArray(e)?o.tail(e):e,l=new a.Resolvable("",c,s);return l.get(n)},e}();t.TemplateFactory=s},function(t,n){t.exports=e},function(e,t,n){"use strict";var r=n(4),i=n(3),o=function(){function e(t,n){this.stateRegistry=t,this.stateService=n,i.bindFunctions(e.prototype,this,this)}return e.prototype.decorator=function(e,t){return this.stateRegistry.decorator(e,t)||this},e.prototype.state=function(e,t){return r.isObject(e)?t=e:t.name=e,this.stateRegistry.register(t),this},e.prototype.onInvalid=function(e){return this.stateService.onInvalid(e)},e}();t.StateProvider=o},function(e,t,n){"use strict";var r=n(6),i=n(53),o=n(17),a=n(3);t.getStateHookBuilder=function(e){return function(t,n){function s(e,t){var n=new o.ResolveContext(e.treeChanges().to);return r.services.$injector.invoke(c,this,a.extend({$state$:t},i.getLocals(n)))}var c=t[e];return c?s:void 0}}},function(e,t,n){"use strict";function r(e,t){var n,r=e.match(/^\s*({[^}]*})\s*$/);if(r&&(e=t+"("+r[1]+")"),n=e.replace(/\n/g," ").match(/^([^(]+?)\s*(\((.*)\))?$/),!n||4!==n.length)throw new Error("Invalid state ref '"+e+"'");return{state:n[1],paramExpr:n[3]||null}}function i(e){var t=e.parent().inheritedData("$uiView"),n=d.parse("$cfg.path")(t);return n?l.tail(n).state.name:void 0}function o(e){var t="[object SVGAnimatedString]"===Object.prototype.toString.call(e.prop("href")),n="FORM"===e[0].nodeName;return{attr:n?"action":t?"xlink:href":"href",isAnchor:"A"===e.prop("tagName").toUpperCase(),clickable:!n}}function a(e,t,n,r,i){return function(o){var a=o.which||o.button,s=i();if(!(a>1||o.ctrlKey||o.metaKey||o.shiftKey||e.attr("target"))){var c=n(function(){t.go(s.state,s.params,s.options)});o.preventDefault();var l=r.isAnchor&&!s.href?1:0;o.preventDefault=function(){l--<=0&&n.cancel(c)}}}}function s(e,t){return{relative:i(e)||t.$current,inherit:!0,source:"sref"}}var c=n(57),l=n(3),u=n(4),d=n(5),m=["$state","$timeout",function(e,t){return{restrict:"A",require:["?^uiSrefActive","?^uiSrefActiveEq"],link:function(n,i,u,d){var m,f=r(u.uiSref,e.current.name),h={state:f.state,href:null,params:null,options:null},p=o(i),g=d[1]||d[0],v=null;h.options=l.extend(s(i,e),u.uiSrefOpts?n.$eval(u.uiSrefOpts):{});var b=function(t){t&&(h.params=c.copy(t)),h.href=e.href(f.state,h.params,h.options),v&&v(),g&&(v=g.$$addStateInfo(f.state,h.params)),null!==h.href&&u.$set(p.attr,h.href)};f.paramExpr&&(n.$watch(f.paramExpr,function(e){e!==h.params&&b(e)},!0),h.params=c.copy(n.$eval(f.paramExpr))),b(),p.clickable&&(m=a(i,e,t,p,function(){return h}),i.on("click",m),n.$on("$destroy",function(){i.off("click",m)}))}}}],f=["$state","$timeout",function(e,t){return{restrict:"A",require:["?^uiSrefActive","?^uiSrefActiveEq"],link:function(n,r,i,s){function c(t){h.state=t[0],h.params=t[1],h.options=t[2],h.href=e.href(h.state,h.params,h.options),p&&p(),d&&(p=d.$$addStateInfo(h.state,h.params)),h.href&&i.$set(u.attr,h.href)}var l,u=o(r),d=s[1]||s[0],m=[i.uiState,i.uiStateParams||null,i.uiStateOpts||null],f="["+m.map(function(e){return e||"null"}).join(", ")+"]",h={state:null,params:null,options:null,href:null},p=null;n.$watch(f,c,!0),c(n.$eval(f)),u.clickable&&(l=a(r,e,t,u,function(){return h}),r.on("click",l),n.$on("$destroy",function(){r.off("click",l)}))}}}],h=["$state","$stateParams","$interpolate","$transitions","$uiRouter",function(e,t,n,o,a){return{restrict:"A",controller:["$scope","$element","$attrs","$timeout",function(t,s,c,d){function m(e){e.promise.then(p)}function f(t,n,r){var o=e.get(t,i(s)),a=h(t,n),c={state:o||{name:t},params:n,hash:a};return C.push(c),w[a]=r,function(){var e=C.indexOf(c);e!==-1&&C.splice(e,1)}}function h(e,n){if(!u.isString(e))throw new Error("state should be a string");return u.isObject(n)?e+l.toJson(n):(n=t.$eval(n),u.isObject(n)?e+l.toJson(n):e)}function p(){for(var e=0;e0)){var n=f(e,t,E);return p(),n}},t.$on("$stateChangeSuccess",p),t.$on("$destroy",o.onStart({},m)),a.globals.transition&&m(a.globals.transition),p()}]}}];c.module("ui.router.state").directive("uiSref",m).directive("uiSrefActive",h).directive("uiSrefActiveEq",h).directive("uiState",f)},function(e,t,n){"use strict";function r(e){var t=function(t,n,r){return e.is(t,n,r)};return t.$stateful=!0,t}function i(e){var t=function(t,n,r){return e.includes(t,n,r)};return t.$stateful=!0,t}var o=n(57);r.$inject=["$state"],t.$IsStateFilter=r,i.$inject=["$state"],t.$IncludedByStateFilter=i,o.module("ui.router.state").filter("isState",r).filter("includedByState",i)},function(e,t,n){"use strict";function r(e,t,n,r,c){var h=l.parse("viewDecl.controllerAs"),p=l.parse("viewDecl.resolveAs");return{restrict:"ECA",priority:-400,compile:function(r){var c=r.html();return function(r,l){var g=l.data("$uiView");if(g){var v=g.$cfg||{viewDecl:{}};l.html(v.template||c),s.trace.traceUIViewFill(g.$uiView,l.html());var b=e(l.contents()),$=v.controller,y=h(v),E=p(v),C=v.path&&new u.ResolveContext(v.path),w=C&&m.getLocals(C);if(r[E]=w,$){var x=t($,o.extend({},w,{$scope:r,$element:l}));y&&(r[y]=x,r[y][E]=w),l.data("$ngControllerController",x),l.children().data("$ngControllerController",x),i(n,x,r,v)}if(a.isString(v.viewDecl.component))var k=v.viewDecl.component,M=d.kebobString(k),A=function(){var e=[].slice.call(l[0].children).filter(function(e){return e&&e.tagName&&e.tagName.toLowerCase()===M});return e&&f.element(e).data("$"+k+"Controller")},T=r.$watch(A,function(e){e&&(i(n,e,r,v),T())});b(r)}}}}}function i(e,t,n,r){!a.isFunction(t.$onInit)||r.viewDecl.component&&p||t.$onInit();var i=o.tail(r.path).state.self,s={bind:t};if(a.isFunction(t.uiOnParamsChanged)){var c=new u.ResolveContext(r.path),l=c.getResolvable("$transition$").data,d=function(e){if(e!==l&&e.exiting().indexOf(i)===-1){var n=e.params("to"),r=e.params("from"),a=e.treeChanges().to.map(function(e){return e.paramSchema}).reduce(o.unnestR,[]),s=e.treeChanges().from.map(function(e){return e.paramSchema}).reduce(o.unnestR,[]),c=a.filter(function(e){var t=s.indexOf(e);return t===-1||!s[t].type.equals(n[e.id],r[e.id])});if(c.length){var u=c.map(function(e){return e.id});t.uiOnParamsChanged(o.filter(n,function(e,t){return u.indexOf(t)!==-1}),e)}}};n.$on("$destroy",e.onSuccess({},d,s))}if(a.isFunction(t.uiCanExit)){var m={exiting:i.name};n.$on("$destroy",e.onBefore(m,t.uiCanExit,s))}}var o=n(3),a=n(4),s=n(12),c=n(55),l=n(5),u=n(17),d=n(9),m=n(53),f=n(57),h=["$view","$animate","$uiViewScroll","$interpolate","$q",function(e,t,n,r,i){function o(e,n){return{enter:function(e,n,r){f.version.minor>2?t.enter(e,null,n).then(r):t.enter(e,null,n,r)},leave:function(e,n){f.version.minor>2?t.leave(e).then(n):t.leave(e,n)}}}function u(e,t){return e===t}var d={$cfg:{viewDecl:{$context:e.rootContext()}},$uiView:{}},m={count:0,restrict:"ECA",terminal:!0,priority:400,transclude:"element",compile:function(t,f,h){return function(t,f,p){function g(e){(!e||e instanceof c.Ng1ViewConfig)&&(u(M,e)||(s.trace.traceUIViewConfigUpdated(S,e&&e.viewDecl&&e.viewDecl.$context),M=e,b(e)))}function v(){if($&&(s.trace.traceUIViewEvent("Removing (previous) el",$.data("$uiView")),$.remove(),$=null),E&&(s.trace.traceUIViewEvent("Destroying scope",S),E.$destroy(),E=null),y){var e=y.data("$uiViewAnim");s.trace.traceUIViewEvent("Animate out",e),k.leave(y,function(){e.$$animLeave.resolve(),$=null}),$=y,y=null}}function b(e){var r=t.$new(),o=i.defer(),s=i.defer(),c={$cfg:e,$uiView:S},l={$animEnter:o.promise,$animLeave:s.promise,$$animLeave:s},u=h(r,function(e){e.data("$uiViewAnim",l),e.data("$uiView",c),k.enter(e,f,function(){o.resolve(),E&&E.$emit("$viewContentAnimationEnded"),(a.isDefined(x)&&!x||t.$eval(x))&&n(e)}),v()});y=u,E=r,E.$emit("$viewContentLoaded",e||M),E.$eval(w)}var $,y,E,C,w=p.onload||"",x=p.autoscroll,k=o(p,t),M=void 0,A=f.inheritedData("$uiView")||d,T=r(p.uiView||p.name||"")(t)||"$default",S={ +$type:"ng1",id:m.count++,name:T,fqn:A.$uiView.fqn?A.$uiView.fqn+"."+T:T,config:null,configUpdated:g,get creationContext(){return l.parse("$cfg.viewDecl.$context")(A)}};s.trace.traceUIViewEvent("Linking",S),f.data("$uiView",{$uiView:S}),b(),C=e.registerUIView(S),t.$on("$destroy",function(){s.trace.traceUIViewEvent("Destroying/Unregistering",S),C()})}}};return m}];r.$inject=["$compile","$controller","$transitions","$view","$timeout"];var p="function"==typeof f.module("ui.router").component;f.module("ui.router.state").directive("uiView",h),f.module("ui.router.state").directive("uiView",r)},function(e,t,n){"use strict";function r(){var e=!1;this.useAnchorScroll=function(){e=!0},this.$get=["$anchorScroll","$timeout",function(t,n){return e?t:function(e){return n(function(){e[0].scrollIntoView()},0,!1)}}]}var i=n(57);i.module("ui.router.state").provider("$uiViewScroll",r)}])})},237:function(e,t,n){n(238),e.exports="ngAria"},238:function(e,t){/** + * @license AngularJS v1.5.8 + * (c) 2010-2016 Google, Inc. http://angularjs.org + * License: MIT + */ +!function(e,t){"use strict";function n(){function e(e,t,r,i){return function(a,s,c){var l=c.$normalize(t);!n[l]||o(s,r)||c[l]||a.$watch(c[e],function(e){e=i?!e:!!e,s.attr(t,e)})}}var n={ariaHidden:!0,ariaChecked:!0,ariaReadonly:!0,ariaDisabled:!0,ariaRequired:!0,ariaInvalid:!0,ariaValue:!0,tabindex:!0,bindKeypress:!0,bindRoleForClick:!0};this.config=function(e){n=t.extend(n,e)},this.$get=function(){return{config:function(e){return n[e]},$$watchExpr:e}}}var r=t.module("ngAria",["ng"]).provider("$aria",n),i=["BUTTON","A","INPUT","TEXTAREA","SELECT","DETAILS","SUMMARY"],o=function(e,t){if(t.indexOf(e[0].nodeName)!==-1)return!0};r.directive("ngShow",["$aria",function(e){return e.$$watchExpr("ngShow","aria-hidden",[],!0)}]).directive("ngHide",["$aria",function(e){return e.$$watchExpr("ngHide","aria-hidden",[],!1)}]).directive("ngValue",["$aria",function(e){return e.$$watchExpr("ngValue","aria-checked",i,!1)}]).directive("ngChecked",["$aria",function(e){return e.$$watchExpr("ngChecked","aria-checked",i,!1)}]).directive("ngReadonly",["$aria",function(e){return e.$$watchExpr("ngReadonly","aria-readonly",i,!1)}]).directive("ngRequired",["$aria",function(e){return e.$$watchExpr("ngRequired","aria-required",i,!1)}]).directive("ngModel",["$aria",function(e){function t(t,n,r,a){return e.config(n)&&!r.attr(t)&&(a||!o(r,i))}function n(e,t){return!t.attr("role")&&t.attr("type")===e&&"INPUT"!==t[0].nodeName}function r(e,t){var n=e.type,r=e.role;return"checkbox"===(n||r)||"menuitemcheckbox"===r?"checkbox":"radio"===(n||r)||"menuitemradio"===r?"radio":"range"===n||"progressbar"===r||"slider"===r?"range":""}return{restrict:"A",require:"ngModel",priority:200,compile:function(i,o){var a=r(o,i);return{pre:function(e,t,n,r){"checkbox"===a&&(r.$isEmpty=function(e){return e===!1})},post:function(r,i,o,s){function c(){return s.$modelValue}function l(e){var t=o.value==s.$viewValue;i.attr("aria-checked",t)}function u(){i.attr("aria-checked",!s.$isEmpty(s.$viewValue))}var d=t("tabindex","tabindex",i,!1);switch(a){case"radio":case"checkbox":n(a,i)&&i.attr("role",a),t("aria-checked","ariaChecked",i,!1)&&r.$watch(c,"radio"===a?l:u),d&&i.attr("tabindex",0);break;case"range":if(n(a,i)&&i.attr("role","slider"),e.config("ariaValue")){var m=!i.attr("aria-valuemin")&&(o.hasOwnProperty("min")||o.hasOwnProperty("ngMin")),f=!i.attr("aria-valuemax")&&(o.hasOwnProperty("max")||o.hasOwnProperty("ngMax")),h=!i.attr("aria-valuenow");m&&o.$observe("min",function(e){i.attr("aria-valuemin",e)}),f&&o.$observe("max",function(e){i.attr("aria-valuemax",e)}),h&&r.$watch(c,function(e){i.attr("aria-valuenow",e)})}d&&i.attr("tabindex",0)}!o.hasOwnProperty("ngRequired")&&s.$validators.required&&t("aria-required","ariaRequired",i,!1)&&o.$observe("required",function(){i.attr("aria-required",!!o.required)}),t("aria-invalid","ariaInvalid",i,!0)&&r.$watch(function(){return s.$invalid},function(e){i.attr("aria-invalid",!!e)})}}}}}]).directive("ngDisabled",["$aria",function(e){return e.$$watchExpr("ngDisabled","aria-disabled",i,!1)}]).directive("ngMessages",function(){return{restrict:"A",require:"?ngMessages",link:function(e,t,n,r){t.attr("aria-live")||t.attr("aria-live","assertive")}}}).directive("ngClick",["$aria","$parse",function(e,t){return{restrict:"A",compile:function(n,r){var a=t(r.ngClick,null,!0);return function(t,n,r){o(n,i)||(e.config("bindRoleForClick")&&!n.attr("role")&&n.attr("role","button"),e.config("tabindex")&&!n.attr("tabindex")&&n.attr("tabindex",0),e.config("bindKeypress")&&!r.ngKeypress&&n.on("keypress",function(e){function n(){a(t,{$event:e})}var r=e.which||e.keyCode;32!==r&&13!==r||t.$apply(n)}))}}}}]).directive("ngDblclick",["$aria",function(e){return function(t,n,r){!e.config("tabindex")||n.attr("tabindex")||o(n,i)||n.attr("tabindex",0)}}])}(window,window.angular)},239:function(e,t,n){n(1),n(240),n(237),n(242),e.exports="ngMaterial"},240:function(e,t,n){n(241),e.exports="ngAnimate"},241:function(e,t){/** + * @license AngularJS v1.5.8 + * (c) 2010-2016 Google, Inc. http://angularjs.org + * License: MIT + */ +!function(e,t){"use strict";function n(e,t,n){if(!e)throw pe("areq","Argument '{0}' is {1}",t||"?",n||"required");return e}function r(e,t){return e||t?e?t?(G(e)&&(e=e.join(" ")),G(t)&&(t=t.join(" ")),e+" "+t):e:t:""}function i(e){var t={};return e&&(e.to||e.from)&&(t.to=e.to,t.from=e.from),t}function o(e,t,n){var r="";return e=G(e)?e:e&&ee(e)&&e.length?e.split(/\s+/):[],K(e,function(e,i){e&&e.length>0&&(r+=i>0?" ":"",r+=n?t+e:e+t)}),r}function a(e,t){var n=e.indexOf(t);t>=0&&e.splice(n,1)}function s(e){if(e instanceof ne)switch(e.length){case 0:return e;case 1:if(e[0].nodeType===P)return e;break;default:return ne(c(e))}if(e.nodeType===P)return ne(e)}function c(e){if(!e[0])return e;for(var t=0;t=0)&&(n=T(n)),0===n&&(n=null),r[t]=n}}),r}function T(e){var t=0,n=e.split(/\s*,\s*/);return K(n,function(e){"s"==e.charAt(e.length-1)&&(e=e.substring(0,e.length-1)),e=parseFloat(e)||0,t=t?Math.max(e,t):e}),t}function S(e){return 0===e||null!=e}function _(e,t){var n=I,r=e+"s";return t?n+=ie:r+=" linear all",[n,r]}function N(){var e=Object.create(null);return{flush:function(){e=Object.create(null)},count:function(t){var n=e[t];return n?n.total:0},get:function(t){var n=e[t];return n&&n.value},put:function(t,n){e[t]?e[t].total++:e[t]={total:1,value:n}}}}function D(e,t,n){K(n,function(n){e[n]=Q(e[n])?e[n]:t.style.getPropertyValue(n)})}var I,O,R,H,P=1,F="-add",L="-remove",j="ng-",U="-active",V="-prepare",q="ng-animate",B="$$ngAnimateChildren",z="";void 0===e.ontransitionend&&void 0!==e.onwebkittransitionend?(z="-webkit-",I="WebkitTransition",O="webkitTransitionEnd transitionend"):(I="transition",O="transitionend"),void 0===e.onanimationend&&void 0!==e.onwebkitanimationend?(z="-webkit-",R="WebkitAnimation",H="webkitAnimationEnd animationend"):(R="animation",H="animationend");var W,Y,K,G,Q,X,Z,J,ee,te,ne,re,ie="Duration",oe="Property",ae="Delay",se="TimingFunction",ce="IterationCount",le="PlayState",ue=9999,de=R+ae,me=R+ie,fe=I+ae,he=I+ie,pe=t.$$minErr("ng"),ge=["$$rAF",function(e){function t(e){r=r.concat(e),n()}function n(){if(r.length){for(var t=r.shift(),o=0;o0&&(l=n.get(s),!l)){var u=o(a,"-stagger");r.addClass(i,u),l=A(e,i,c),l.animationDuration=Math.max(l.animationDuration,0),l.transitionDuration=Math.max(l.transitionDuration,0),r.removeClass(i,u),n.put(s,l)}return l||{}}function T(e){q.push(e),g.waitUntilQuiet(function(){t.flush(),n.flush();for(var e=l(),r=0;r=ne&&r>=ie&&(Z=!0,g())}function q(){function t(){if(!Q){if(y(!1),K(le,function(e){var t=e[0],n=e[1];Y.style[t]=n}),P(e,B),r.addClass(e,ke),Le.recalculateTimingStyles){if(xe=Y.className+" "+Ce,Te=$(Y,xe),Pe=N(Y,xe,Te),Fe=Pe.maxDelay,te=Math.max(Fe,0),ie=Pe.maxDuration,0===ie)return void g();Le.hasTransitions=Pe.transitionDuration>0,Le.hasAnimations=Pe.animationDuration>0}if(Le.applyAnimationDelay&&(Fe="boolean"!=typeof B.delay&&S(B.delay)?parseFloat(B.delay):Fe,te=Math.max(Fe,0),Pe.animationDelay=Fe,je=M(Fe,!0),le.push(je),Y.style[je[0]]=je[1]),ne=te*$e,ae=ie*$e,B.easing){var t,i=B.easing;Le.hasTransitions&&(t=I+se,le.push([t,i]),Y.style[t]=i),Le.hasAnimations&&(t=R+se,le.push([t,i]),Y.style[t]=i)}Pe.transitionDuration&&fe.push(O),Pe.animationDuration&&fe.push(H),ce=Date.now();var o=ne+Ee*ae,a=ce+o,s=e.data(be)||[],l=!0;if(s.length){var u=s[0];l=a>u.expectedEndTime,l?c.cancel(u.timer):s.push(g)}if(l){var d=c(n,o,!1);s[0]={timer:d,expectedEndTime:a},s.push(g),e.data(be,s)}fe.length&&e.on(fe.join(" "),V),B.to&&(B.cleanupStyles&&D(z,Y,Object.keys(B.to)),p(e,B))}}function n(){var t=e.data(be);if(t){for(var n=1;n0&&(Pe.transitionDuration&&0===Se.transitionDuration||Pe.animationDuration&&0===Se.animationDuration)&&Math.max(Se.animationDelay,Se.transitionDelay);o?c(t,Math.floor(o*Re*$e),!1):t(),ee.resume=function(){i(!0)},ee.pause=function(){i(!1)}}}var B=n||{};B.$$prepared||(B=m(W(B)));var z={},Y=b(e);if(!Y||!Y.parentNode||!v.enabled())return A();var Q,X,Z,J,ee,te,ne,ie,ae,ce,le=[],de=e.attr("class"),me=i(B),fe=[];if(0===B.duration||!u.animations&&!u.transitions)return A();var he=B.event&&G(B.event)?B.event.join(" "):B.event,pe=he&&B.structural,ge="",ve="";pe?ge=o(he,j,!0):he&&(ge=he),B.addClass&&(ve+=o(B.addClass,F)),B.removeClass&&(ve.length&&(ve+=" "),ve+=o(B.removeClass,L)),B.applyClassesEarly&&ve.length&&P(e,B);var Ce=[ge,ve].join(" ").trim(),xe=de+" "+Ce,ke=o(Ce,U),Me=me.to&&Object.keys(me.to).length>0,Ae=(B.keyframeStyle||"").length>0;if(!Ae&&!Me&&!Ce)return A();var Te,Se;if(B.stagger>0){var _e=parseFloat(B.stagger);Se={transitionDelay:_e,animationDelay:_e,transitionDuration:0,animationDuration:0}}else Te=$(Y,xe),Se=x(Y,Ce,Te,we);B.$$skipPreparationClasses||r.addClass(e,Ce);var Ne;if(B.transitionStyle){var De=[I,B.transitionStyle];w(Y,De),le.push(De)}if(B.duration>=0){Ne=Y.style[I].length>0;var Ie=_(B.duration,Ne);w(Y,Ie),le.push(Ie)}if(B.keyframeStyle){var Oe=[R,B.keyframeStyle];w(Y,Oe),le.push(Oe)}var Re=Se?B.staggerIndex>=0?B.staggerIndex:t.count(Te):0,He=0===Re;He&&!B.skipBlocking&&E(Y,ue);var Pe=N(Y,xe,Te),Fe=Pe.maxDelay;te=Math.max(Fe,0),ie=Pe.maxDuration;var Le={};if(Le.hasTransitions=Pe.transitionDuration>0,Le.hasAnimations=Pe.animationDuration>0,Le.hasTransitionAll=Le.hasTransitions&&"all"==Pe.transitionProperty,Le.applyTransitionDuration=Me&&(Le.hasTransitions&&!Le.hasTransitionAll||Le.hasAnimations&&!Le.hasTransitions),Le.applyAnimationDuration=B.duration&&Le.hasAnimations,Le.applyTransitionDelay=S(B.delay)&&(Le.applyTransitionDuration||Le.hasTransitions),Le.applyAnimationDelay=S(B.delay)&&Le.hasAnimations,Le.recalculateTimingStyles=ve.length>0,(Le.applyTransitionDuration||Le.applyAnimationDuration)&&(ie=B.duration?parseFloat(B.duration):ie,Le.applyTransitionDuration&&(Le.hasTransitions=!0,Pe.transitionDuration=ie,Ne=Y.style[I+oe].length>0,le.push(_(ie,Ne))),Le.applyAnimationDuration&&(Le.hasAnimations=!0,Pe.animationDuration=ie,le.push(k(ie)))),0===ie&&!Le.recalculateTimingStyles)return A();if(null!=B.delay){var je;"boolean"!=typeof B.delay&&(je=parseFloat(B.delay),te=Math.max(je,0)),Le.applyTransitionDelay&&le.push(M(je)),Le.applyAnimationDelay&&le.push(M(je,!0))}return null==B.duration&&Pe.transitionDuration>0&&(Le.recalculateTimingStyles=Le.recalculateTimingStyles||He),ne=te*$e,ae=ie*$e,B.skipBlocking||(Le.blockTransition=Pe.transitionDuration>0,Le.blockKeyframeAnimation=Pe.animationDuration>0&&Se.animationDelay>0&&0===Se.animationDuration),B.from&&(B.cleanupStyles&&D(z,Y,Object.keys(B.from)),h(e,B)),Le.blockTransition||Le.blockKeyframeAnimation?y(ie):B.skipBlocking||E(Y,!1),{$$willAnimate:!0,end:l,start:function(){if(!Q)return ee={end:l,cancel:d,resume:null,pause:null},J=new s(ee),T(q),J}}}}]}],ke=["$$animationProvider",function(e){function t(e){return e.parentNode&&11===e.parentNode.nodeType}e.drivers.push("$$animateCssDriver");var n="ng-animate-shim",r="ng-anchor",i="ng-anchor-out",o="ng-anchor-in";this.$get=["$animateCss","$rootScope","$$AnimateRunner","$rootElement","$sniffer","$$jqLite","$document",function(e,a,s,c,l,u,m){function f(e){return e.replace(/\bng-\S+\b/g,"")}function h(e,t){return ee(e)&&(e=e.split(" ")),ee(t)&&(t=t.split(" ")),e.filter(function(e){return t.indexOf(e)===-1}).join(" ")}function p(t,a,c){function l(e){var t={},n=b(e).getBoundingClientRect();return K(["width","height","top","left"],function(e){var r=n[e];switch(e){case"top":r+=$.scrollTop;break;case"left":r+=$.scrollLeft}t[e]=Math.floor(r)+"px"}),t}function u(){var t=e(g,{addClass:i,delay:!0,from:l(a)});return t.$$willAnimate?t:null}function d(e){return e.attr("class")||""}function m(){var t=f(d(c)),n=h(t,v),r=h(v,t),a=e(g,{to:l(c),addClass:o+" "+n,removeClass:i+" "+r,delay:!0});return a.$$willAnimate?a:null}function p(){g.remove(),a.removeClass(n),c.removeClass(n)}var g=ne(b(a).cloneNode(!0)),v=f(d(g));a.addClass(n),c.addClass(n),g.addClass(r),E.append(g);var y,C=u();if(!C&&(y=m(),!y))return p();var w=C||y;return{start:function(){function e(){n&&n.end()}var t,n=w.start();return n.done(function(){return n=null,!y&&(y=m())?(n=y.start(),n.done(function(){n=null,p(),t.complete()}),n):(p(),void t.complete())}),t=new s({end:e,cancel:e})}}}function g(e,t,n,r){var i=v(e,re),o=v(t,re),a=[];if(K(r,function(e){var t=e.out,r=e["in"],i=p(n,t,r);i&&a.push(i)}),i||o||0!==a.length)return{start:function(){function e(){K(t,function(e){e.end()})}var t=[];i&&t.push(i.start()),o&&t.push(o.start()),K(a,function(e){t.push(e.start())});var n=new s({end:e,cancel:e});return s.all(t,function(e){n.complete(e)}),n}}}function v(t){var n=t.element,r=t.options||{};t.structural&&(r.event=t.event,r.structural=!0,r.applyClassesEarly=!0,"leave"===t.event&&(r.onDone=r.domOperation)),r.preparationClasses&&(r.event=x(r.event,r.preparationClasses));var i=e(n,r);return i.$$willAnimate?i:null}if(!l.animations&&!l.transitions)return re;var $=m[0].body,y=b(c),E=ne(t(y)||$.contains(y)?y:$);d(u);return function(e){return e.from&&e.to?g(e.from,e.to,e.classes,e.anchors):v(e)}}]}],Me=["$animateProvider",function(e){this.$get=["$injector","$$AnimateRunner","$$jqLite",function(t,n,r){function i(n){n=G(n)?n:n.split(" ");for(var r=[],i={},o=0;o0,r=(e.removeClass||"").length>0;return t?n&&r:n||r}var l=1,u=2,h=" ",p=this.rules={skip:[],cancel:[],join:[]};p.join.push(function(e,t,n){return!t.structural&&a(t)}),p.skip.push(function(e,t,n){return!t.structural&&!a(t)}),p.skip.push(function(e,t,n){return"leave"==n.event&&t.structural}),p.skip.push(function(e,t,n){return n.structural&&n.state===u&&!t.structural}),p.cancel.push(function(e,t,n){return n.structural&&t.structural}),p.cancel.push(function(e,t,n){return n.state===u&&t.structural}),p.cancel.push(function(e,t,n){if(n.structural)return!1;var r=t.addClass,o=t.removeClass,a=n.addClass,s=n.removeClass;return!(te(r)&&te(o)||te(a)&&te(s))&&(i(r,s)||i(o,a))}),this.$get=["$$rAF","$rootScope","$rootElement","$document","$$HashMap","$$animation","$$AnimateRunner","$templateRequest","$$jqLite","$$forceReflow",function(r,i,h,p,v,E,C,w,x,k){function M(){var e=!1;return function(t){e?t():i.$$postDigest(function(){e=!0,t()})}}function A(e,t){return g(e,t,{})}function T(e,t,n){var r=b(t),i=b(e),o=[],a=V[n];return a&&K(a,function(e){re.call(e.node,r)?o.push(e.callback):"leave"===n&&re.call(e.node,i)&&o.push(e.callback)}),o}function S(e,t,n){var r=c(t);return e.filter(function(e){var t=e.node===r&&(!n||e.callback===n);return!t})}function _(e,t){"close"!==e||t[0].parentNode||ie.off(t)}function N(e,t,n){function c(t,n,i,o){k(function(){var t=T(v,e,n);t.length?r(function(){K(t,function(t){t(e,i,o)}),_(i,e)}):_(i,e)}),t.progress(n,i,o)}function d(t){y(e,w),Z(e,w),f(e,w),w.domOperation(),x.complete(!t)}var h,v,w=W(n);e=s(e),e&&(h=b(e),v=e.parent()),w=m(w);var x=new C,k=M();if(G(w.addClass)&&(w.addClass=w.addClass.join(" ")),w.addClass&&!ee(w.addClass)&&(w.addClass=null),G(w.removeClass)&&(w.removeClass=w.removeClass.join(" ")),w.removeClass&&!ee(w.removeClass)&&(w.removeClass=null),w.from&&!J(w.from)&&(w.from=null),w.to&&!J(w.to)&&(w.to=null),!h)return d(),x;var S=[h.className,w.addClass,w.removeClass].join(" ");if(!z(S))return d(),x;var N=["enter","move","leave"].indexOf(t)>=0,O=p[0].hidden,P=!j||O||L.get(h),U=!P&&F.get(h)||{},V=!!U.state;if(P||V&&U.state==l||(P=!R(e,v,t)),P)return O&&c(x,t,"start"),d(),O&&c(x,t,"close"),x;N&&D(e);var q={structural:N,element:e,event:t,addClass:w.addClass,removeClass:w.removeClass,close:d,options:w,runner:x};if(V){var B=o("skip",e,q,U);if(B)return U.state===u?(d(),x):(g(e,U,q),U.runner);var Y=o("cancel",e,q,U);if(Y)if(U.state===u)U.runner.end();else{if(!U.structural)return g(e,U,q),U.runner;U.close()}else{var Q=o("join",e,q,U);if(Q){if(U.state!==u)return $(e,N?t:null,w),t=q.event=U.event,w=g(e,U,q),U.runner;A(e,q)}}}else A(e,q);var X=q.structural;if(X||(X="animate"===q.event&&Object.keys(q.options.to||{}).length>0||a(q)),!X)return d(),I(e),x;var te=(U.counter||0)+1;return q.counter=te,H(e,l,q),i.$$postDigest(function(){var n=F.get(h),r=!n;n=n||{};var i=e.parent()||[],o=i.length>0&&("animate"===n.event||n.structural||a(n));if(r||n.counter!==te||!o)return r&&(Z(e,w),f(e,w)),(r||N&&n.event!==t)&&(w.domOperation(),x.end()),void(o||I(e));t=!n.structural&&a(n,!0)?"setClass":n.event,H(e,u);var s=E(e,t,n.options);x.setHost(s),c(x,t,"start",{}),s.done(function(n){d(!n);var r=F.get(h);r&&r.counter===te&&I(b(e)),c(x,t,"close",{})})}),x}function D(e){var t=b(e),n=t.querySelectorAll("["+Te+"]");K(n,function(e){var t=parseInt(e.getAttribute(Te)),n=F.get(e);if(n)switch(t){case u:n.runner.end();case l:F.remove(e)}})}function I(e){var t=b(e);t.removeAttribute(Te),F.remove(t)}function O(e,t){return b(e)===b(t)}function R(e,t,n){var r,i=ne(p[0].body),o=O(e,i)||"HTML"===e[0].nodeName,a=O(e,h),s=!1,c=L.get(b(e)),l=ne.data(e[0],Se);for(l&&(t=l),t=b(t);t&&(a||(a=O(t,h)),t.nodeType===P);){var u=F.get(t)||{};if(!s){var d=L.get(t);if(d===!0&&c!==!1){c=!0;break}d===!1&&(c=!1),s=u.structural}if(te(r)||r===!0){var m=ne.data(t,B);Q(m)&&(r=m)}if(s&&r===!1)break;if(o||(o=O(t,i)),o&&a)break;t=a||!(l=ne.data(t,Se))?t.parentNode:b(l)}var f=(!s||r)&&c!==!0;return f&&a&&o}function H(e,t,n){n=n||{},n.state=t;var r=b(e);r.setAttribute(Te,t);var i=F.get(r),o=i?Y(i,n):n;F.put(r,o)}var F=new v,L=new v,j=null,U=i.$watch(function(){return 0===w.totalPendingRequests},function(e){e&&(U(),i.$$postDigest(function(){i.$$postDigest(function(){null===j&&(j=!0)})}))}),V=Object.create(null),q=t.classNameFilter(),z=q?function(e){return q.test(e)}:function(){return!0},Z=d(x),re=e.Node.prototype.contains||function(e){return this===e||!!(16&this.compareDocumentPosition(e))},ie={on:function(e,t,n){var r=c(t);V[e]=V[e]||[],V[e].push({node:r,callback:n}),ne(t).on("$destroy",function(){var i=F.get(r);i||ie.off(e,t,n)})},off:function(e,t,n){if(1!==arguments.length||ee(arguments[0])){var r=V[e];r&&(V[e]=1===arguments.length?null:S(r,t,n))}else{t=arguments[0];for(var i in V)V[i]=S(V[i],t)}},pin:function(e,t){n(X(e),"element","not an element"),n(X(t),"parentElement","not an element"),e.data(Se,t)},push:function(e,t,n,r){return n=n||{},n.domOperation=r,N(e,t,n)},enabled:function(e,t){var n=arguments.length;if(0===n)t=!!j;else{var r=X(e);if(r){var i=b(e);1===n?t=!L.get(i):L.put(i,!t)}else t=j=!!e}return t}};return ie}]}],Ne=["$animateProvider",function(e){function t(e,t){e.data(s,t)}function n(e){e.removeData(s)}function i(e){return e.data(s)}var o="ng-animate-ref",a=this.drivers=[],s="$$animationRunner";this.$get=["$$jqLite","$rootScope","$injector","$$AnimateRunner","$$HashMap","$$rAFScheduler",function(e,s,c,l,u,h){function p(e){function t(e){if(e.processed)return e;e.processed=!0;var n=e.domNode,r=n.parentNode;o.put(n,e);for(var a;r;){if(a=o.get(r)){a.processed||(a=t(a));break}r=r.parentNode}return(a||i).children.push(e),e}function n(e){var t,n=[],r=[];for(t=0;t=0,l=e.structural?y(a):[];if(l.length){var u=c?"to":"from";K(l,function(e){var t=e.getAttribute(o);n[t]=n[t]||{},n[t][u]={animationID:r,element:ne(e)}})}else t.push(e)});var r={},i={};return K(n,function(n,o){var a=n.from,s=n.to;if(!a||!s){var c=a?a.animationID:s.animationID,l=c.toString();return void(r[l]||(r[l]=!0,t.push(e[c])))}var u=e[a.animationID],d=e[s.animationID],m=a.animationID.toString();if(!i[m]){var f=i[m]={structural:!0,beforeStart:function(){u.beforeStart(),d.beforeStart()},close:function(){u.close(),d.close()},classes:C(u.classes,d.classes),from:u,to:d,anchors:[]};f.classes.length?t.push(f):(t.push(u),t.push(d))}i[m].anchors.push({out:a.element,"in":s.element})}),t}function C(e,t){e=e.split(" "),t=t.split(" ");for(var n=[],r=0;r=0;t--){var n=a[t],r=c.get(n),i=r(e);if(i)return i}}function x(){u.addClass(q),N&&e.addClass(u,N),D&&(e.removeClass(u,D),D=null)}function k(e,t){function n(e){var n=i(e);n&&n.setHost(t)}e.from&&e.to?(n(e.from.element),n(e.to.element)):n(e.element)}function M(){var e=i(u);!e||"leave"===d&&$.$$domOperationFired||e.end()}function A(t){u.off("$destroy",M),n(u),v(u,$),f(u,$),$.domOperation(),N&&e.removeClass(u,N),u.removeClass(q),S.complete(!t)}$=m($);var T=["enter","move","leave"].indexOf(d)>=0,S=new l({end:function(){A()},cancel:function(){A(!0)}});if(!a.length)return A(),S;t(u,S);var _=r(u.attr("class"),r($.addClass,$.removeClass)),N=$.tempClasses;N&&(_+=" "+N,$.tempClasses=null);var D;return T&&(D="ng-"+d+V,e.addClass(u,D)),g.push({element:u,classes:_,event:d,structural:T,options:$,beforeStart:x,close:A}),u.on("$destroy",M),g.length>1?S:(s.$$postDigest(function(){var e=[];K(g,function(t){i(t.element)?e.push(t):t.close()}),g.length=0;var t=E(e),n=[];K(t,function(e){n.push({domNode:b(e.from?e.from.element:e.element),fn:function(){e.beforeStart();var t,n=e.close,r=e.anchors?e.from.element||e.to.element:e.element;if(i(r)){var o=w(e);o&&(t=o.start)}if(t){var a=t();a.done(function(e){n(!e)}),k(e,a)}else n()}})}),h(p(n))}),S)}}]}],De=["$animate","$rootScope",function(e,t){return{restrict:"A",transclude:"element",terminal:!0,priority:600,link:function(t,n,r,i,o){var a,s;t.$watchCollection(r.ngAnimateSwap||r["for"],function(r){a&&e.leave(a),s&&(s.$destroy(),s=null),(r||0===r)&&(s=t.$new(),o(s,function(t){a=t,e.enter(t,null,n)}))})}}}];t.module("ngAnimate",[],function(){re=t.noop,W=t.copy,Y=t.extend,ne=t.element,K=t.forEach,G=t.isArray,ee=t.isString,J=t.isObject,te=t.isUndefined,Q=t.isDefined,Z=t.isFunction,X=t.isElement}).directive("ngAnimateSwap",De).directive("ngAnimateChildren",ve).factory("$$rAFScheduler",ge).provider("$$animateQueue",_e).provider("$$animation",Ne).provider("$animateCss",xe).provider("$$animateCssDriver",ke).provider("$$animateJs",Me).provider("$$animateJsDriver",Ae)}(window,window.angular)},242:function(e,t){/*! + * Angular Material Design + * https://github.com/angular/material + * @license MIT + * v1.1.1 + */ +!function(e,t,n){"use strict";!function(){t.module("ngMaterial",["ng","ngAnimate","ngAria","material.core","material.core.gestures","material.core.layout","material.core.meta","material.core.theming.palette","material.core.theming","material.core.animate","material.components.autocomplete","material.components.backdrop","material.components.bottomSheet","material.components.button","material.components.card","material.components.chips","material.components.checkbox","material.components.colors","material.components.content","material.components.datepicker","material.components.dialog","material.components.divider","material.components.fabActions","material.components.fabShared","material.components.fabSpeedDial","material.components.fabToolbar","material.components.gridList","material.components.icon","material.components.input","material.components.list","material.components.menu","material.components.menuBar","material.components.navBar","material.components.panel","material.components.progressCircular","material.components.progressLinear","material.components.radioButton","material.components.select","material.components.showHide","material.components.sidenav","material.components.slider","material.components.sticky","material.components.subheader","material.components.swipe","material.components.switch","material.components.tabs","material.components.toast","material.components.toolbar","material.components.tooltip","material.components.virtualRepeat","material.components.whiteframe"])}(),function(){function e(e,t){if(t.has("$swipe")){var n="You are using the ngTouch module. \nAngular Material already has mobile click, tap, and swipe support... \nngTouch is not supported with Angular Material!";e.warn(n)}}function n(e,t){e.decorator("$$rAF",["$delegate",r]),t.theme("default").primaryPalette("indigo").accentPalette("pink").warnPalette("deep-orange").backgroundPalette("grey")}function r(e){return e.throttle=function(t){var n,r,i,o;return function(){n=arguments,o=this,i=t,r||(r=!0,e(function(){i.apply(o,Array.prototype.slice.call(n)),r=!1}))}},e}e.$inject=["$log","$injector"],n.$inject=["$provide","$mdThemingProvider"],r.$inject=["$delegate"],t.module("material.core",["ngAnimate","material.core.animate","material.core.layout","material.core.gestures","material.core.theming"]).config(n).run(e)}(),function(){function e(){return{restrict:"A",link:n}}function n(e,t,n){var r=n.mdAutoFocus||n.mdAutofocus||n.mdSidenavFocus;e.$watch(r,function(e){t.toggleClass("md-autofocus",e)})}t.module("material.core").directive("mdAutofocus",e).directive("mdAutoFocus",e).directive("mdSidenavFocus",e)}(),function(){function e(){function e(e){var t="#"===e[0]?e.substr(1):e,n=t.length/3,r=t.substr(0,n),i=t.substr(n,n),o=t.substr(2*n);return 1===n&&(r+=r,i+=i,o+=o),"rgba("+parseInt(r,16)+","+parseInt(i,16)+","+parseInt(o,16)+",0.1)"}function t(e){e=e.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i);var t=e&&4===e.length?"#"+("0"+parseInt(e[1],10).toString(16)).slice(-2)+("0"+parseInt(e[2],10).toString(16)).slice(-2)+("0"+parseInt(e[3],10).toString(16)).slice(-2):"";return t.toUpperCase()}function n(e){return e.replace(")",", 0.1)").replace("(","a(")}function r(e){return e?e.replace("rgba","rgb").replace(/,[^\),]+\)/,")"):"rgb(0,0,0)"}return{rgbaToHex:t,hexToRgba:e,rgbToRgba:n,rgbaToRgb:r}}t.module("material.core").factory("$mdColorUtil",e)}(),function(){function e(e,n,r){function i(e){var t=s+"-"+e,n=a(t),r=n.charAt(0).toLowerCase()+n.substring(1);return o(e)?e:o(n)?n:o(r)?r:e}function o(e){return t.isDefined(u.style[e])}function a(e){return e.replace(l,function(e,t,n,r){return r?n.toUpperCase():n})}var s=e.vendorPrefix,c=/webkit/i.test(s),l=/([:\-_]+(.))/g,u=document.createElement("div"),d={isInputKey:function(e){return e.keyCode>=31&&e.keyCode<=90},isNumPadKey:function(e){return 3===e.location&&e.keyCode>=97&&e.keyCode<=105},isNavigationKey:function(e){var t=d.KEY_CODE,n=[t.SPACE,t.ENTER,t.UP_ARROW,t.DOWN_ARROW];return n.indexOf(e.keyCode)!=-1},KEY_CODE:{COMMA:188,SEMICOLON:186,ENTER:13,ESCAPE:27,SPACE:32,PAGE_UP:33,PAGE_DOWN:34,END:35,HOME:36,LEFT_ARROW:37,UP_ARROW:38,RIGHT_ARROW:39,DOWN_ARROW:40,TAB:9,BACKSPACE:8,DELETE:46},CSS:{TRANSITIONEND:"transitionend"+(c?" webkitTransitionEnd":""),ANIMATIONEND:"animationend"+(c?" webkitAnimationEnd":""),TRANSFORM:i("transform"),TRANSFORM_ORIGIN:i("transformOrigin"),TRANSITION:i("transition"),TRANSITION_DURATION:i("transitionDuration"),ANIMATION_PLAY_STATE:i("animationPlayState"),ANIMATION_DURATION:i("animationDuration"),ANIMATION_NAME:i("animationName"),ANIMATION_TIMING:i("animationTimingFunction"),ANIMATION_DIRECTION:i("animationDirection")},MEDIA:{xs:"(max-width: 599px)","gt-xs":"(min-width: 600px)",sm:"(min-width: 600px) and (max-width: 959px)","gt-sm":"(min-width: 960px)",md:"(min-width: 960px) and (max-width: 1279px)","gt-md":"(min-width: 1280px)",lg:"(min-width: 1280px) and (max-width: 1919px)","gt-lg":"(min-width: 1920px)",xl:"(min-width: 1920px)",landscape:"(orientation: landscape)",portrait:"(orientation: portrait)",print:"print"},MEDIA_PRIORITY:["xl","gt-lg","lg","gt-md","md","gt-sm","sm","gt-xs","xs","landscape","portrait","print"]};return d}e.$inject=["$sniffer","$window","$document"],t.module("material.core").factory("$mdConstant",e)}(),function(){function e(e,n){function r(){return[].concat(b)}function i(){return b.length}function o(e){return b.length&&e>-1&&e-1}function h(){return b.length?b[0]:null}function p(){return b.length?b[b.length-1]:null}function g(e,r,i,a){i=i||v;for(var s=m(r);;){if(!o(s))return null;var c=s+(e?-1:1),l=null;if(o(c)?l=b[c]:n&&(l=e?p():h(),c=m(l)),null===l||c===a)return null;if(i(l))return l;t.isUndefined(a)&&(a=c),s=c}}var v=function(){return!0};e&&!t.isArray(e)&&(e=Array.prototype.slice.call(e)),n=!!n;var b=e||[];return{items:r,count:i,inRange:o,contains:f,indexOf:m,itemAt:c,findBy:l,add:u,remove:d,first:h,last:p,next:t.bind(null,g,!1),previous:t.bind(null,g,!0),hasPrevious:s,hasNext:a}}t.module("material.core").config(["$provide",function(t){t.decorator("$mdUtil",["$delegate",function(t){return t.iterator=e,t}])}])}(),function(){function e(e,n,r){function i(e){var n=m[e];t.isUndefined(n)&&(n=m[e]=o(e));var r=h[n];return t.isUndefined(r)&&(r=a(n)),r}function o(t){return e.MEDIA[t]||("("!==t.charAt(0)?"("+t+")":t)}function a(e){var t=f[e];return t||(t=f[e]=r.matchMedia(e)),t.addListener(s),h[t.media]=!!t.matches}function s(e){n.$evalAsync(function(){h[e.media]=!!e.matches})}function c(e){return f[e]}function l(t,n){for(var r=0;r-1}function g(e){return String(e).indexOf("%")>-1}function v(e){return e[0]||e}var b=l.startSymbol(),$=l.endSymbol(),y="{{"===b&&"}}"===$,E=function(e,n,r){var i=!1;if(e&&e.length){var o=m.getComputedStyle(e[0]);i=t.isDefined(o[n])&&(!r||o[n]==r)}return i},C={dom:{},now:e.performance?t.bind(e.performance,e.performance.now):Date.now||function(){return(new Date).getTime()},bidi:function(e,n,i,o){var a=!("rtl"==r[0].dir||"rtl"==r[0].body.dir);if(0==arguments.length)return a?"ltr":"rtl";var s=t.element(e);a&&t.isDefined(i)?s.css(n,h(i)):!a&&t.isDefined(o)&&s.css(n,h(o))},bidiProperty:function(e,n,i,o){var a=!("rtl"==r[0].dir||"rtl"==r[0].body.dir),s=t.element(e);a&&t.isDefined(n)?(s.css(n,h(o)),s.css(i,"")):!a&&t.isDefined(i)&&(s.css(i,h(o)),s.css(n,""))},clientRect:function(e,t,n){var r=v(e);t=v(t||r.offsetParent||document.body);var i=r.getBoundingClientRect(),o=n?t.getBoundingClientRect():{left:0,top:0,width:0,height:0};return{left:i.left-o.left,top:i.top-o.top,width:i.width,height:i.height}},offsetRect:function(e,t){return C.clientRect(e,t,!0)},nodesToArray:function(e){e=e||[];for(var t=[],n=0;n
'),e.appendChild(r[0])),r.on("wheel",n),r.on("touchmove",n),function(){r.off("wheel"),r.off("touchmove"),r[0].parentNode.removeChild(r[0]),delete C.disableScrollAround._enableScrolling}}function a(){var e=c.parentNode,t=e.style.cssText||"",n=c.style.cssText||"",r=C.scrollTop(c),i=c.clientWidth;return c.scrollHeight>c.clientHeight+1&&(s(c,{position:"fixed",width:"100%",top:-r+"px"}),e.style.overflowY="scroll"),c.clientWidth
").css({width:"100%","z-index":-1,position:"absolute",height:"35px","overflow-y":"scroll"});e.children().css("height","60px"),r[0].body.appendChild(e[0]),this.floatingScrollbars.cached=e[0].offsetWidth==e[0].childNodes[0].offsetWidth,e.remove()}return this.floatingScrollbars.cached},forceFocus:function(t){var n=t[0]||t;document.addEventListener("click",function i(e){e.target===n&&e.$focus&&(n.focus(),e.stopImmediatePropagation(),e.preventDefault(),n.removeEventListener("click",i))},!0);var r=document.createEvent("MouseEvents");r.initMouseEvent("click",!1,!0,e,{},0,0,0,0,!1,!1,!1,!1,0,null),r.$material=!0,r.$focus=!0,n.dispatchEvent(r)},createBackdrop:function(e,t){return a(C.supplant('',[t]))(e)},supplant:function(e,t,n){return n=n||/\{([^\{\}]*)\}/g,e.replace(n,function(e,n){var r=n.split("."),i=t;try{for(var o in r)r.hasOwnProperty(o)&&(i=i[r[o]])}catch(a){i=e}return"string"==typeof i||"number"==typeof i?i:e})},fakeNgModel:function(){return{$fake:!0,$setTouched:t.noop,$setViewValue:function(e){this.$viewValue=e,this.$render(e),this.$viewChangeListeners.forEach(function(e){e()})},$isEmpty:function(e){return 0===(""+e).length},$parsers:[],$formatters:[],$viewChangeListeners:[],$render:t.noop}},debounce:function(e,t,r,i){var a;return function(){var s=r,c=Array.prototype.slice.call(arguments);o.cancel(a),a=o(function(){a=n,e.apply(s,c)},t||10,i)}},throttle:function(e,t){var n;return function(){var r=this,i=arguments,o=C.now();(!n||o-n>t)&&(e.apply(r,i),n=o)}},time:function(e){var t=C.now();return e(),C.now()-t},valueOnUse:function(e,t,n){var r=null,i=Array.prototype.slice.call(arguments),o=i.length>3?i.slice(3):[];Object.defineProperty(e,t,{get:function(){return null===r&&(r=n.apply(e,o)),r}})},nextUid:function(){return""+i++},disconnectScope:function(e){if(e&&e.$root!==e&&!e.$$destroyed){var t=e.$parent;e.$$disconnected=!0,t.$$childHead===e&&(t.$$childHead=e.$$nextSibling),t.$$childTail===e&&(t.$$childTail=e.$$prevSibling),e.$$prevSibling&&(e.$$prevSibling.$$nextSibling=e.$$nextSibling),e.$$nextSibling&&(e.$$nextSibling.$$prevSibling=e.$$prevSibling),e.$$nextSibling=e.$$prevSibling=null}},reconnectScope:function(e){if(e&&e.$root!==e&&e.$$disconnected){var t=e,n=t.$parent;t.$$disconnected=!1,t.$$prevSibling=n.$$childTail,n.$$childHead?(n.$$childTail.$$nextSibling=t,n.$$childTail=t):n.$$childHead=n.$$childTail=t}},getClosest:function(e,n,r){if(t.isString(n)){var i=n.toUpperCase();n=function(e){return e.nodeName===i}}if(e instanceof t.element&&(e=e[0]),r&&(e=e.parentNode),!e)return null;do if(n(e))return e;while(e=e.parentNode);return null},elementContains:function(n,r){var i=e.Node&&e.Node.prototype&&Node.prototype.contains,o=i?t.bind(n,n.contains):t.bind(n,function(e){return n===r||!!(16&this.compareDocumentPosition(e))});return o(r)},extractElementByName:function(e,n,r,i){function o(e){return a(e)||(r?s(e):null)}function a(e){if(e)for(var t=0,r=e.length;t");r[0].body.appendChild(n[0]);for(var i=["sticky","-webkit-sticky"],o=0;ot)&&f(n)}function r(){var e=1e3,t=C.now()-c;return i(t,o,a,e)}function i(e,t,n,r){if(e>r)return t+n;var i=(e/=r)*e,o=i*e;return t+n*(-2*o+3*i)}var o=e.scrollTop,a=t-o,s=o-1;r?a(e,t,function(){return l(e)}):o(e,t,n)}function c(e,t){var n=l(e),r=n.indexOf(i.startSymbol())>-1;r||n||o(e,t,n)}function l(e){function t(t){for(;t.parentNode&&(t=t.parentNode)!==e;)if(t.getAttribute&&"true"===t.getAttribute("aria-hidden"))return!0}e=e[0]||e;for(var n,r=document.createTreeWalker(e,NodeFilter.SHOW_TEXT,null,!1),i="";n=r.nextNode();)t(n)||(i+=n.textContent);return i.trim()||""}function u(e,t){function n(e){var t=e.currentStyle?e.currentStyle:r.getComputedStyle(e);return"none"===t.display}var i=e.hasChildNodes(),o=!1;if(i)for(var a=e.childNodes,s=0;s").html(r.trim()).contents(),c=i(s);return n={locals:e,element:s,link:function(r){if(e.$scope=r,l){var i=o(l,e,!0,u);h&&t.extend(i.instance,e);var a=i();s.data("$ngControllerController",a),s.children().data("$ngControllerController",a),n.controller=a}return c(r)}}})}}e.$inject=["$q","$templateRequest","$injector","$compile","$controller"],t.module("material.core").service("$mdCompiler",e)}(),function(){function n(){}function r(n,r,i){function o(e){return function(t,n){n.distancethis.options.maxDistance&&this.cancel()},onEnd:function(){this.onCancel()}}).handler("drag",{options:{minDistance:6,horizontal:!0,cancelMultiplier:1.5},onSetup:function(e,t){g&&(this.oldTouchAction=e[0].style[g],e[0].style[g]=t.horizontal===!1?"pan-y":"pan-x")},onCleanup:function(e){this.oldTouchAction&&(e[0].style[g]=this.oldTouchAction)},onStart:function(e){this.state.registeredParent||this.cancel()},onMove:function(e,t){var n,r;g||"touchmove"!==e.type||e.preventDefault(),this.state.dragPointer?this.dispatchDragMove(e):(this.state.options.horizontal?(n=Math.abs(t.distanceX)>this.state.options.minDistance,r=Math.abs(t.distanceY)>this.state.options.minDistance*this.state.options.cancelMultiplier):(n=Math.abs(t.distanceY)>this.state.options.minDistance,r=Math.abs(t.distanceX)>this.state.options.minDistance*this.state.options.cancelMultiplier),n?(this.state.dragPointer=s(e),u(e,this.state.dragPointer),this.dispatchEvent(e,"$md.dragstart",this.state.dragPointer)):r&&this.cancel())},dispatchDragMove:r.throttle(function(e){this.state.isRunning&&(u(e,this.state.dragPointer),this.dispatchEvent(e,"$md.drag",this.state.dragPointer))}),onEnd:function(e,t){this.state.dragPointer&&(u(e,this.state.dragPointer),this.dispatchEvent(e,"$md.dragend",this.state.dragPointer))}}).handler("swipe",{options:{minVelocity:.65,minDistance:10},onEnd:function(e,t){var n;Math.abs(t.velocityX)>this.state.options.minVelocity&&Math.abs(t.distanceX)>this.state.options.minDistance?(n="left"==t.directionX?"$md.swipeleft":"$md.swiperight",this.dispatchEvent(e,n)):Math.abs(t.velocityY)>this.state.options.minVelocity&&Math.abs(t.distanceY)>this.state.options.minDistance&&(n="up"==t.directionY?"$md.swipeup":"$md.swipedown",this.dispatchEvent(e,n))}})}function i(e){this.name=e,this.state={}}function o(){function n(e,n,r){r=r||m;var i=new t.element.Event(n);i.$material=!0,i.pointer=r,i.srcEvent=e,t.extend(i,{clientX:r.x,clientY:r.y,screenX:r.x,screenY:r.y,pageX:r.x,pageY:r.y,ctrlKey:e.ctrlKey,altKey:e.altKey,shiftKey:e.shiftKey,metaKey:e.metaKey}),t.element(r.target).trigger(i)}function r(t,n,r){r=r||m;var i;"click"===n||"mouseup"==n||"mousedown"==n?(i=document.createEvent("MouseEvents"),i.initMouseEvent(n,!0,!0,e,t.detail,r.x,r.y,r.x,r.y,t.ctrlKey,t.altKey,t.shiftKey,t.metaKey,t.button,t.relatedTarget||null)):(i=document.createEvent("CustomEvent"),i.initCustomEvent(n,!0,!0,{})),i.$material=!0,i.pointer=r,i.srcEvent=t,r.target.dispatchEvent(i)}var o="undefined"!=typeof e.jQuery&&t.element===e.jQuery;return i.prototype={options:{},dispatchEvent:o?n:r,onSetup:t.noop,onCleanup:t.noop,onStart:t.noop,onMove:t.noop,onEnd:t.noop,onCancel:t.noop,start:function(e,n){if(!this.state.isRunning){var r=this.getNearestParent(e.target),i=r&&r.$mdGesture[this.name]||{};this.state={isRunning:!0,options:t.extend({},this.options,i),registeredParent:r},this.onStart(e,n)}},move:function(e,t){this.state.isRunning&&this.onMove(e,t)},end:function(e,t){this.state.isRunning&&(this.onEnd(e,t),this.state.isRunning=!1)},cancel:function(e,t){this.onCancel(e,t),this.state={}},getNearestParent:function(e){for(var t=e;t;){if((t.$mdGesture||{})[this.name])return t;t=t.parentNode}return null},registerElement:function(e,t){function n(){delete e[0].$mdGesture[r.name],e.off("$destroy",n),r.onCleanup(e,t||{})}var r=this;return e[0].$mdGesture=e[0].$mdGesture||{},e[0].$mdGesture[this.name]=t||{},e.on("$destroy",n),r.onSetup(e,t||{}),n}},i}function a(e,n){function r(e){var t=!e.clientX&&!e.clientY;t||e.$material||e.isIonicTap||l(e)||(e.preventDefault(),e.stopPropagation())}function i(e){var t=0===e.clientX&&0===e.clientY;t||e.$material||e.isIonicTap||l(e)?(g=null,"label"==e.target.tagName.toLowerCase()&&(g={x:e.x,y:e.y})):(e.preventDefault(),e.stopPropagation(),g=null)}function o(e,t){var r;for(var i in h)r=h[i],r instanceof n&&("start"===e&&r.cancel(),r[e](t,m))}function a(e){if(!m){var t=+Date.now();f&&!c(e,f)&&t-f.endTime<1500||(m=s(e),o("start",e))}}function d(e){m&&c(e,m)&&(u(e,m),o("move",e))}function p(e){m&&c(e,m)&&(u(e,m),m.endTime=+Date.now(),o("end",e),f=m,m=null)}document.contains||(document.contains=function(e){return document.body.contains(e)}),!v&&e.isHijackingClicks&&(document.addEventListener("click",i,!0),document.addEventListener("mouseup",r,!0),document.addEventListener("mousedown",r,!0),document.addEventListener("focus",r,!0),v=!0);var b="mousedown touchstart pointerdown",$="mousemove touchmove pointermove",y="mouseup mouseleave touchend touchcancel pointerup pointercancel";t.element(document).on(b,a).on($,d).on(y,p).on("$$mdGestureReset",function(){f=m=null})}function s(e){var t=d(e),n={startTime:+Date.now(),target:e.target,type:e.type.charAt(0)};return n.startX=n.x=t.pageX,n.startY=n.y=t.pageY,n}function c(e,t){return e&&t&&e.type.charAt(0)===t.type}function l(e){return g&&g.x==e.x&&g.y==e.y}function u(e,t){var n=d(e),r=t.x=n.pageX,i=t.y=n.pageY;t.distanceX=r-t.startX,t.distanceY=i-t.startY,t.distance=Math.sqrt(t.distanceX*t.distanceX+t.distanceY*t.distanceY),t.directionX=t.distanceX>0?"right":t.distanceX<0?"left":"",t.directionY=t.distanceY>0?"down":t.distanceY<0?"up":"",t.duration=+Date.now()-t.startTime,t.velocityX=t.distanceX/t.duration,t.velocityY=t.distanceY/t.duration}function d(e){return e=e.originalEvent||e,e.touches&&e.touches[0]||e.changedTouches&&e.changedTouches[0]||e}r.$inject=["$$MdGestureHandler","$$rAF","$timeout"],a.$inject=["$mdGesture","$$MdGestureHandler"];var m,f,h={},p=!1,g=null,v=!1;t.module("material.core.gestures",[]).provider("$mdGesture",n).factory("$$MdGestureHandler",o).run(a),n.prototype={skipClickHijack:function(){return p=!0},$get:["$$MdGestureHandler","$$rAF","$timeout",function(e,t,n){return new r(e,t,n)}]}}(),function(){function e(){function e(e){function n(e){return c.optionsFactory=e.options,c.methods=(e.methods||[]).concat(a),l}function r(e,t){return s[e]=t,l}function i(t,n){if(n=n||{},n.methods=n.methods||[],n.options=n.options||function(){return{}},/^cancel|hide|show$/.test(t))throw new Error("Preset '"+t+"' in "+e+" is reserved!");if(n.methods.indexOf("_options")>-1)throw new Error("Method '_options' in "+e+" is reserved!");return c.presets[t]={methods:n.methods.concat(a),optionsFactory:n.options,argOption:n.argOption},l}function o(n,r){function i(e){return e=e||{},e._options&&(e=e._options),d.show(t.extend({},u,e))}function o(e){return d.destroy(e)}function a(t,n){var i={};return i[e]=m,r.invoke(t||function(){return n},{},i)}var l,u,d=n(),m={hide:d.hide,cancel:d.cancel,show:i,destroy:o};return l=c.methods||[],u=a(c.optionsFactory,{}),t.forEach(s,function(e,t){m[t]=e}),t.forEach(c.presets,function(e,n){function r(e){this._options=t.extend({},i,e)}var i=a(e.optionsFactory,{}),o=(e.methods||[]).concat(l);if(t.extend(i,{$type:n}),t.forEach(o,function(e){r.prototype[e]=function(t){return this._options[e]=t,this}}),e.argOption){var s="show"+n.charAt(0).toUpperCase()+n.slice(1);m[s]=function(e){var t=m[n](e);return m.show(t)}}m[n]=function(n){return arguments.length&&e.argOption&&!t.isObject(n)&&!t.isArray(n)?(new r)[e.argOption](n):new r(n)}}),m}o.$inject=["$$interimElement","$injector"];var a=["onHide","onShow","onRemove"],s={},c={presets:{}},l={setDefaults:n,addPreset:i,addMethod:r,$get:o};return l.addPreset("build",{methods:["controller","controllerAs","resolve","template","templateUrl","themable","transformTemplate","parent"]}),l}function r(e,r,i,o,a,s,c,l,u,d,m){return function(){function f(e){e=e||{};var t=new v(e||{}),n=!e.skipHide&&y.length?b.cancel():r.when(!0);return n["finally"](function(){y.push(t),t.show()["catch"](function(e){return e})}),t.deferred.promise}function h(e,t){function i(n){return n.remove(e,!1,t||{})["catch"](function(e){return e}),n.deferred.promise}if(!y.length)return r.when(e);if(t=t||{},t.closeAll){var o=r.all(y.reverse().map(i));return y=[],o}if(t.closeTo!==n)return r.all(y.splice(t.closeTo).map(i));var a=y.pop();return i(a)}function p(e,n){var i=y.pop();return i?(i.remove(e,!0,n||{})["catch"](function(e){return e}),i.deferred.promise["catch"](t.noop)):r.when(e)}function g(e){var n=e?null:y.shift(),i=t.element(e).length?t.element(e)[0].parentNode:null;if(i){var o=y.filter(function(e){var t=e.options.element[0];return t===i});o.length>0&&(n=o[0],y.splice(y.indexOf(n),1))}return n?n.remove($,!1,{$destroy:!0}):r.when($)}function v(m){function f(){return r(function(e,t){function n(e){w.deferred.reject(e),t(e)}m.onCompiling&&m.onCompiling(m),g(m).then(function(t){x=v(t,m),k=E(x,m,t.controller).then(e,n)},n)})}function h(e,n,i){function o(e){w.deferred.resolve(e)}function a(e){w.deferred.reject(e)}return x?(m=t.extend(m||{},i||{}),m.cancelAutoHide&&m.cancelAutoHide(),m.element.triggerHandler("$mdInterimElementRemove"),m.$destroy===!0?C(m.element,m).then(function(){n&&a(e)||o(e)}):(r.when(k)["finally"](function(){C(m.element,m).then(function(){n&&a(e)||o(e)},a)}),w.deferred.promise)):r.when(!1)}function p(e){return e=e||{},e.template&&(e.template=l.processTemplate(e.template)),t.extend({preserveScope:!1,cancelAutoHide:t.noop,scope:e.scope||o.$new(e.isolateScope),onShow:function(e,t,n){return c.enter(t,n.parent)},onRemove:function(e,t){return t&&c.leave(t)||r.when()}},e)}function g(e){var t=e.skipCompile?null:u.compile(e);return t||r(function(t){t({locals:{},link:function(){return e.element}})})}function v(e,n){t.extend(e.locals,n);var r=e.link(n.scope);return n.element=r,n.parent=$(r,n),n.themable&&d(r),r}function $(n,r){var i=r.parent;if(i=t.isFunction(i)?i(r.scope,n,r):t.isString(i)?t.element(e[0].querySelector(i)):t.element(i),!(i||{}).length){var o;return s[0]&&s[0].querySelector&&(o=s[0].querySelector(":not(svg) > body")),o||(o=s[0]),"#comment"==o.nodeName&&(o=e[0].body),t.element(o)}return i}function y(){var e,r=t.noop;m.hideDelay&&(e=a(b.hide,m.hideDelay),r=function(){a.cancel(e)}),m.cancelAutoHide=function(){r(),m.cancelAutoHide=n}}function E(e,n,i){var o=n.onShowing||t.noop,a=n.onComplete||t.noop;return o(n.scope,e,n,i),r(function(t,o){try{r.when(n.onShow(n.scope,e,n,i)).then(function(){a(n.scope,e,n),y(),t(e)},o)}catch(s){o(s.message)}})}function C(e,n){var r=n.onRemoving||t.noop;return i(function(t,o){try{var a=i.when(n.onRemove(n.scope,e,n)||!0);r(e,a),1==n.$destroy?t(e):a.then(function(){!n.preserveScope&&n.scope&&n.scope.$destroy(),t(e)},o)}catch(s){o(s)}})}var w,x,k=r.when(!0);return m=p(m),w={options:m,deferred:r.defer(),show:f,remove:h}}var b,$=!1,y=[];return b={show:f,hide:h,cancel:p,destroy:g,$injector_:m}}}return r.$inject=["$document","$q","$$q","$rootScope","$timeout","$rootElement","$animate","$mdUtil","$mdCompiler","$mdTheming","$injector"],e.$get=r,e}t.module("material.core").provider("$$interimElement",e)}(),function(){!function(){function e(e){function s(e){return e.replace(d,"").replace(m,function(e,t,n,r){return r?n.toUpperCase():n})}var d=/^((?:x|data)[\:\-_])/i,m=/([\:\-\_]+(.))/g,f=["","xs","gt-xs","sm","gt-sm","md","gt-md","lg","gt-lg","xl","print"],h=["layout","flex","flex-order","flex-offset","layout-align"],p=["show","hide","layout-padding","layout-margin"]; +t.forEach(f,function(n){t.forEach(h,function(t){var r=n?t+"-"+n:t;e.directive(s(r),o(r))}),t.forEach(p,function(t){var r=n?t+"-"+n:t;e.directive(s(r),a(r))})}),e.provider("$$mdLayout",function(){return{$get:t.noop,validateAttributeValue:u,validateAttributeUsage:l,disableLayouts:function(e){k.enabled=e!==!0}}}).directive("mdLayoutCss",r).directive("ngCloak",i("ng-cloak")).directive("layoutWrap",a("layout-wrap")).directive("layoutNowrap",a("layout-nowrap")).directive("layoutNoWrap",a("layout-no-wrap")).directive("layoutFill",a("layout-fill")).directive("layoutLtMd",c("layout-lt-md",!0)).directive("layoutLtLg",c("layout-lt-lg",!0)).directive("flexLtMd",c("flex-lt-md",!0)).directive("flexLtLg",c("flex-lt-lg",!0)).directive("layoutAlignLtMd",c("layout-align-lt-md")).directive("layoutAlignLtLg",c("layout-align-lt-lg")).directive("flexOrderLtMd",c("flex-order-lt-md")).directive("flexOrderLtLg",c("flex-order-lt-lg")).directive("offsetLtMd",c("flex-offset-lt-md")).directive("offsetLtLg",c("flex-offset-lt-lg")).directive("hideLtMd",c("hide-lt-md")).directive("hideLtLg",c("hide-lt-lg")).directive("showLtMd",c("show-lt-md")).directive("showLtLg",c("show-lt-lg")).config(n)}function n(){var e=!!document.querySelector("[md-layouts-disabled]");k.enabled=!e}function r(){return k.enabled=!1,{restrict:"A",priority:"900"}}function i(e){return["$timeout",function(n){return{restrict:"A",priority:-10,compile:function(r){return k.enabled?(r.addClass(e),function(t,r){n(function(){r.removeClass(e)},10,!1)}):t.noop}}}]}function o(e){function n(t,n,r){var i=s(n,e,r),o=r.$observe(r.$normalize(e),i);i(f(e,r,"")),t.$on("$destroy",function(){o()})}return["$mdUtil","$interpolate","$log",function(r,i,o){return g=r,v=i,b=o,{restrict:"A",compile:function(r,i){var o;return k.enabled&&(l(e,i,r,b),u(e,f(e,i,""),d(r,e,i)),o=n),o||t.noop}}}]}function a(e){function n(t,n){n.addClass(e)}return["$mdUtil","$interpolate","$log",function(r,i,o){return g=r,v=i,b=o,{restrict:"A",compile:function(r,i){var o;return k.enabled&&(u(e,f(e,i,""),d(r,e,i)),n(null,r),o=n),o||t.noop}}}]}function s(e,n){var r;return function(i){var o=u(n,i||"");t.isDefined(o)&&(r&&e.removeClass(r),r=o?n+"-"+o.replace(y,"-"):n,e.addClass(r))}}function c(e){var n=e.split("-");return["$log",function(r){return r.warn(e+"has been deprecated. Please use a `"+n[0]+"-gt-` variant."),t.noop}]}function l(e,t,n,r){var i,o,a,s=n[0].nodeName.toLowerCase();switch(e.replace($,"")){case"flex":"md-button"!=s&&"fieldset"!=s||(o="<"+s+" "+e+">",a="https://github.com/philipwalton/flexbugs#9-some-html-elements-cant-be-flex-containers",i="Markup '{0}' may not work as expected in IE Browsers. Consult '{1}' for details.",r.warn(g.supplant(i,[o,a])))}}function u(e,n,r){var i=n;if(!m(n)){switch(e.replace($,"")){case"layout":h(n,C)||(n=C[0]);break;case"flex":h(n,E)||isNaN(n)&&(n="");break;case"flex-offset":case"flex-order":n&&!isNaN(+n)||(n="0");break;case"layout-align":var o=p(n);n=g.supplant("{main}-{cross}",o);break;case"layout-padding":case"layout-margin":case"layout-fill":case"layout-wrap":case"layout-nowrap":case"layout-nowrap":n=""}n!=i&&(r||t.noop)(n)}return n}function d(e,t,n){return function(e){m(e)||(n[n.$normalize(t)]=e)}}function m(e){return(e||"").indexOf(v.startSymbol())>-1}function f(e,t,n){var r=t.$normalize(e);return t[r]?t[r].replace(y,"-"):n||null}function h(e,t,n){e=n&&e?e.replace(y,n):e;var r=!1;return e&&t.forEach(function(t){t=n?t.replace(y,n):t,r=r||t===e}),r}function p(e){var t,n={main:"start",cross:"stretch"};return e=e||"",0!==e.indexOf("-")&&0!==e.indexOf(" ")||(e="none"+e),t=e.toLowerCase().trim().replace(y,"-").split("-"),t.length&&"space"===t[0]&&(t=[t[0]+"-"+t[1],t[2]]),t.length>0&&(n.main=t[0]||n.main),t.length>1&&(n.cross=t[1]||n.cross),w.indexOf(n.main)<0&&(n.main="start"),x.indexOf(n.cross)<0&&(n.cross="stretch"),n}var g,v,b,$=/(-gt)?-(sm|md|lg|print)/g,y=/\s+/g,E=["grow","initial","auto","none","noshrink","nogrow"],C=["row","column"],w=["","start","center","end","stretch","space-around","space-between"],x=["","start","center","end","stretch"],k={enabled:!0,breakpoints:[]};e(t.module("material.core.layout",["ng"]))}()}(),function(){t.module("material.core.meta",[]).provider("$$mdMeta",function(){function e(e){if(o[e])return!0;var n=document.getElementsByName(e)[0];return!!n&&(o[e]=t.element(n),!0)}function n(n,r){if(e(n),o[n])o[n].attr("content",r);else{var a=t.element('');i.append(a),o[n]=a}return function(){o[n].attr("content",""),o[n].remove(),delete o[n]}}function r(t){if(!e(t))throw Error("$$mdMeta: could not find a meta tag with the name '"+t+"'");return o[t].attr("content")}var i=t.element(document.head),o={},a={setMeta:n,getMeta:r};return t.extend({},a,{$get:function(){return a}})})}(),function(){function e(e,r){function i(e){return e&&""!==e}var o,a=[],s={};return o={notFoundError:function(t,n){e.error((n||"")+"No instance found for handle",t)},getInstances:function(){return a},get:function(e){if(!i(e))return null;var t,n,r;for(t=0,n=a.length;t
');return this.$element.append(e),e},r.prototype.clearTimeout=function(){this.timeout&&(this.$timeout.cancel(this.timeout),this.timeout=null)},r.prototype.isRippleAllowed=function(){var e=this.$element[0];do{if(!e.tagName||"BODY"===e.tagName)break;if(e&&t.isFunction(e.hasAttribute)){if(e.hasAttribute("disabled"))return!1;if("false"===this.inkRipple()||"0"===this.inkRipple())return!1}}while(e=e.parentNode);return!0},r.prototype.inkRipple=function(){return this.$element.attr("md-ink-ripple")},r.prototype.createRipple=function(e,n){function r(e,t,n){return e?Math.max(t,n):Math.sqrt(Math.pow(t,2)+Math.pow(n,2))}if(this.isRippleAllowed()){var i=this,o=i.$mdColorUtil,s=t.element('
'),c=this.$element.prop("clientWidth"),l=this.$element.prop("clientHeight"),u=2*Math.max(Math.abs(c-e),e),d=2*Math.max(Math.abs(l-n),n),m=r(this.options.fitRipple,u,d),f=this.calculateColor();s.css({left:e+"px",top:n+"px",background:"black",width:m+"px",height:m+"px",backgroundColor:o.rgbaToRgb(f),borderColor:o.rgbaToRgb(f)}),this.lastRipple=s,this.clearTimeout(),this.timeout=this.$timeout(function(){i.clearTimeout(),i.mousedown||i.fadeInComplete(s)},.35*a,!1),this.options.dimBackground&&this.container.css({backgroundColor:f}),this.container.append(s),this.ripples.push(s),s.addClass("md-ripple-placed"),this.$mdUtil.nextTick(function(){s.addClass("md-ripple-scaled md-ripple-active"),i.$timeout(function(){i.clearRipples()},a,!1)},!1)}},r.prototype.fadeInComplete=function(e){this.lastRipple===e?this.timeout||this.mousedown||this.removeRipple(e):this.removeRipple(e)},r.prototype.removeRipple=function(e){var t=this,n=this.ripples.indexOf(e);n<0||(this.ripples.splice(this.ripples.indexOf(e),1),e.removeClass("md-ripple-active"),e.addClass("md-ripple-remove"),0===this.ripples.length&&this.container.css({backgroundColor:""}),this.$timeout(function(){t.fadeOutComplete(e)},a,!1))},r.prototype.fadeOutComplete=function(e){e.remove(),this.lastRipple=null}}(),function(){!function(){function e(e){function n(n,r,i){return e.attach(n,r,t.extend({center:!1,dimBackground:!0,outline:!1,rippleSize:"full"},i))}return{attach:n}}e.$inject=["$mdInkRipple"],t.module("material.core").factory("$mdTabInkRipple",e)}()}(),function(){t.module("material.core.theming.palette",[]).constant("$mdColorPalette",{red:{50:"#ffebee",100:"#ffcdd2",200:"#ef9a9a",300:"#e57373",400:"#ef5350",500:"#f44336",600:"#e53935",700:"#d32f2f",800:"#c62828",900:"#b71c1c",A100:"#ff8a80",A200:"#ff5252",A400:"#ff1744",A700:"#d50000",contrastDefaultColor:"light",contrastDarkColors:"50 100 200 300 A100",contrastStrongLightColors:"400 500 600 700 A200 A400 A700"},pink:{50:"#fce4ec",100:"#f8bbd0",200:"#f48fb1",300:"#f06292",400:"#ec407a",500:"#e91e63",600:"#d81b60",700:"#c2185b",800:"#ad1457",900:"#880e4f",A100:"#ff80ab",A200:"#ff4081",A400:"#f50057",A700:"#c51162",contrastDefaultColor:"light",contrastDarkColors:"50 100 200 A100",contrastStrongLightColors:"500 600 A200 A400 A700"},purple:{50:"#f3e5f5",100:"#e1bee7",200:"#ce93d8",300:"#ba68c8",400:"#ab47bc",500:"#9c27b0",600:"#8e24aa",700:"#7b1fa2",800:"#6a1b9a",900:"#4a148c",A100:"#ea80fc",A200:"#e040fb",A400:"#d500f9",A700:"#aa00ff",contrastDefaultColor:"light",contrastDarkColors:"50 100 200 A100",contrastStrongLightColors:"300 400 A200 A400 A700"},"deep-purple":{50:"#ede7f6",100:"#d1c4e9",200:"#b39ddb",300:"#9575cd",400:"#7e57c2",500:"#673ab7",600:"#5e35b1",700:"#512da8",800:"#4527a0",900:"#311b92",A100:"#b388ff",A200:"#7c4dff",A400:"#651fff",A700:"#6200ea",contrastDefaultColor:"light",contrastDarkColors:"50 100 200 A100",contrastStrongLightColors:"300 400 A200"},indigo:{50:"#e8eaf6",100:"#c5cae9",200:"#9fa8da",300:"#7986cb",400:"#5c6bc0",500:"#3f51b5",600:"#3949ab",700:"#303f9f",800:"#283593",900:"#1a237e",A100:"#8c9eff",A200:"#536dfe",A400:"#3d5afe",A700:"#304ffe",contrastDefaultColor:"light",contrastDarkColors:"50 100 200 A100",contrastStrongLightColors:"300 400 A200 A400"},blue:{50:"#e3f2fd",100:"#bbdefb",200:"#90caf9",300:"#64b5f6",400:"#42a5f5",500:"#2196f3",600:"#1e88e5",700:"#1976d2",800:"#1565c0",900:"#0d47a1",A100:"#82b1ff",A200:"#448aff",A400:"#2979ff",A700:"#2962ff",contrastDefaultColor:"light",contrastDarkColors:"50 100 200 300 400 A100",contrastStrongLightColors:"500 600 700 A200 A400 A700"},"light-blue":{50:"#e1f5fe",100:"#b3e5fc",200:"#81d4fa",300:"#4fc3f7",400:"#29b6f6",500:"#03a9f4",600:"#039be5",700:"#0288d1",800:"#0277bd",900:"#01579b",A100:"#80d8ff",A200:"#40c4ff",A400:"#00b0ff",A700:"#0091ea",contrastDefaultColor:"dark",contrastLightColors:"600 700 800 900 A700",contrastStrongLightColors:"600 700 800 A700"},cyan:{50:"#e0f7fa",100:"#b2ebf2",200:"#80deea",300:"#4dd0e1",400:"#26c6da",500:"#00bcd4",600:"#00acc1",700:"#0097a7",800:"#00838f",900:"#006064",A100:"#84ffff",A200:"#18ffff",A400:"#00e5ff",A700:"#00b8d4",contrastDefaultColor:"dark",contrastLightColors:"700 800 900",contrastStrongLightColors:"700 800 900"},teal:{50:"#e0f2f1",100:"#b2dfdb",200:"#80cbc4",300:"#4db6ac",400:"#26a69a",500:"#009688",600:"#00897b",700:"#00796b",800:"#00695c",900:"#004d40",A100:"#a7ffeb",A200:"#64ffda",A400:"#1de9b6",A700:"#00bfa5",contrastDefaultColor:"dark",contrastLightColors:"500 600 700 800 900",contrastStrongLightColors:"500 600 700"},green:{50:"#e8f5e9",100:"#c8e6c9",200:"#a5d6a7",300:"#81c784",400:"#66bb6a",500:"#4caf50",600:"#43a047",700:"#388e3c",800:"#2e7d32",900:"#1b5e20",A100:"#b9f6ca",A200:"#69f0ae",A400:"#00e676",A700:"#00c853",contrastDefaultColor:"dark",contrastLightColors:"500 600 700 800 900",contrastStrongLightColors:"500 600 700"},"light-green":{50:"#f1f8e9",100:"#dcedc8",200:"#c5e1a5",300:"#aed581",400:"#9ccc65",500:"#8bc34a",600:"#7cb342",700:"#689f38",800:"#558b2f",900:"#33691e",A100:"#ccff90",A200:"#b2ff59",A400:"#76ff03",A700:"#64dd17",contrastDefaultColor:"dark",contrastLightColors:"700 800 900",contrastStrongLightColors:"700 800 900"},lime:{50:"#f9fbe7",100:"#f0f4c3",200:"#e6ee9c",300:"#dce775",400:"#d4e157",500:"#cddc39",600:"#c0ca33",700:"#afb42b",800:"#9e9d24",900:"#827717",A100:"#f4ff81",A200:"#eeff41",A400:"#c6ff00",A700:"#aeea00",contrastDefaultColor:"dark",contrastLightColors:"900",contrastStrongLightColors:"900"},yellow:{50:"#fffde7",100:"#fff9c4",200:"#fff59d",300:"#fff176",400:"#ffee58",500:"#ffeb3b",600:"#fdd835",700:"#fbc02d",800:"#f9a825",900:"#f57f17",A100:"#ffff8d",A200:"#ffff00",A400:"#ffea00",A700:"#ffd600",contrastDefaultColor:"dark"},amber:{50:"#fff8e1",100:"#ffecb3",200:"#ffe082",300:"#ffd54f",400:"#ffca28",500:"#ffc107",600:"#ffb300",700:"#ffa000",800:"#ff8f00",900:"#ff6f00",A100:"#ffe57f",A200:"#ffd740",A400:"#ffc400",A700:"#ffab00",contrastDefaultColor:"dark"},orange:{50:"#fff3e0",100:"#ffe0b2",200:"#ffcc80",300:"#ffb74d",400:"#ffa726",500:"#ff9800",600:"#fb8c00",700:"#f57c00",800:"#ef6c00",900:"#e65100",A100:"#ffd180",A200:"#ffab40",A400:"#ff9100",A700:"#ff6d00",contrastDefaultColor:"dark",contrastLightColors:"800 900",contrastStrongLightColors:"800 900"},"deep-orange":{50:"#fbe9e7",100:"#ffccbc",200:"#ffab91",300:"#ff8a65",400:"#ff7043",500:"#ff5722",600:"#f4511e",700:"#e64a19",800:"#d84315",900:"#bf360c",A100:"#ff9e80",A200:"#ff6e40",A400:"#ff3d00",A700:"#dd2c00",contrastDefaultColor:"light",contrastDarkColors:"50 100 200 300 400 A100 A200",contrastStrongLightColors:"500 600 700 800 900 A400 A700"},brown:{50:"#efebe9",100:"#d7ccc8",200:"#bcaaa4",300:"#a1887f",400:"#8d6e63",500:"#795548",600:"#6d4c41",700:"#5d4037",800:"#4e342e",900:"#3e2723",A100:"#d7ccc8",A200:"#bcaaa4",A400:"#8d6e63",A700:"#5d4037",contrastDefaultColor:"light",contrastDarkColors:"50 100 200 A100 A200",contrastStrongLightColors:"300 400"},grey:{50:"#fafafa",100:"#f5f5f5",200:"#eeeeee",300:"#e0e0e0",400:"#bdbdbd",500:"#9e9e9e",600:"#757575",700:"#616161",800:"#424242",900:"#212121",A100:"#ffffff",A200:"#000000",A400:"#303030",A700:"#616161",contrastDefaultColor:"dark",contrastLightColors:"600 700 800 900 A200 A400 A700"},"blue-grey":{50:"#eceff1",100:"#cfd8dc",200:"#b0bec5",300:"#90a4ae",400:"#78909c",500:"#607d8b",600:"#546e7a",700:"#455a64",800:"#37474f",900:"#263238",A100:"#cfd8dc",A200:"#b0bec5",A400:"#78909c",A700:"#455a64",contrastDefaultColor:"light",contrastDarkColors:"50 100 200 300 A100 A200",contrastStrongLightColors:"400 500 700"}})}(),function(){!function(e){function t(e){var t=!!document.querySelector("[md-themes-disabled]");e.disableTheming(t)}function r(t,r){function i(e,t){return t=t||{},f[e]=a(e,t),h}function o(t,n){return a(t,e.extend({},f[t]||{},n))}function a(e,t){var n=M.filter(function(e){return!t[e]});if(n.length)throw new Error("Missing colors %1 in palette %2!".replace("%1",n.join(", ")).replace("%2",e));return t}function c(t,n){if($[t])return $[t];n=n||"default";var r="string"==typeof n?$[n]:n,i=new u(t);return r&&e.forEach(r.colors,function(t,n){i.colors[n]={name:t.name,hues:e.extend({},t.hues)}}),$[t]=i,i}function u(t){function n(t){if(t=0===arguments.length||!!t,t!==r.isDark){r.isDark=t,r.foregroundPalette=r.isDark?g:p,r.foregroundShadow=r.isDark?v:b;var n=r.isDark?k:x,i=r.isDark?x:k;return e.forEach(n,function(e,t){var n=r.colors[t],o=i[t];if(n)for(var a in n.hues)n.hues[a]===o[a]&&(n.hues[a]=e[a])}),r}}var r=this;r.name=t,r.colors={},r.dark=n,n(!1),C.forEach(function(t){var n=(r.isDark?k:x)[t];r[t+"Palette"]=function(i,o){var a=r.colors[t]={name:i,hues:e.extend({},n,o)};return Object.keys(a.hues).forEach(function(e){if(!n[e])throw new Error("Invalid hue name '%1' in theme %2's %3 color %4. Available hue names: %4".replace("%1",e).replace("%2",r.name).replace("%3",i).replace("%4",Object.keys(n).join(", ")))}),Object.keys(a.hues).map(function(e){return a.hues[e]}).forEach(function(e){if(M.indexOf(e)==-1)throw new Error("Invalid hue value '%1' in theme %2's %3 color %4. Available hue values: %5".replace("%1",e).replace("%2",r.name).replace("%3",t).replace("%4",i).replace("%5",M.join(", ")))}),r},r[t+"Color"]=function(){var e=Array.prototype.slice.call(arguments);return console.warn("$mdThemingProviderTheme."+t+"Color() has been deprecated. Use $mdThemingProviderTheme."+t+"Palette() instead."),r[t+"Palette"].apply(r,e)}})}function d(t,r){function i(e){return e===n||""===e||a.THEMES[e]!==n}function o(n,o){function a(){return l=o.controller("mdTheme")||n.data("$mdThemeController"),l&&l.$mdTheme||("default"==E?"":E)}function s(e){if(e){i(e)||r.warn("Attempted to use unregistered theme '"+e+"'. Register it with $mdThemingProvider.theme().");var t=n.data("$mdThemeName");t&&n.removeClass("md-"+t+"-theme"),n.addClass("md-"+e+"-theme"),n.data("$mdThemeName",e),l&&n.data("$mdThemeController",l)}}function c(){var e=o.controller("mdTheme");return!!e&&(n.on("$destroy",e.registerChanges(function(){s(a())})),!0)}var l=o.controller("mdTheme"),u=n.attr("md-theme-watch"),d=(y||e.isDefined(u))&&"false"!=u;s(a()),(y&&!c()||!y&&d)&&n.on("$destroy",t.$watch(a,s))}var a=function(e,r){r===n&&(r=e,e=n),e===n&&(e=t),a.inherit(r,r)};return a.THEMES=e.extend({},$),a.PALETTES=e.extend({},f),a.inherit=o,a.registered=i,a.defaultTheme=function(){return E},a.generateTheme=function(e){l($[e],e,A.nonce)},a.setBrowserColor=T,a}d.$inject=["$rootScope","$log"],f={};var h,$={},y=!1,E="default";e.extend(f,t);var w=function(e){var t=r.setMeta("theme-color",e),n=r.setMeta("msapplication-navbutton-color",e);return function(){t(),n()}},T=function(t){t=e.isObject(t)?t:{};var n=t.theme||"default",r=t.hue||"800",i=f[t.palette]||f[$[n].colors[t.palette||"primary"].name],o=e.isObject(i[r])?i[r].hex:i[r];return w(o)};return h={definePalette:i,extendPalette:o,theme:c,configuration:function(){return e.extend({},A,{defaultTheme:E,alwaysWatchTheme:y,registeredStyles:[].concat(A.registeredStyles)})},disableTheming:function(t){A.disableTheming=e.isUndefined(t)||!!t},registerStyles:function(e){A.registeredStyles.push(e)},setNonce:function(e){A.nonce=e},generateThemesOnDemand:function(e){A.generateOnDemand=e},setDefaultTheme:function(e){E=e},alwaysWatchTheme:function(e){y=e},enableBrowserColor:T,$get:d,_LIGHT_DEFAULT_HUES:x,_DARK_DEFAULT_HUES:k,_PALETTES:f,_THEMES:$,_parseRules:s,_rgba:m}}function i(t,n,r){return{priority:100,link:{pre:function(i,o,a){var s=[],c={registerChanges:function(t,n){return n&&(t=e.bind(n,t)),s.push(t),function(){var e=s.indexOf(t);e>-1&&s.splice(e,1)}},$setTheme:function(e){t.registered(e)||r.warn("attempted to use unregistered theme '"+e+"'"),c.$mdTheme=e,s.forEach(function(e){e()})}};o.data("$mdThemeController",c),c.$setTheme(n(a.mdTheme)(i)),a.$observe("mdTheme",c.$setTheme)}}}}function o(){return A.disableTheming=!0,{restrict:"A",priority:"900"}}function a(e){return e}function s(t,n,r){u(t,n),r=r.replace(/THEME_NAME/g,t.name);var i=[],o=t.colors[n],a=new RegExp("\\.md-"+t.name+"-theme","g"),s=new RegExp("('|\")?{{\\s*("+n+")-(color|contrast)-?(\\d\\.?\\d*)?\\s*}}(\"|')?","g"),c=/'?"?\{\{\s*([a-zA-Z]+)-(A?\d+|hue\-[0-3]|shadow|default)-?(\d\.?\d*)?(contrast)?\s*\}\}'?"?/g,l=f[o.name];return r=r.replace(c,function(e,n,r,i,o){return"foreground"===n?"shadow"==r?t.foregroundShadow:t.foregroundPalette[r]||t.foregroundPalette[1]:(0!==r.indexOf("hue")&&"default"!==r||(r=t.colors[n].hues[r]),m((f[t.colors[n].name][r]||"")[o?"contrast":"value"],i))}),e.forEach(o.hues,function(e,n){var o=r.replace(s,function(t,n,r,i,o){return m(l[e]["color"===i?"value":"contrast"],o)});if("default"!==n&&(o=o.replace(a,".md-"+t.name+"-theme.md-"+n)),"default"==t.name){var c=/((?:(?:(?: |>|\.|\w|-|:|\(|\)|\[|\]|"|'|=)+) )?)((?:(?:\w|\.|-)+)?)\.md-default-theme((?: |>|\.|\w|-|:|\(|\)|\[|\]|"|'|=)*)/g;o=o.replace(c,function(e,t,n,r){return e+", "+t+n+r})}i.push(o)}),i}function c(t,n){function r(t,n){var r=t.contrastDefaultColor,i=t.contrastLightColors||[],o=t.contrastStrongLightColors||[],a=t.contrastDarkColors||[];"string"==typeof i&&(i=i.split(" ")),"string"==typeof o&&(o=o.split(" ")),"string"==typeof a&&(a=a.split(" ")),delete t.contrastDefaultColor,delete t.contrastLightColors,delete t.contrastStrongLightColors,delete t.contrastDarkColors,e.forEach(t,function(n,s){function c(){return"light"===r?a.indexOf(s)>-1?$:o.indexOf(s)>-1?E:y:i.indexOf(s)>-1?o.indexOf(s)>-1?E:y:$}if(!e.isObject(n)){var l=d(n);if(!l)throw new Error("Color %1, in palette %2's hue %3, is invalid. Hex or rgb(a) color expected.".replace("%1",n).replace("%2",t.name).replace("%3",s));t[s]={hex:t[s],value:l,contrast:c()}}})}var i=document.head,o=i?i.firstElementChild:null,a=!A.disableTheming&&t.has("$MD_THEME_CSS")?t.get("$MD_THEME_CSS"):"";if(a+=A.registeredStyles.join(""),o&&0!==a.length){e.forEach(f,r);var s=a.split(/\}(?!(\}|'|"|;))/).filter(function(e){return e&&e.trim().length}).map(function(e){return e.trim()+"}"}),c=new RegExp("md-("+C.join("|")+")","g");C.forEach(function(e){T[e]=""}),s.forEach(function(e){for(var t,n=(e.match(c),0);t=C[n];n++)if(e.indexOf(".md-"+t)>-1)return T[t]+=e;for(n=0;t=C[n];n++)if(e.indexOf(t)>-1)return T[t]+=e;return T[w]+=e}),A.generateOnDemand||e.forEach(n.THEMES,function(e){h[e.name]||"default"!==n.defaultTheme()&&"default"===e.name||l(e,e.name,A.nonce)})}}function l(e,t,n){var r=document.head,i=r?r.firstElementChild:null;h[t]||(C.forEach(function(t){for(var o=s(e,t,T[t]);o.length;){var a=o.shift();if(a){var c=document.createElement("style");c.setAttribute("md-theme-style",""),n&&c.setAttribute("nonce",n),c.appendChild(document.createTextNode(a)),r.insertBefore(c,i)}}}),h[e.name]=!0)}function u(e,t){if(!f[(e.colors[t]||{}).name])throw new Error("You supplied an invalid color palette for theme %1's %2 palette. Available palettes: %3".replace("%1",e.name).replace("%2",t).replace("%3",Object.keys(f).join(", ")))}function d(t){if(e.isArray(t)&&3==t.length)return t;if(/^rgb/.test(t))return t.replace(/(^\s*rgba?\(|\)\s*$)/g,"").split(",").map(function(e,t){return 3==t?parseFloat(e,10):parseInt(e,10)});if("#"==t.charAt(0)&&(t=t.substring(1)),/^([a-fA-F0-9]{3}){1,2}$/g.test(t)){var n=t.length/3,r=t.substr(0,n),i=t.substr(n,n),o=t.substr(2*n);return 1===n&&(r+=r,i+=i,o+=o),[parseInt(r,16),parseInt(i,16),parseInt(o,16)]}}function m(t,n){return t?(4==t.length&&(t=e.copy(t),n?t.pop():n=t.pop()),n&&("number"==typeof n||"string"==typeof n&&n.length)?"rgba("+t.join(",")+","+n+")":"rgb("+t.join(",")+")"):"rgb('0,0,0')"}t.$inject=["$mdThemingProvider"],i.$inject=["$mdTheming","$interpolate","$log"],a.$inject=["$mdTheming"],r.$inject=["$mdColorPalette","$$mdMetaProvider"],c.$inject=["$injector","$mdTheming"],e.module("material.core.theming",["material.core.theming.palette","material.core.meta"]).directive("mdTheme",i).directive("mdThemable",a).directive("mdThemesDisabled",o).provider("$mdTheming",r).config(t).run(c);var f,h={},p={name:"dark",1:"rgba(0,0,0,0.87)",2:"rgba(0,0,0,0.54)",3:"rgba(0,0,0,0.38)",4:"rgba(0,0,0,0.12)"},g={name:"light",1:"rgba(255,255,255,1.0)",2:"rgba(255,255,255,0.7)",3:"rgba(255,255,255,0.5)",4:"rgba(255,255,255,0.12)"},v="1px 1px 0px rgba(0,0,0,0.4), -1px -1px 0px rgba(0,0,0,0.4)",b="",$=d("rgba(0,0,0,0.87)"),y=d("rgba(255,255,255,0.87)"),E=d("rgb(255,255,255)"),C=["primary","accent","warn","background"],w="primary",x={accent:{"default":"A200","hue-1":"A100","hue-2":"A400","hue-3":"A700"},background:{"default":"50","hue-1":"A100","hue-2":"100","hue-3":"300"}},k={background:{"default":"A400","hue-1":"800","hue-2":"900","hue-3":"A200"}};C.forEach(function(e){var t={"default":"500","hue-1":"300","hue-2":"800","hue-3":"A100"};x[e]||(x[e]=t),k[e]||(k[e]=t)});var M=["50","100","200","300","400","500","600","700","800","900","A100","A200","A400","A700"],A={disableTheming:!1,generateOnDemand:!1,registeredStyles:[],nonce:null},T={}}(e.angular)}(),function(){function n(n,r,i,o,a){var s;return s={translate3d:function(e,t,n,r){function i(n){return a(e,{to:n||t,addClass:r.transitionOutClass,removeClass:r.transitionInClass}).start()}return a(e,{from:t,to:n,addClass:r.transitionInClass,removeClass:r.transitionOutClass}).start().then(function(){return i})},waitTransitionEnd:function(t,n){var a=3e3;return r(function(r,s){function c(e){e&&e.target!==t[0]||(e&&i.cancel(u),t.off(o.CSS.TRANSITIONEND,c),r())}function l(n){return n=n||e.getComputedStyle(t[0]),"0s"==n.transitionDuration||!n.transition&&!n.transitionProperty}n=n||{},l(n.cachedTransitionStyles)&&(a=0);var u=i(c,n.timeout||a);t.on(o.CSS.TRANSITIONEND,c)})},calculateTransformValues:function(e,t){function n(){var t=e?e.parent():null,n=t?t.parent():null;return n?s.clientRect(n):null}var r=t.element,i=t.bounds;if(r||i){var o=r?s.clientRect(r)||n():s.copyRect(i),a=s.copyRect(e[0].getBoundingClientRect()),c=s.centerPointFor(a),l=s.centerPointFor(o);return{centerX:l.x-c.x,centerY:l.y-c.y,scaleX:Math.round(100*Math.min(.5,o.width/a.width))/100,scaleY:Math.round(100*Math.min(.5,o.height/a.height))/100}}return{centerX:0,centerY:0,scaleX:.5,scaleY:.5}},calculateZoomToOrigin:function(e,r){var i="translate3d( {centerX}px, {centerY}px, 0 ) scale( {scaleX}, {scaleY} )",o=t.bind(null,n.supplant,i);return o(s.calculateTransformValues(e,r))},calculateSlideToOrigin:function(e,r){var i="translate3d( {centerX}px, {centerY}px, 0 )",o=t.bind(null,n.supplant,i);return o(s.calculateTransformValues(e,r))},toCss:function(e){function n(e,n,i){t.forEach(n.split(" "),function(e){r[e]=i})}var r={},i="left top right bottom width height x y min-width min-height max-width max-height";return t.forEach(e,function(e,a){if(!t.isUndefined(e))if(i.indexOf(a)>=0)r[a]=e+"px";else switch(a){case"transition":n(a,o.CSS.TRANSITION,e);break;case"transform":n(a,o.CSS.TRANSFORM,e);break;case"transformOrigin":n(a,o.CSS.TRANSFORM_ORIGIN,e);break;case"font-size":r["font-size"]=e}}),r},toTransformCss:function(e,n,r){var i={};return t.forEach(o.CSS.TRANSFORM.split(" "),function(t){i[t]=e}),n&&(r=r||"all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1) !important",i.transition=r),i},copyRect:function(e,n){return e?(n=n||{},t.forEach("left top right bottom width height".split(" "),function(t){n[t]=Math.round(e[t])}),n.width=n.width||n.right-n.left,n.height=n.height||n.bottom-n.top,n):null},clientRect:function(e){var n=t.element(e)[0].getBoundingClientRect(),r=function(e){return e&&e.width>0&&e.height>0};return r(n)?s.copyRect(n):null},centerPointFor:function(e){return e?{x:Math.round(e.left+e.width/2),y:Math.round(e.top+e.height/2)}:{x:0,y:0}}}}t.module("material.core").factory("$$mdAnimate",["$q","$timeout","$mdConstant","$animateCss",function(e,t,r,i){return function(o){return n(o,e,t,r,i)}}])}(),function(){t.version.minor>=4?t.module("material.core.animate",[]):!function(){function e(e){return e.replace(/-[a-z]/g,function(e){return e.charAt(1).toUpperCase()})}var n=t.forEach,r=t.isDefined(document.documentElement.style.WebkitAppearance),i=r?"-webkit-":"",o=(r?"webkitTransitionEnd ":"")+"transitionend",a=(r?"webkitAnimationEnd ":"")+"animationend",s=["$document",function(e){return function(){return e[0].body.clientWidth+1}}],c=["$$rAF",function(e){return function(){var t=!1;return e(function(){t=!0}),function(n){t?n():e(n)}}}],l=["$q","$$rAFMutex",function(e,r){function i(e){this.setHost(e),this._doneCallbacks=[],this._runInAnimationFrame=r(),this._state=0}var o=0,a=1,s=2;return i.prototype={setHost:function(e){this.host=e||{}},done:function(e){this._state===s?e():this._doneCallbacks.push(e)},progress:t.noop,getPromise:function(){if(!this.promise){var t=this;this.promise=e(function(e,n){t.done(function(t){t===!1?n():e()})})}return this.promise},then:function(e,t){return this.getPromise().then(e,t)},"catch":function(e){return this.getPromise()["catch"](e)},"finally":function(e){return this.getPromise()["finally"](e)},pause:function(){this.host.pause&&this.host.pause()},resume:function(){this.host.resume&&this.host.resume()},end:function(){this.host.end&&this.host.end(),this._resolve(!0)},cancel:function(){this.host.cancel&&this.host.cancel(),this._resolve(!1)},complete:function(e){var t=this;t._state===o&&(t._state=a,t._runInAnimationFrame(function(){t._resolve(e)}))},_resolve:function(e){this._state!==s&&(n(this._doneCallbacks,function(t){t(e)}),this._doneCallbacks.length=0,this._state=s)}},i.all=function(e,t){function r(n){o=o&&n,++i===e.length&&t(o)}var i=0,o=!0;n(e,function(e){e.done(r)})},i}];t.module("material.core.animate",[]).factory("$$forceReflow",s).factory("$$AnimateRunner",l).factory("$$rAFMutex",c).factory("$animateCss",["$window","$$rAF","$$AnimateRunner","$$forceReflow","$$jqLite","$timeout","$animate",function(t,s,c,l,u,d,m){function f(r,s){var l=[],u=E(r),f=u&&m.enabled(),g=!1,w=!1;f&&(s.transitionStyle&&l.push([i+"transition",s.transitionStyle]),s.keyframeStyle&&l.push([i+"animation",s.keyframeStyle]),s.delay&&l.push([i+"transition-delay",s.delay+"s"]),s.duration&&l.push([i+"transition-duration",s.duration+"s"]), +g=s.keyframeStyle||s.to&&(s.duration>0||s.transitionStyle),w=!!s.addClass||!!s.removeClass,C(r,!0));var x=f&&(g||w);$(r,s);var k,M,A=!1;return{close:t.close,start:function(){function t(){if(!A)return A=!0,k&&M&&r.off(k,M),h(r,s),b(r,s),n(l,function(t){u.style[e(t[0])]=""}),m.complete(!0),m}var m=new c;return v(function(){if(C(r,!1),!x)return t();n(l,function(t){var n=t[0],r=t[1];u.style[e(n)]=r}),h(r,s);var c=p(r);if(0===c.duration)return t();var m=[];s.easing&&(c.transitionDuration&&m.push([i+"transition-timing-function",s.easing]),c.animationDuration&&m.push([i+"animation-timing-function",s.easing])),s.delay&&c.animationDelay&&m.push([i+"animation-delay",s.delay+"s"]),s.duration&&c.animationDuration&&m.push([i+"animation-duration",s.duration+"s"]),n(m,function(t){var n=t[0],r=t[1];u.style[e(n)]=r,l.push(t)});var f=c.delay,g=1e3*f,v=c.duration,b=1e3*v,$=Date.now();k=[],c.transitionDuration&&k.push(o),c.animationDuration&&k.push(a),k=k.join(" "),M=function(e){e.stopPropagation();var n=e.originalEvent||e,r=n.timeStamp||Date.now(),i=parseFloat(n.elapsedTime.toFixed(3));Math.max(r-$,0)>=g&&i>=v&&t()},r.on(k,M),y(r,s),d(t,g+1.5*b,!1)}),m}}}function h(e,t){t.addClass&&(u.addClass(e,t.addClass),t.addClass=null),t.removeClass&&(u.removeClass(e,t.removeClass),t.removeClass=null)}function p(e){function n(e){return r?"Webkit"+e.charAt(0).toUpperCase()+e.substr(1):e}var i=E(e),o=t.getComputedStyle(i),a=g(o[n("transitionDuration")]),s=g(o[n("animationDuration")]),c=g(o[n("transitionDelay")]),l=g(o[n("animationDelay")]);s*=parseInt(o[n("animationIterationCount")],10)||1;var u=Math.max(s,a),d=Math.max(l,c);return{duration:u,delay:d,animationDuration:s,transitionDuration:a,animationDelay:l,transitionDelay:c}}function g(e){var t=0,r=(e||"").split(/\s*,\s*/);return n(r,function(e){"s"==e.charAt(e.length-1)&&(e=e.substring(0,e.length-1)),e=parseFloat(e)||0,t=t?Math.max(e,t):e}),t}function v(e){w&&w(),x.push(e),w=s(function(){w=null;for(var e=l(),t=0;t0&&(t.pointer.distanceY>20||Math.abs(t.pointer.velocityY)>r)){var i=e.prop("offsetHeight")-t.pointer.distanceY,a=Math.min(i/t.pointer.velocityY*.75,500);e.css(n.CSS.TRANSITION_DURATION,a+"ms"),o.nextTick(s.cancel,!0)}else e.css(n.CSS.TRANSITION_DURATION,""),e.css(n.CSS.TRANSFORM,"")}var d=l.register(t,"drag",{horizontal:!1});return t.on("$md.dragstart",a).on("$md.drag",c).on("$md.dragend",u),{element:e,cleanup:function(){d(),t.off("$md.dragstart",a),t.off("$md.drag",c),t.off("$md.dragend",u)}}}var h;return{themable:!0,onShow:d,onRemove:m,disableBackdrop:!1,escapeToClose:!0,clickOutsideToClose:!0,disableParentScroll:!0}}n.$inject=["$animate","$mdConstant","$mdUtil","$mdTheming","$mdBottomSheet","$rootElement","$mdGesture","$log"];var r=.5,i=80;return e("$mdBottomSheet").setDefaults({methods:["disableParentScroll","escapeToClose","clickOutsideToClose"],options:n})}e.$inject=["$mdBottomSheet"],n.$inject=["$$interimElementProvider"],t.module("material.components.bottomSheet",["material.core","material.components.backdrop"]).directive("mdBottomSheet",e).provider("$mdBottomSheet",n)}(),function(){function e(e){return{restrict:"E",link:function(t,n){e(n)}}}function n(e,n,r,i){function o(e){return t.isDefined(e.href)||t.isDefined(e.ngHref)||t.isDefined(e.ngLink)||t.isDefined(e.uiSref)}function a(e,t){if(o(t))return'';var n="undefined"==typeof t.type?"button":t.type;return''}function s(a,s,c){n(s),e.attach(a,s),r.expectWithoutText(s,"aria-label"),o(c)&&t.isDefined(c.ngDisabled)&&a.$watch(c.ngDisabled,function(e){s.attr("tabindex",e?-1:0)}),s.on("click",function(e){c.disabled===!0&&(e.preventDefault(),e.stopImmediatePropagation())}),s.hasClass("md-no-focus")||(a.mouseActive=!1,s.on("mousedown",function(){a.mouseActive=!0,i(function(){a.mouseActive=!1},100)}).on("focus",function(){a.mouseActive===!1&&s.addClass("md-focused")}).on("blur",function(e){s.removeClass("md-focused")}))}return{restrict:"EA",replace:!0,transclude:!0,template:a,link:s}}n.$inject=["$mdButtonInkRipple","$mdTheming","$mdAria","$timeout"],e.$inject=["$mdTheming"],t.module("material.components.button",["material.core"]).directive("mdButton",n).directive("a",e)}(),function(){function e(e){return{restrict:"E",link:function(t,n,r){n.addClass("_md"),e(n)}}}e.$inject=["$mdTheming"],t.module("material.components.card",["material.core"]).directive("mdCard",e)}(),function(){t.module("material.components.chips",["material.core","material.components.autocomplete"])}(),function(){function e(e,n,r,i,o,a){function s(s,c){function l(s,c,l,u){function d(e,t,n){l[e]&&s.$watch(l[e],function(e){n[e]&&c.attr(t,n[e])})}function m(e){var t=e.which||e.keyCode;t!==r.KEY_CODE.SPACE&&t!==r.KEY_CODE.ENTER||(e.preventDefault(),c.addClass("md-focused"),f(e))}function f(e){c[0].hasAttribute("disabled")||s.skipToggle||s.$apply(function(){var t=l.ngChecked?l.checked:!u.$viewValue;u.$setViewValue(t,e&&e.type),u.$render()})}function h(){c.toggleClass("md-checked",!!u.$viewValue&&!g)}function p(e){g=e!==!1,g&&c.attr("aria-checked","mixed"),c.toggleClass("md-indeterminate",g)}var g;u=u||o.fakeNgModel(),i(c),c.children().on("focus",function(){c.focus()}),o.parseAttributeBoolean(l.mdIndeterminate)&&(p(),s.$watch(l.mdIndeterminate,p)),l.ngChecked&&s.$watch(s.$eval.bind(s,l.ngChecked),function(e){u.$setViewValue(e),u.$render()}),d("ngDisabled","tabindex",{"true":"-1","false":l.tabindex}),n.expectWithText(c,"aria-label"),e.link.pre(s,{on:t.noop,0:{}},l,[u]),s.mouseActive=!1,c.on("click",f).on("keypress",m).on("mousedown",function(){s.mouseActive=!0,a(function(){s.mouseActive=!1},100)}).on("focus",function(){s.mouseActive===!1&&c.addClass("md-focused")}).on("blur",function(){c.removeClass("md-focused")}),u.$render=h}return c.$set("tabindex",c.tabindex||"0"),c.$set("type","checkbox"),c.$set("role",c.type),{pre:function(e,t){t.on("click",function(e){this.hasAttribute("disabled")&&e.stopImmediatePropagation()})},post:l}}return e=e[0],{restrict:"E",transclude:!0,require:"?ngModel",priority:210,template:'
',compile:s}}e.$inject=["inputDirective","$mdAria","$mdConstant","$mdTheming","$mdUtil","$timeout"],t.module("material.components.checkbox",["material.core"]).directive("mdCheckbox",e)}(),function(){!function(){function e(e,n,r){function o(e,t){try{t&&e.css(c(t))}catch(n){r.error(n.message)}}function a(e){var t=u(e);return s(t)}function s(t,r){r=r||!1;var i=e.PALETTES[t.palette][t.hue];return i=r?i.contrast:i.value,n.supplant("rgba({0}, {1}, {2}, {3})",[i[0],i[1],i[2],i[3]||t.opacity])}function c(e){var n={},r=e.hasOwnProperty("color");return t.forEach(e,function(e,t){var i=u(e),o=t.indexOf("background")>-1;n[t]=s(i),o&&!r&&(n.color=s(i,!0))}),n}function l(n){return t.isDefined(e.THEMES[n.split("-")[0]])}function u(n){var r=n.split("-"),i=t.isDefined(e.THEMES[r[0]]),o=i?r.splice(0,1)[0]:e.defaultTheme();return{theme:o,palette:d(r,o),hue:m(r,o),opacity:r[2]||1}}function d(t,r){var o=t.length>1&&i.indexOf(t[1])!==-1,a=t[0].replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase();if(o&&(a=t[0]+"-"+t.splice(1,1)),i.indexOf(a)===-1){var s=e.THEMES[r].colors[a];if(!s)throw new Error(n.supplant("mdColors: couldn't find '{palette}' in the palettes.",{palette:a}));a=s.name}return a}function m(t,r){var i=e.THEMES[r].colors;if("hue"===t[1]){var o=parseInt(t.splice(2,1)[0],10);if(o<1||o>3)throw new Error(n.supplant("mdColors: 'hue-{hueNumber}' is not a valid hue, can be only 'hue-1', 'hue-2' and 'hue-3'",{hueNumber:o}));if(t[1]="hue-"+o,!(t[0]in i))throw new Error(n.supplant("mdColors: 'hue-x' can only be used with [{availableThemes}], but was used with '{usedTheme}'",{availableThemes:Object.keys(i).join(", "),usedTheme:t[0]}));return i[t[0]].hues[t[1]]}return t[1]||i[t[0]in i?t[0]:"primary"].hues["default"]}return i=i||Object.keys(e.PALETTES),{applyThemeColors:o,getThemeColor:a,hasTheme:l}}function n(e,n,i,o){return{restrict:"A",require:["^?mdTheme"],compile:function(a,s){function c(){var e=s.mdColors,i=e.indexOf("::")>-1,o=!!i||r.test(s.mdColors);s.mdColors=e.replace("::","");var a=t.isDefined(s.mdColorsWatch);return!i&&!o&&(!a||n.parseAttributeBoolean(s.mdColorsWatch))}var l=c();return function(n,r,a,s){var c=s[0],u={},d=function(t){"string"!=typeof t&&(t=""),a.mdColors||(a.mdColors="{}");var r=o(a.mdColors)(n);return c&&Object.keys(r).forEach(function(n){var i=r[n];e.hasTheme(i)||(r[n]=(t||c.$mdTheme)+"-"+i)}),m(r),r},m=function(e){if(!t.equals(e,u)){var n=Object.keys(u);u.background&&!n.color&&n.push("color"),n.forEach(function(e){r.css(e,"")})}u=e},f=t.noop;c&&(f=c.registerChanges(function(t){e.applyThemeColors(r,d(t))})),n.$on("$destroy",function(){f()});try{l?n.$watch(d,t.bind(this,e.applyThemeColors,r),!0):e.applyThemeColors(r,d())}catch(h){i.error(h.message)}}}}}n.$inject=["$mdColors","$mdUtil","$log","$parse"],e.$inject=["$mdTheming","$mdUtil","$log"];var r=/^{((\s|,)*?["'a-zA-Z-]+?\s*?:\s*?('|")[a-zA-Z0-9-.]*('|"))+\s*}$/,i=null;t.module("material.components.colors",["material.core"]).directive("mdColors",n).service("$mdColors",e)}()}(),function(){function e(e){function t(e,t){this.$scope=e,this.$element=t}return{restrict:"E",controller:["$scope","$element",t],link:function(t,r){r.addClass("_md"),e(r),t.$broadcast("$mdContentLoaded",r),n(r[0])}}}function n(e){t.element(e).on("$md.pressdown",function(t){"t"===t.pointer.type&&(t.$materialScrollFixed||(t.$materialScrollFixed=!0,0===e.scrollTop?e.scrollTop=1:e.scrollHeight===e.scrollTop+e.offsetHeight&&(e.scrollTop-=1)))})}e.$inject=["$mdTheming"],t.module("material.components.content",["material.core"]).directive("mdContent",e)}(),function(){t.module("material.components.datepicker",["material.core","material.components.icon","material.components.virtualRepeat"])}(),function(){function e(e,n,r){return{restrict:"E",link:function(i,o){o.addClass("_md"),n(o),e(function(){function e(){o.toggleClass("md-content-overflow",a.scrollHeight>a.clientHeight)}var n,a=o[0].querySelector("md-dialog-content");a&&(n=a.getElementsByTagName("img"),e(),t.element(n).on("load",e)),i.$on("$destroy",function(){r.destroy(o)})})}}}function r(e){function r(e,t){return{template:['',' ','

{{ dialog.title }}

','
','
',"

{{::dialog.mdTextContent}}

","
",' ',' '," ","
"," ",' '," {{ dialog.cancel }}"," ",' '," {{ dialog.ok }}"," "," ","
"].join("").replace(/\s\s+/g,""),controller:function(){var n="prompt"==this.$type;n&&this.initialValue&&(this.result=this.initialValue),this.hide=function(){e.hide(!n||this.result)},this.abort=function(){e.cancel()},this.keypress=function(n){n.keyCode===t.KEY_CODE.ENTER&&e.hide(this.result)}},controllerAs:"dialog",bindToController:!0}}function i(e,r,i,s,c,l,u,d,m,f,h){function p(e){$(e),e.contentElement&&(e.restoreContentElement=y(e))}function g(e,t,n,r){if(r){if(r.mdHtmlContent=r.htmlContent||n.htmlContent||"",r.mdTextContent=r.textContent||n.textContent||r.content||n.content||"",r.mdHtmlContent&&!f.has("$sanitize"))throw Error("The ngSanitize module must be loaded in order to use htmlContent.");if(r.mdHtmlContent&&r.mdTextContent)throw Error("md-dialog cannot have both `htmlContent` and `textContent`")}}function v(e,n,r,o){function a(){n[0].querySelector(".md-actions")&&m.warn("Using a class of md-actions is deprecated, please use .")}function s(){function e(){var e=n[0].querySelector(".dialog-close");if(!e){var t=n[0].querySelectorAll(".md-actions button, md-dialog-actions button");e=t[t.length-1]}return e}if(r.focusOnOpen){var t=i.findFocusTarget(n)||e()||c;t.focus()}}t.element(l[0].body).addClass("md-dialog-is-showing");var c=n.find("md-dialog");if(c.hasClass("ng-cloak")){var u="$mdDialog: using `` will affect the dialog opening animations.";m.warn(u,n[0])}return E(r),x(c,r),w(e,n,r),C(n,r),A(n,r).then(function(){k(n,r),a(),s()})}function b(e,n,r){function i(){return T(n,r)}function s(){t.element(l[0].body).removeClass("md-dialog-is-showing"),r.contentElement?(r.reverseContainerStretch(),r.restoreContentElement()):n.remove(),r.$destroy||r.origin.focus()}return r.deactivateListeners(),r.unlockScreenReader(),r.hideBackdrop(r.$destroy),o&&o.parentNode&&o.parentNode.removeChild(o),a&&a.parentNode&&a.parentNode.removeChild(a),r.$destroy?s():i().then(s)}function $(e){if(!e.theme&&(e.theme=h.defaultTheme(),e.targetEvent&&e.targetEvent.target)){var n=t.element(e.targetEvent.target);e.theme=(n.controller("mdTheme")||{}).$mdTheme||e.theme}}function y(e){function n(e){var t=e.parentNode,n=e.nextElementSibling;return function(){n?t.insertBefore(e,n):t.appendChild(e)}}var r=e.contentElement,i=null;return t.isString(r)?(r=document.querySelector(r),i=n(r)):(r=r[0]||r,i=document.contains(r)?n(r):function(){r.parentNode.removeChild(r)}),e.element=t.element(r),e.skipCompile=!0,i}function E(e){function r(e,r){var i=t.element(e||{});if(i&&i.length){var o={top:0,left:0,height:0,width:0},a=t.isFunction(i[0].getBoundingClientRect);return t.extend(r||{},{element:a?i:n,bounds:a?i[0].getBoundingClientRect():t.extend({},o,i[0]),focus:t.bind(i,i.focus)})}}function i(e,n){return t.isString(e)&&(e=l[0].querySelector(e)),t.element(e||n)}e.origin=t.extend({element:null,bounds:null,focus:t.noop},e.origin||{}),e.parent=i(e.parent,d),e.closeTo=r(i(e.closeTo)),e.openFrom=r(i(e.openFrom)),e.targetEvent&&(e.origin=r(e.targetEvent.target,e.origin))}function C(n,r){var o=t.element(u),a=i.debounce(function(){M(n,r)},60),c=[],l=function(){var t="alert"==r.$type?e.hide:e.cancel;i.nextTick(t,!0)};if(r.escapeToClose){var d=r.parent,m=function(e){e.keyCode===s.KEY_CODE.ESCAPE&&(e.stopPropagation(),e.preventDefault(),l())};n.on("keydown",m),d.on("keydown",m),c.push(function(){n.off("keydown",m),d.off("keydown",m)})}if(o.on("resize",a),c.push(function(){o.off("resize",a)}),r.clickOutsideToClose){var f,h=n,p=function(e){f=e.target},g=function(e){f===h[0]&&e.target===h[0]&&(e.stopPropagation(),e.preventDefault(),l())};h.on("mousedown",p),h.on("mouseup",g),c.push(function(){h.off("mousedown",p),h.off("mouseup",g)})}r.deactivateListeners=function(){c.forEach(function(e){e()}),r.deactivateListeners=null}}function w(e,t,n){n.disableParentScroll&&(n.restoreScroll=i.disableScrollAround(t,n.parent)),n.hasBackdrop&&(n.backdrop=i.createBackdrop(e,"md-dialog-backdrop md-opaque"),c.enter(n.backdrop,n.parent)),n.hideBackdrop=function(e){n.backdrop&&(e?n.backdrop.remove():c.leave(n.backdrop)),n.disableParentScroll&&(n.restoreScroll(),delete n.restoreScroll),n.hideBackdrop=null}}function x(e,t){var n="alert"===t.$type?"alertdialog":"dialog",s=e.find("md-dialog-content"),c=e.attr("id"),l="dialogContent_"+(c||i.nextUid());e.attr({role:n,tabIndex:"-1"}),0===s.length&&(s=e,c&&(l=c)),s.attr("id",l),e.attr("aria-describedby",l),t.ariaLabel?r.expect(e,"aria-label",t.ariaLabel):r.expectAsync(e,"aria-label",function(){var e=s.text().split(/\s+/);return e.length>3&&(e=e.slice(0,3).concat("...")),e.join(" ")}),o=document.createElement("div"),o.classList.add("md-dialog-focus-trap"),o.tabIndex=0,a=o.cloneNode(!1);var u=function(){e.focus()};o.addEventListener("focus",u),a.addEventListener("focus",u),e[0].parentNode.insertBefore(o,e[0]),e.after(a)}function k(e,t){function n(e){for(;e.parentNode;){if(e===document.body)return;for(var t=e.parentNode.children,i=0;i/g.test(e)?""+(e||"")+"":e||""}return'
'+n(e)+"
"}}}r.$inject=["$mdDialog","$mdConstant"],i.$inject=["$mdDialog","$mdAria","$mdUtil","$mdConstant","$animate","$document","$window","$rootElement","$log","$injector","$mdTheming"];var o,a;return e("$mdDialog").setDefaults({methods:["disableParentScroll","hasBackdrop","clickOutsideToClose","escapeToClose","targetEvent","closeTo","openFrom","parent","fullscreen","contentElement"],options:i}).addPreset("alert",{methods:["title","htmlContent","textContent","content","ariaLabel","ok","theme","css"],options:r}).addPreset("confirm",{methods:["title","htmlContent","textContent","content","ariaLabel","ok","cancel","theme","css"],options:r}).addPreset("prompt",{methods:["title","htmlContent","textContent","initialValue","content","placeholder","ariaLabel","ok","cancel","theme","css"],options:r})}e.$inject=["$$rAF","$mdTheming","$mdDialog"],r.$inject=["$$interimElementProvider"],t.module("material.components.dialog",["material.core","material.components.backdrop"]).directive("mdDialog",e).provider("$mdDialog",r)}(),function(){function e(e){return{restrict:"E",link:e}}e.$inject=["$mdTheming"],t.module("material.components.divider",["material.core"]).directive("mdDivider",e)}(),function(){!function(){function e(e){return{restrict:"E",require:["^?mdFabSpeedDial","^?mdFabToolbar"],compile:function(t,n){var r=t.children(),i=e.prefixer().hasAttribute(r,"ng-repeat");i?r.addClass("md-fab-action-item"):r.wrap('
')}}}e.$inject=["$mdUtil"],t.module("material.components.fabActions",["material.core"]).directive("mdFabActions",e)}()}(),function(){!function(){function e(e,n,r,i,o,a){function s(){_.direction=_.direction||"down",_.isOpen=_.isOpen||!1,u(),n.addClass("md-animations-waiting")}function c(){var r=["click","focusin","focusout"];t.forEach(r,function(e){n.on(e,l)}),e.$on("$destroy",function(){t.forEach(r,function(e){n.off(e,l)}),h()})}function l(e){"click"==e.type&&A(e),"focusout"!=e.type||D||(D=a(function(){_.close()},100,!1)),"focusin"==e.type&&D&&(a.cancel(D),D=null)}function u(){_.currentActionIndex=-1}function d(){e.$watch("vm.direction",function(e,t){r.removeClass(n,"md-"+t),r.addClass(n,"md-"+e),u()});var t,i;e.$watch("vm.isOpen",function(e){u(),t&&i||(t=T(),i=S()),e?f():h();var o=e?"md-is-open":"",a=e?"":"md-is-open";t.attr("aria-haspopup",!0),t.attr("aria-expanded",e),i.attr("aria-hidden",!e),r.setClass(n,o,a)})}function m(){n[0].scrollHeight>0?r.addClass(n,"_md-animations-ready").then(function(){n.removeClass("md-animations-waiting")}):N<10&&(a(m,100),N+=1)}function f(){n.on("keydown",g),i.nextTick(function(){t.element(document).on("click touchend",p)})}function h(){n.off("keydown",g),t.element(document).off("click touchend",p)}function p(e){if(e.target){var t=i.getClosest(e.target,"md-fab-trigger"),n=i.getClosest(e.target,"md-fab-actions");t||n||_.close()}}function g(e){switch(e.which){case o.KEY_CODE.ESCAPE:return _.close(),e.preventDefault(),!1;case o.KEY_CODE.LEFT_ARROW:return E(e),!1;case o.KEY_CODE.UP_ARROW:return C(e),!1;case o.KEY_CODE.RIGHT_ARROW:return w(e),!1;case o.KEY_CODE.DOWN_ARROW:return x(e),!1}}function v(e){$(e,-1)}function b(e){$(e,1)}function $(e,n){var r=y();_.currentActionIndex=_.currentActionIndex+n,_.currentActionIndex=Math.min(r.length-1,_.currentActionIndex),_.currentActionIndex=Math.max(0,_.currentActionIndex);var i=t.element(r[_.currentActionIndex]).children()[0];t.element(i).attr("tabindex",0),i.focus(),e.preventDefault(),e.stopImmediatePropagation()}function y(){var e=S()[0].querySelectorAll(".md-fab-action-item");return t.forEach(e,function(e){t.element(t.element(e).children()[0]).attr("tabindex",-1)}),e}function E(e){"left"===_.direction?b(e):v(e)}function C(e){"down"===_.direction?v(e):b(e)}function w(e){"left"===_.direction?v(e):b(e)}function x(e){"up"===_.direction?v(e):b(e)}function k(e){return i.getClosest(e,"md-fab-trigger")}function M(e){return i.getClosest(e,"md-fab-actions")}function A(e){k(e.target)&&_.toggle(),M(e.target)&&_.close()}function T(){return n.find("md-fab-trigger")}function S(){return n.find("md-fab-actions")}var _=this;_.open=function(){e.$evalAsync("vm.isOpen = true")},_.close=function(){e.$evalAsync("vm.isOpen = false"),n.find("md-fab-trigger")[0].focus()},_.toggle=function(){e.$evalAsync("vm.isOpen = !vm.isOpen")},s(),c(),d();var N=0;m();var D}e.$inject=["$scope","$element","$animate","$mdUtil","$mdConstant","$timeout"],t.module("material.components.fabShared",["material.core"]).controller("MdFabController",e)}()}(),function(){!function(){function n(){function e(e,t){t.prepend('
')}return{restrict:"E",scope:{direction:"@?mdDirection",isOpen:"=?mdOpen"},bindToController:!0,controller:"MdFabController",controllerAs:"vm",link:e}}function r(n){function r(e){n(e,o,!1)}function i(n){if(!n.hasClass("md-animations-waiting")||n.hasClass("_md-animations-ready")){var r=n[0],i=n.controller("mdFabSpeedDial"),o=r.querySelectorAll(".md-fab-action-item"),a=r.querySelector("md-fab-trigger"),s=r.querySelector("._md-css-variables"),c=parseInt(e.getComputedStyle(s).zIndex);t.forEach(o,function(e,t){var n=e.style;n.transform=n.webkitTransform="",n.transitionDelay="",n.opacity=1,n.zIndex=o.length-t+c}),a.style.zIndex=c+o.length+1,i.isOpen||t.forEach(o,function(e,t){var n,r,o=e.style,s=(a.clientHeight-e.clientHeight)/2,c=(a.clientWidth-e.clientWidth)/2;switch(i.direction){case"up":n=e.scrollHeight*(t+1)+s,r="Y";break;case"down":n=-(e.scrollHeight*(t+1)+s),r="Y";break;case"left":n=e.scrollWidth*(t+1)+c,r="X";break;case"right":n=-(e.scrollWidth*(t+1)+c),r="X"}var l="translate"+r+"("+n+"px)";o.transform=o.webkitTransform=l})}}return{addClass:function(e,t,n){e.hasClass("md-fling")?(i(e),r(n)):n()},removeClass:function(e,t,n){i(e),r(n)}}}function i(n){function r(e){n(e,o,!1)}function i(n){var r=n[0],i=n.controller("mdFabSpeedDial"),o=r.querySelectorAll(".md-fab-action-item"),s=r.querySelector("._md-css-variables"),c=parseInt(e.getComputedStyle(s).zIndex);t.forEach(o,function(e,t){var n=e.style,r=t*a;n.opacity=i.isOpen?1:0,n.transform=n.webkitTransform=i.isOpen?"scale(1)":"scale(0)",n.transitionDelay=(i.isOpen?r:o.length-r)+"ms",n.zIndex=o.length-t+c})}var a=65;return{addClass:function(e,t,n){i(e),r(n)},removeClass:function(e,t,n){i(e),r(n)}}}r.$inject=["$timeout"],i.$inject=["$timeout"];var o=300;t.module("material.components.fabSpeedDial",["material.core","material.components.fabShared","material.components.fabActions"]).directive("mdFabSpeedDial",n).animation(".md-fling",r).animation(".md-scale",i).service("mdFabSpeedDialFlingAnimation",r).service("mdFabSpeedDialScaleAnimation",i)}()}(),function(){!function(){function n(){function e(e,t,n){t.addClass("md-fab-toolbar"),t.find("md-fab-trigger").find("button").prepend('
')}return{restrict:"E",transclude:!0,template:'
',scope:{direction:"@?mdDirection",isOpen:"=?mdOpen"},bindToController:!0,controller:"MdFabController",controllerAs:"vm",link:e}}function r(){function n(n,r,i){if(r){var o=n[0],a=n.controller("mdFabToolbar"),s=o.querySelector(".md-fab-toolbar-background"),c=o.querySelector("md-fab-trigger button"),l=o.querySelector("md-toolbar"),u=o.querySelector("md-fab-trigger button md-icon"),d=n.find("md-fab-actions").children();if(c&&s){var m=e.getComputedStyle(c).getPropertyValue("background-color"),f=o.offsetWidth,h=(o.offsetHeight,2*(f/c.offsetWidth));s.style.backgroundColor=m,s.style.borderRadius=f+"px",a.isOpen?(l.style.pointerEvents="inherit",s.style.width=c.offsetWidth+"px",s.style.height=c.offsetHeight+"px",s.style.transform="scale("+h+")",s.style.transitionDelay="0ms",u&&(u.style.transitionDelay=".3s"),t.forEach(d,function(e,t){e.style.transitionDelay=25*(d.length-t)+"ms"})):(l.style.pointerEvents="none",s.style.transform="scale(1)",s.style.top="0",n.hasClass("md-right")&&(s.style.left="0",s.style.right=null),n.hasClass("md-left")&&(s.style.right="0",s.style.left=null),s.style.transitionDelay="200ms",u&&(u.style.transitionDelay="0ms"),t.forEach(d,function(e,t){e.style.transitionDelay=200+25*t+"ms"}))}}}return{addClass:function(e,t,r){n(e,t,r),r()},removeClass:function(e,t,r){n(e,t,r),r()}}}t.module("material.components.fabToolbar",["material.core","material.components.fabShared","material.components.fabActions"]).directive("mdFabToolbar",n).animation(".md-fab-toolbar",r).service("mdFabToolbarAnimation",r)}()}(),function(){function e(e,r,i,o){function a(n,a,s,c){function l(){for(var e in r.MEDIA)o(e),o.getQuery(r.MEDIA[e]).addListener(w);return o.watchResponsiveAttributes(["md-cols","md-row-height","md-gutter"],s,d)}function u(){c.layoutDelegate=t.noop,x();for(var e in r.MEDIA)o.getQuery(r.MEDIA[e]).removeListener(w)}function d(e){null==e?c.invalidateLayout():o(e)&&c.invalidateLayout()}function m(e){var r=g(),o={tileSpans:v(r),colCount:b(),rowMode:E(),rowHeight:y(),gutter:$()};if(e||!t.equals(o,k)){var s=i(o.colCount,o.tileSpans,r).map(function(e,n){return{grid:{element:a,style:p(o.colCount,n,o.gutter,o.rowMode,o.rowHeight)},tiles:e.map(function(e,i){return{element:t.element(r[i]),style:h(e.position,e.spans,o.colCount,n,o.gutter,o.rowMode,o.rowHeight)}})}}).reflow().performance();n.mdOnLayout({$event:{performance:s}}),k=o}}function f(e){return M+e+A}function h(e,t,n,r,i,o,a){var s=1/n*100,c=(n-1)/n,l=T({share:s,gutterShare:c,gutter:i}),u={left:S({unit:l,offset:e.col,gutter:i}),width:_({unit:l,span:t.col,gutter:i}),paddingTop:"",marginTop:"",top:"",height:""};switch(o){case"fixed":u.top=S({unit:a,offset:e.row,gutter:i}),u.height=_({unit:a,span:t.row,gutter:i});break;case"ratio":var d=s/a,m=T({share:d,gutterShare:c,gutter:i});u.paddingTop=_({unit:m,span:t.row,gutter:i}),u.marginTop=S({unit:m,offset:e.row,gutter:i});break;case"fit":var f=(r-1)/r,d=1/r*100,m=T({share:d,gutterShare:f,gutter:i});u.top=S({unit:m,offset:e.row,gutter:i}),u.height=_({unit:m,span:t.row,gutter:i})}return u}function p(e,t,n,r,i){var o={};switch(r){case"fixed":o.height=_({unit:i,span:t,gutter:n}),o.paddingBottom="";break;case"ratio":var a=1===e?0:(e-1)/e,s=1/e*100,c=s*(1/i),l=T({share:c,gutterShare:a,gutter:n});o.height="",o.paddingBottom=_({unit:l,span:t,gutter:n});break;case"fit":}return o}function g(){return[].filter.call(a.children(),function(e){return"MD-GRID-TILE"==e.tagName&&!e.$$mdDestroyed})}function v(e){return[].map.call(e,function(e){var n=t.element(e).controller("mdGridTile");return{row:parseInt(o.getResponsiveAttribute(n.$attrs,"md-rowspan"),10)||1,col:parseInt(o.getResponsiveAttribute(n.$attrs,"md-colspan"),10)||1}})}function b(){var e=parseInt(o.getResponsiveAttribute(s,"md-cols"),10);if(isNaN(e))throw"md-grid-list: md-cols attribute was not found, or contained a non-numeric value"; +return e}function $(){return C(o.getResponsiveAttribute(s,"md-gutter")||1)}function y(){var e=o.getResponsiveAttribute(s,"md-row-height");if(!e)throw"md-grid-list: md-row-height attribute was not found";switch(E()){case"fixed":return C(e);case"ratio":var t=e.split(":");return parseFloat(t[0])/parseFloat(t[1]);case"fit":return 0}}function E(){var e=o.getResponsiveAttribute(s,"md-row-height");if(!e)throw"md-grid-list: md-row-height attribute was not found";return"fit"==e?"fit":e.indexOf(":")!==-1?"ratio":"fixed"}function C(e){return/\D$/.test(e)?e:e+"px"}a.addClass("_md"),a.attr("role","list"),c.layoutDelegate=m;var w=t.bind(c,c.invalidateLayout),x=l();n.$on("$destroy",u);var k,M=e.startSymbol(),A=e.endSymbol(),T=e(f("share")+"% - ("+f("gutter")+" * "+f("gutterShare")+")"),S=e("calc(("+f("unit")+" + "+f("gutter")+") * "+f("offset")+")"),_=e("calc(("+f("unit")+") * "+f("span")+" + ("+f("span")+" - 1) * "+f("gutter")+")")}return{restrict:"E",controller:n,scope:{mdOnLayout:"&"},link:a}}function n(e){this.layoutInvalidated=!1,this.tilesInvalidated=!1,this.$timeout_=e.nextTick,this.layoutDelegate=t.noop}function r(e){function n(t,n){var r,a,s,c,l,u;return c=e.time(function(){a=i(t,n)}),r={layoutInfo:function(){return a},map:function(t){return l=e.time(function(){var e=r.layoutInfo();s=t(e.positioning,e.rowCount)}),r},reflow:function(t){return u=e.time(function(){var e=t||o;e(s.grid,s.tiles)}),r},performance:function(){return{tileCount:n.length,layoutTime:c,mapTime:l,reflowTime:u,totalTime:c+l+u}}}}function r(e,t){e.element.css(e.style),t.forEach(function(e){e.element.css(e.style)})}function i(e,t){function n(t,n){if(t.col>e)throw"md-grid-list: Tile at position "+n+" has a colspan ("+t.col+") that exceeds the column count ("+e+")";for(var a=0,u=0;u-a=e?r():(a=l.indexOf(0,s),a!==-1&&(u=o(a+1))!==-1?s=u+1:(a=u=0,r()));return i(a,t.col,t.row),s=a+t.col,{col:a,row:c}}function r(){s=0,c++,i(0,e,-1)}function i(e,t,n){for(var r=e;r",transclude:!0,scope:{},controller:["$attrs",function(e){this.$attrs=e}],link:n}}function o(){return{template:"
",transclude:!0}}n.$inject=["$mdUtil"],r.$inject=["$mdUtil"],e.$inject=["$interpolate","$mdConstant","$mdGridLayout","$mdMedia"],i.$inject=["$mdMedia"],t.module("material.components.gridList",["material.core"]).directive("mdGridList",e).directive("mdGridTile",i).directive("mdGridTileFooter",o).directive("mdGridTileHeader",o).factory("$mdGridLayout",r),n.prototype={invalidateTiles:function(){this.tilesInvalidated=!0,this.invalidateLayout()},invalidateLayout:function(){this.layoutInvalidated||(this.layoutInvalidated=!0,this.$timeout_(t.bind(this,this.layout)))},layout:function(){try{this.layoutDelegate(this.tilesInvalidated)}finally{this.layoutInvalidated=!1,this.tilesInvalidated=!1}}}}(),function(){t.module("material.components.icon",["material.core"])}(),function(){function n(e,t){function n(t){var n=t[0].querySelector(o),r=t[0].querySelector(a);return n&&t.addClass("md-icon-left"),r&&t.addClass("md-icon-right"),function(t,n){e(n)}}function r(e,n,r,i){var o=this;o.isErrorGetter=r.mdIsError&&t(r.mdIsError),o.delegateClick=function(){o.input.focus()},o.element=n,o.setFocused=function(e){n.toggleClass("md-input-focused",!!e)},o.setHasValue=function(e){n.toggleClass("md-input-has-value",!!e)},o.setHasPlaceholder=function(e){n.toggleClass("md-input-has-placeholder",!!e)},o.setInvalid=function(e){e?i.addClass(n,"md-input-invalid"):i.removeClass(n,"md-input-invalid")},e.$watch(function(){return o.label&&o.input},function(e){e&&!o.label.attr("for")&&o.label.attr("for",o.input.attr("id"))})}r.$inject=["$scope","$element","$attrs","$animate"];var i=["INPUT","TEXTAREA","SELECT","MD-SELECT"],o=i.reduce(function(e,t){return e.concat(["md-icon ~ "+t,".md-icon ~ "+t])},[]).join(","),a=i.reduce(function(e,t){return e.concat([t+" ~ md-icon",t+" ~ .md-icon"])},[]).join(",");return{restrict:"E",compile:n,controller:r}}function r(){return{restrict:"E",require:"^?mdInputContainer",link:function(e,t,n,r){!r||n.mdNoFloat||t.hasClass("md-container-ignore")||(r.label=t,e.$on("$destroy",function(){r.label=null}))}}}function i(e,n,r,i,o){function a(a,s,c,l){function u(e){return h.setHasValue(!g.$isEmpty(e)),e}function d(){h.label&&c.$observe("required",function(e){h.label.toggleClass("md-required",e&&!$)})}function m(){h.setHasValue(s.val().length>0||(s[0].validity||{}).badInput)}function f(){function r(){s.attr("rows",1).css("height","auto").addClass("md-no-flex");var e=l();if(!y){var t=s[0].style.padding||"";y=s.css("padding",0).prop("offsetHeight"),s[0].style.padding=t}if(v&&y&&(e=Math.max(e,y*v)),b&&y){var n=y*b;n-1&&g.$formatters.splice(e,1)}}function m(){function n(e){e.preventDefault(),m=!0,f=e.clientY,p=parseFloat(s.css("height"))||s.prop("offsetHeight")}function r(e){m&&(e.preventDefault(),d(),g.addClass("md-input-resized"))}function i(t){m&&s.css("height",p+(t.pointer.y-f)-e.scrollTop()+"px")}function l(e){m&&(m=!1,g.removeClass("md-input-resized"))}if(!c.hasOwnProperty("mdNoResize")){var u=t.element('
'),m=!1,f=null,p=0,g=h.element,v=o.register(u,"drag",{horizontal:!1});s.wrap('
').after(u),u.on("mousedown",n),g.on("$md.dragstart",r).on("$md.drag",i).on("$md.dragend",l),a.$on("$destroy",function(){u.off("mousedown",n).remove(),g.off("$md.dragstart",r).off("$md.drag",i).off("$md.dragend",l),v(),u=null,g=null,v=null})}}var f=!c.hasOwnProperty("mdNoAutogrow");if(m(),f){var v=c.hasOwnProperty("rows")?parseInt(c.rows):NaN,b=c.hasOwnProperty("maxRows")?parseInt(c.maxRows):NaN,$=a.$on("md-resize-textarea",r),y=null,E=s[0];if(i(function(){e.nextTick(r)},10,!1),s.on("input",r),p&&g.$formatters.push(u),v||s.attr("rows",1),t.element(n).on("resize",r),a.$on("$destroy",d),c.hasOwnProperty("mdDetectHidden")){var C=function(){var e=!1;return function(){var t=0===E.offsetHeight;t===!1&&e===!0&&r(),e=t}}();a.$watch(function(){return e.nextTick(C,!1),!0})}}}var h=l[0],p=!!l[1],g=l[1]||e.fakeNgModel(),v=l[2],b=t.isDefined(c.readonly),$=e.parseAttributeBoolean(c.mdNoAsterisk),y=s[0].tagName.toLowerCase();if(h){if("hidden"===c.type)return void s.attr("aria-hidden","true");if(h.input){if(h.input[0].contains(s[0]))return;throw new Error(" can only have *one* ,
\n\t
\n\t
\n\t \n\t \n\t it('should auto compile', function() {\n\t var textarea = $('textarea');\n\t var output = $('div[compile]');\n\t // The initial state reads 'Hello Angular'.\n\t expect(output.getText()).toBe('Hello Angular');\n\t textarea.clear();\n\t textarea.sendKeys('{{name}}!');\n\t expect(output.getText()).toBe('Angular!');\n\t });\n\t \n\t \n\t\n\t *\n\t *\n\t * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n\t * @param {function(angular.Scope, cloneAttachFn=)} transclude function available to directives - DEPRECATED.\n\t *\n\t *
\n\t * **Note:** Passing a `transclude` function to the $compile function is deprecated, as it\n\t * e.g. will not use the right outer scope. Please pass the transclude function as a\n\t * `parentBoundTranscludeFn` to the link function instead.\n\t *
\n\t *\n\t * @param {number} maxPriority only apply directives lower than given priority (Only effects the\n\t * root element(s), not their children)\n\t * @returns {function(scope, cloneAttachFn=, options=)} a link function which is used to bind template\n\t * (a DOM element/tree) to a scope. Where:\n\t *\n\t * * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n\t * * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n\t * `template` and call the `cloneAttachFn` function allowing the caller to attach the\n\t * cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n\t * called as:
`cloneAttachFn(clonedElement, scope)` where:\n\t *\n\t * * `clonedElement` - is a clone of the original `element` passed into the compiler.\n\t * * `scope` - is the current scope with which the linking function is working with.\n\t *\n\t * * `options` - An optional object hash with linking options. If `options` is provided, then the following\n\t * keys may be used to control linking behavior:\n\t *\n\t * * `parentBoundTranscludeFn` - the transclude function made available to\n\t * directives; if given, it will be passed through to the link functions of\n\t * directives found in `element` during compilation.\n\t * * `transcludeControllers` - an object hash with keys that map controller names\n\t * to a hash with the key `instance`, which maps to the controller instance;\n\t * if given, it will make the controllers available to directives on the compileNode:\n\t * ```\n\t * {\n\t * parent: {\n\t * instance: parentControllerInstance\n\t * }\n\t * }\n\t * ```\n\t * * `futureParentElement` - defines the parent to which the `cloneAttachFn` will add\n\t * the cloned elements; only needed for transcludes that are allowed to contain non html\n\t * elements (e.g. SVG elements). See also the directive.controller property.\n\t *\n\t * Calling the linking function returns the element of the template. It is either the original\n\t * element passed in, or the clone of the element if the `cloneAttachFn` is provided.\n\t *\n\t * After linking the view is not updated until after a call to $digest which typically is done by\n\t * Angular automatically.\n\t *\n\t * If you need access to the bound view, there are two ways to do it:\n\t *\n\t * - If you are not asking the linking function to clone the template, create the DOM element(s)\n\t * before you send them to the compiler and keep this reference around.\n\t * ```js\n\t * var element = $compile('

{{total}}

')(scope);\n\t * ```\n\t *\n\t * - if on the other hand, you need the element to be cloned, the view reference from the original\n\t * example would not point to the clone, but rather to the original template that was cloned. In\n\t * this case, you can access the clone via the cloneAttachFn:\n\t * ```js\n\t * var templateElement = angular.element('

{{total}}

'),\n\t * scope = ....;\n\t *\n\t * var clonedElement = $compile(templateElement)(scope, function(clonedElement, scope) {\n\t * //attach the clone to DOM document at the right place\n\t * });\n\t *\n\t * //now we have reference to the cloned DOM via `clonedElement`\n\t * ```\n\t *\n\t *\n\t * For information on how the compiler works, see the\n\t * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n\t */\n\t\n\tvar $compileMinErr = minErr('$compile');\n\t\n\tfunction UNINITIALIZED_VALUE() {}\n\tvar _UNINITIALIZED_VALUE = new UNINITIALIZED_VALUE();\n\t\n\t/**\n\t * @ngdoc provider\n\t * @name $compileProvider\n\t *\n\t * @description\n\t */\n\t$CompileProvider.$inject = ['$provide', '$$sanitizeUriProvider'];\n\tfunction $CompileProvider($provide, $$sanitizeUriProvider) {\n\t var hasDirectives = {},\n\t Suffix = 'Directive',\n\t COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\w\\-]+)\\s+(.*)$/,\n\t CLASS_DIRECTIVE_REGEXP = /(([\\w\\-]+)(?:\\:([^;]+))?;?)/,\n\t ALL_OR_NOTHING_ATTRS = makeMap('ngSrc,ngSrcset,src,srcset'),\n\t REQUIRE_PREFIX_REGEXP = /^(?:(\\^\\^?)?(\\?)?(\\^\\^?)?)?/;\n\t\n\t // Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes\n\t // The assumption is that future DOM event attribute names will begin with\n\t // 'on' and be composed of only English letters.\n\t var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/;\n\t var bindingCache = createMap();\n\t\n\t function parseIsolateBindings(scope, directiveName, isController) {\n\t var LOCAL_REGEXP = /^\\s*([@&<]|=(\\*?))(\\??)\\s*(\\w*)\\s*$/;\n\t\n\t var bindings = createMap();\n\t\n\t forEach(scope, function(definition, scopeName) {\n\t if (definition in bindingCache) {\n\t bindings[scopeName] = bindingCache[definition];\n\t return;\n\t }\n\t var match = definition.match(LOCAL_REGEXP);\n\t\n\t if (!match) {\n\t throw $compileMinErr('iscp',\n\t \"Invalid {3} for directive '{0}'.\" +\n\t \" Definition: {... {1}: '{2}' ...}\",\n\t directiveName, scopeName, definition,\n\t (isController ? \"controller bindings definition\" :\n\t \"isolate scope definition\"));\n\t }\n\t\n\t bindings[scopeName] = {\n\t mode: match[1][0],\n\t collection: match[2] === '*',\n\t optional: match[3] === '?',\n\t attrName: match[4] || scopeName\n\t };\n\t if (match[4]) {\n\t bindingCache[definition] = bindings[scopeName];\n\t }\n\t });\n\t\n\t return bindings;\n\t }\n\t\n\t function parseDirectiveBindings(directive, directiveName) {\n\t var bindings = {\n\t isolateScope: null,\n\t bindToController: null\n\t };\n\t if (isObject(directive.scope)) {\n\t if (directive.bindToController === true) {\n\t bindings.bindToController = parseIsolateBindings(directive.scope,\n\t directiveName, true);\n\t bindings.isolateScope = {};\n\t } else {\n\t bindings.isolateScope = parseIsolateBindings(directive.scope,\n\t directiveName, false);\n\t }\n\t }\n\t if (isObject(directive.bindToController)) {\n\t bindings.bindToController =\n\t parseIsolateBindings(directive.bindToController, directiveName, true);\n\t }\n\t if (isObject(bindings.bindToController)) {\n\t var controller = directive.controller;\n\t var controllerAs = directive.controllerAs;\n\t if (!controller) {\n\t // There is no controller, there may or may not be a controllerAs property\n\t throw $compileMinErr('noctrl',\n\t \"Cannot bind to controller without directive '{0}'s controller.\",\n\t directiveName);\n\t } else if (!identifierForController(controller, controllerAs)) {\n\t // There is a controller, but no identifier or controllerAs property\n\t throw $compileMinErr('noident',\n\t \"Cannot bind to controller without identifier for directive '{0}'.\",\n\t directiveName);\n\t }\n\t }\n\t return bindings;\n\t }\n\t\n\t function assertValidDirectiveName(name) {\n\t var letter = name.charAt(0);\n\t if (!letter || letter !== lowercase(letter)) {\n\t throw $compileMinErr('baddir', \"Directive/Component name '{0}' is invalid. The first character must be a lowercase letter\", name);\n\t }\n\t if (name !== name.trim()) {\n\t throw $compileMinErr('baddir',\n\t \"Directive/Component name '{0}' is invalid. The name should not contain leading or trailing whitespaces\",\n\t name);\n\t }\n\t }\n\t\n\t function getDirectiveRequire(directive) {\n\t var require = directive.require || (directive.controller && directive.name);\n\t\n\t if (!isArray(require) && isObject(require)) {\n\t forEach(require, function(value, key) {\n\t var match = value.match(REQUIRE_PREFIX_REGEXP);\n\t var name = value.substring(match[0].length);\n\t if (!name) require[key] = match[0] + key;\n\t });\n\t }\n\t\n\t return require;\n\t }\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $compileProvider#directive\n\t * @kind function\n\t *\n\t * @description\n\t * Register a new directive with the compiler.\n\t *\n\t * @param {string|Object} name Name of the directive in camel-case (i.e. ngBind which\n\t * will match as ng-bind), or an object map of directives where the keys are the\n\t * names and the values are the factories.\n\t * @param {Function|Array} directiveFactory An injectable directive factory function. See the\n\t * {@link guide/directive directive guide} and the {@link $compile compile API} for more info.\n\t * @returns {ng.$compileProvider} Self for chaining.\n\t */\n\t this.directive = function registerDirective(name, directiveFactory) {\n\t assertNotHasOwnProperty(name, 'directive');\n\t if (isString(name)) {\n\t assertValidDirectiveName(name);\n\t assertArg(directiveFactory, 'directiveFactory');\n\t if (!hasDirectives.hasOwnProperty(name)) {\n\t hasDirectives[name] = [];\n\t $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n\t function($injector, $exceptionHandler) {\n\t var directives = [];\n\t forEach(hasDirectives[name], function(directiveFactory, index) {\n\t try {\n\t var directive = $injector.invoke(directiveFactory);\n\t if (isFunction(directive)) {\n\t directive = { compile: valueFn(directive) };\n\t } else if (!directive.compile && directive.link) {\n\t directive.compile = valueFn(directive.link);\n\t }\n\t directive.priority = directive.priority || 0;\n\t directive.index = index;\n\t directive.name = directive.name || name;\n\t directive.require = getDirectiveRequire(directive);\n\t directive.restrict = directive.restrict || 'EA';\n\t directive.$$moduleName = directiveFactory.$$moduleName;\n\t directives.push(directive);\n\t } catch (e) {\n\t $exceptionHandler(e);\n\t }\n\t });\n\t return directives;\n\t }]);\n\t }\n\t hasDirectives[name].push(directiveFactory);\n\t } else {\n\t forEach(name, reverseParams(registerDirective));\n\t }\n\t return this;\n\t };\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $compileProvider#component\n\t * @module ng\n\t * @param {string} name Name of the component in camelCase (i.e. `myComp` which will match ``)\n\t * @param {Object} options Component definition object (a simplified\n\t * {@link ng.$compile#directive-definition-object directive definition object}),\n\t * with the following properties (all optional):\n\t *\n\t * - `controller` – `{(string|function()=}` – controller constructor function that should be\n\t * associated with newly created scope or the name of a {@link ng.$compile#-controller-\n\t * registered controller} if passed as a string. An empty `noop` function by default.\n\t * - `controllerAs` – `{string=}` – identifier name for to reference the controller in the component's scope.\n\t * If present, the controller will be published to scope under the `controllerAs` name.\n\t * If not present, this will default to be `$ctrl`.\n\t * - `template` – `{string=|function()=}` – html template as a string or a function that\n\t * returns an html template as a string which should be used as the contents of this component.\n\t * Empty string by default.\n\t *\n\t * If `template` is a function, then it is {@link auto.$injector#invoke injected} with\n\t * the following locals:\n\t *\n\t * - `$element` - Current element\n\t * - `$attrs` - Current attributes object for the element\n\t *\n\t * - `templateUrl` – `{string=|function()=}` – path or function that returns a path to an html\n\t * template that should be used as the contents of this component.\n\t *\n\t * If `templateUrl` is a function, then it is {@link auto.$injector#invoke injected} with\n\t * the following locals:\n\t *\n\t * - `$element` - Current element\n\t * - `$attrs` - Current attributes object for the element\n\t *\n\t * - `bindings` – `{object=}` – defines bindings between DOM attributes and component properties.\n\t * Component properties are always bound to the component controller and not to the scope.\n\t * See {@link ng.$compile#-bindtocontroller- `bindToController`}.\n\t * - `transclude` – `{boolean=}` – whether {@link $compile#transclusion content transclusion} is enabled.\n\t * Disabled by default.\n\t * - `require` - `{Object=}` - requires the controllers of other directives and binds them to\n\t * this component's controller. The object keys specify the property names under which the required\n\t * controllers (object values) will be bound. See {@link ng.$compile#-require- `require`}.\n\t * - `$...` – additional properties to attach to the directive factory function and the controller\n\t * constructor function. (This is used by the component router to annotate)\n\t *\n\t * @returns {ng.$compileProvider} the compile provider itself, for chaining of function calls.\n\t * @description\n\t * Register a **component definition** with the compiler. This is a shorthand for registering a special\n\t * type of directive, which represents a self-contained UI component in your application. Such components\n\t * are always isolated (i.e. `scope: {}`) and are always restricted to elements (i.e. `restrict: 'E'`).\n\t *\n\t * Component definitions are very simple and do not require as much configuration as defining general\n\t * directives. Component definitions usually consist only of a template and a controller backing it.\n\t *\n\t * In order to make the definition easier, components enforce best practices like use of `controllerAs`,\n\t * `bindToController`. They always have **isolate scope** and are restricted to elements.\n\t *\n\t * Here are a few examples of how you would usually define components:\n\t *\n\t * ```js\n\t * var myMod = angular.module(...);\n\t * myMod.component('myComp', {\n\t * template: '
My name is {{$ctrl.name}}
',\n\t * controller: function() {\n\t * this.name = 'shahar';\n\t * }\n\t * });\n\t *\n\t * myMod.component('myComp', {\n\t * template: '
My name is {{$ctrl.name}}
',\n\t * bindings: {name: '@'}\n\t * });\n\t *\n\t * myMod.component('myComp', {\n\t * templateUrl: 'views/my-comp.html',\n\t * controller: 'MyCtrl',\n\t * controllerAs: 'ctrl',\n\t * bindings: {name: '@'}\n\t * });\n\t *\n\t * ```\n\t * For more examples, and an in-depth guide, see the {@link guide/component component guide}.\n\t *\n\t *
\n\t * See also {@link ng.$compileProvider#directive $compileProvider.directive()}.\n\t */\n\t this.component = function registerComponent(name, options) {\n\t var controller = options.controller || function() {};\n\t\n\t function factory($injector) {\n\t function makeInjectable(fn) {\n\t if (isFunction(fn) || isArray(fn)) {\n\t return function(tElement, tAttrs) {\n\t return $injector.invoke(fn, this, {$element: tElement, $attrs: tAttrs});\n\t };\n\t } else {\n\t return fn;\n\t }\n\t }\n\t\n\t var template = (!options.template && !options.templateUrl ? '' : options.template);\n\t var ddo = {\n\t controller: controller,\n\t controllerAs: identifierForController(options.controller) || options.controllerAs || '$ctrl',\n\t template: makeInjectable(template),\n\t templateUrl: makeInjectable(options.templateUrl),\n\t transclude: options.transclude,\n\t scope: {},\n\t bindToController: options.bindings || {},\n\t restrict: 'E',\n\t require: options.require\n\t };\n\t\n\t // Copy annotations (starting with $) over to the DDO\n\t forEach(options, function(val, key) {\n\t if (key.charAt(0) === '$') ddo[key] = val;\n\t });\n\t\n\t return ddo;\n\t }\n\t\n\t // TODO(pete) remove the following `forEach` before we release 1.6.0\n\t // The component-router@0.2.0 looks for the annotations on the controller constructor\n\t // Nothing in Angular looks for annotations on the factory function but we can't remove\n\t // it from 1.5.x yet.\n\t\n\t // Copy any annotation properties (starting with $) over to the factory and controller constructor functions\n\t // These could be used by libraries such as the new component router\n\t forEach(options, function(val, key) {\n\t if (key.charAt(0) === '$') {\n\t factory[key] = val;\n\t // Don't try to copy over annotations to named controller\n\t if (isFunction(controller)) controller[key] = val;\n\t }\n\t });\n\t\n\t factory.$inject = ['$injector'];\n\t\n\t return this.directive(name, factory);\n\t };\n\t\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $compileProvider#aHrefSanitizationWhitelist\n\t * @kind function\n\t *\n\t * @description\n\t * Retrieves or overrides the default regular expression that is used for whitelisting of safe\n\t * urls during a[href] sanitization.\n\t *\n\t * The sanitization is a security measure aimed at preventing XSS attacks via html links.\n\t *\n\t * Any url about to be assigned to a[href] via data-binding is first normalized and turned into\n\t * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist`\n\t * regular expression. If a match is found, the original url is written into the dom. Otherwise,\n\t * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.\n\t *\n\t * @param {RegExp=} regexp New regexp to whitelist urls with.\n\t * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for\n\t * chaining otherwise.\n\t */\n\t this.aHrefSanitizationWhitelist = function(regexp) {\n\t if (isDefined(regexp)) {\n\t $$sanitizeUriProvider.aHrefSanitizationWhitelist(regexp);\n\t return this;\n\t } else {\n\t return $$sanitizeUriProvider.aHrefSanitizationWhitelist();\n\t }\n\t };\n\t\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $compileProvider#imgSrcSanitizationWhitelist\n\t * @kind function\n\t *\n\t * @description\n\t * Retrieves or overrides the default regular expression that is used for whitelisting of safe\n\t * urls during img[src] sanitization.\n\t *\n\t * The sanitization is a security measure aimed at prevent XSS attacks via html links.\n\t *\n\t * Any url about to be assigned to img[src] via data-binding is first normalized and turned into\n\t * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist`\n\t * regular expression. If a match is found, the original url is written into the dom. Otherwise,\n\t * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.\n\t *\n\t * @param {RegExp=} regexp New regexp to whitelist urls with.\n\t * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for\n\t * chaining otherwise.\n\t */\n\t this.imgSrcSanitizationWhitelist = function(regexp) {\n\t if (isDefined(regexp)) {\n\t $$sanitizeUriProvider.imgSrcSanitizationWhitelist(regexp);\n\t return this;\n\t } else {\n\t return $$sanitizeUriProvider.imgSrcSanitizationWhitelist();\n\t }\n\t };\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $compileProvider#debugInfoEnabled\n\t *\n\t * @param {boolean=} enabled update the debugInfoEnabled state if provided, otherwise just return the\n\t * current debugInfoEnabled state\n\t * @returns {*} current value if used as getter or itself (chaining) if used as setter\n\t *\n\t * @kind function\n\t *\n\t * @description\n\t * Call this method to enable/disable various debug runtime information in the compiler such as adding\n\t * binding information and a reference to the current scope on to DOM elements.\n\t * If enabled, the compiler will add the following to DOM elements that have been bound to the scope\n\t * * `ng-binding` CSS class\n\t * * `$binding` data property containing an array of the binding expressions\n\t *\n\t * You may want to disable this in production for a significant performance boost. See\n\t * {@link guide/production#disabling-debug-data Disabling Debug Data} for more.\n\t *\n\t * The default value is true.\n\t */\n\t var debugInfoEnabled = true;\n\t this.debugInfoEnabled = function(enabled) {\n\t if (isDefined(enabled)) {\n\t debugInfoEnabled = enabled;\n\t return this;\n\t }\n\t return debugInfoEnabled;\n\t };\n\t\n\t\n\t var TTL = 10;\n\t /**\n\t * @ngdoc method\n\t * @name $compileProvider#onChangesTtl\n\t * @description\n\t *\n\t * Sets the number of times `$onChanges` hooks can trigger new changes before giving up and\n\t * assuming that the model is unstable.\n\t *\n\t * The current default is 10 iterations.\n\t *\n\t * In complex applications it's possible that dependencies between `$onChanges` hooks and bindings will result\n\t * in several iterations of calls to these hooks. However if an application needs more than the default 10\n\t * iterations to stabilize then you should investigate what is causing the model to continuously change during\n\t * the `$onChanges` hook execution.\n\t *\n\t * Increasing the TTL could have performance implications, so you should not change it without proper justification.\n\t *\n\t * @param {number} limit The number of `$onChanges` hook iterations.\n\t * @returns {number|object} the current limit (or `this` if called as a setter for chaining)\n\t */\n\t this.onChangesTtl = function(value) {\n\t if (arguments.length) {\n\t TTL = value;\n\t return this;\n\t }\n\t return TTL;\n\t };\n\t\n\t this.$get = [\n\t '$injector', '$interpolate', '$exceptionHandler', '$templateRequest', '$parse',\n\t '$controller', '$rootScope', '$sce', '$animate', '$$sanitizeUri',\n\t function($injector, $interpolate, $exceptionHandler, $templateRequest, $parse,\n\t $controller, $rootScope, $sce, $animate, $$sanitizeUri) {\n\t\n\t var SIMPLE_ATTR_NAME = /^\\w/;\n\t var specialAttrHolder = window.document.createElement('div');\n\t\n\t\n\t\n\t var onChangesTtl = TTL;\n\t // The onChanges hooks should all be run together in a single digest\n\t // When changes occur, the call to trigger their hooks will be added to this queue\n\t var onChangesQueue;\n\t\n\t // This function is called in a $$postDigest to trigger all the onChanges hooks in a single digest\n\t function flushOnChangesQueue() {\n\t try {\n\t if (!(--onChangesTtl)) {\n\t // We have hit the TTL limit so reset everything\n\t onChangesQueue = undefined;\n\t throw $compileMinErr('infchng', '{0} $onChanges() iterations reached. Aborting!\\n', TTL);\n\t }\n\t // We must run this hook in an apply since the $$postDigest runs outside apply\n\t $rootScope.$apply(function() {\n\t var errors = [];\n\t for (var i = 0, ii = onChangesQueue.length; i < ii; ++i) {\n\t try {\n\t onChangesQueue[i]();\n\t } catch (e) {\n\t errors.push(e);\n\t }\n\t }\n\t // Reset the queue to trigger a new schedule next time there is a change\n\t onChangesQueue = undefined;\n\t if (errors.length) {\n\t throw errors;\n\t }\n\t });\n\t } finally {\n\t onChangesTtl++;\n\t }\n\t }\n\t\n\t\n\t function Attributes(element, attributesToCopy) {\n\t if (attributesToCopy) {\n\t var keys = Object.keys(attributesToCopy);\n\t var i, l, key;\n\t\n\t for (i = 0, l = keys.length; i < l; i++) {\n\t key = keys[i];\n\t this[key] = attributesToCopy[key];\n\t }\n\t } else {\n\t this.$attr = {};\n\t }\n\t\n\t this.$$element = element;\n\t }\n\t\n\t Attributes.prototype = {\n\t /**\n\t * @ngdoc method\n\t * @name $compile.directive.Attributes#$normalize\n\t * @kind function\n\t *\n\t * @description\n\t * Converts an attribute name (e.g. dash/colon/underscore-delimited string, optionally prefixed with `x-` or\n\t * `data-`) to its normalized, camelCase form.\n\t *\n\t * Also there is special case for Moz prefix starting with upper case letter.\n\t *\n\t * For further information check out the guide on {@link guide/directive#matching-directives Matching Directives}\n\t *\n\t * @param {string} name Name to normalize\n\t */\n\t $normalize: directiveNormalize,\n\t\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $compile.directive.Attributes#$addClass\n\t * @kind function\n\t *\n\t * @description\n\t * Adds the CSS class value specified by the classVal parameter to the element. If animations\n\t * are enabled then an animation will be triggered for the class addition.\n\t *\n\t * @param {string} classVal The className value that will be added to the element\n\t */\n\t $addClass: function(classVal) {\n\t if (classVal && classVal.length > 0) {\n\t $animate.addClass(this.$$element, classVal);\n\t }\n\t },\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $compile.directive.Attributes#$removeClass\n\t * @kind function\n\t *\n\t * @description\n\t * Removes the CSS class value specified by the classVal parameter from the element. If\n\t * animations are enabled then an animation will be triggered for the class removal.\n\t *\n\t * @param {string} classVal The className value that will be removed from the element\n\t */\n\t $removeClass: function(classVal) {\n\t if (classVal && classVal.length > 0) {\n\t $animate.removeClass(this.$$element, classVal);\n\t }\n\t },\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $compile.directive.Attributes#$updateClass\n\t * @kind function\n\t *\n\t * @description\n\t * Adds and removes the appropriate CSS class values to the element based on the difference\n\t * between the new and old CSS class values (specified as newClasses and oldClasses).\n\t *\n\t * @param {string} newClasses The current CSS className value\n\t * @param {string} oldClasses The former CSS className value\n\t */\n\t $updateClass: function(newClasses, oldClasses) {\n\t var toAdd = tokenDifference(newClasses, oldClasses);\n\t if (toAdd && toAdd.length) {\n\t $animate.addClass(this.$$element, toAdd);\n\t }\n\t\n\t var toRemove = tokenDifference(oldClasses, newClasses);\n\t if (toRemove && toRemove.length) {\n\t $animate.removeClass(this.$$element, toRemove);\n\t }\n\t },\n\t\n\t /**\n\t * Set a normalized attribute on the element in a way such that all directives\n\t * can share the attribute. This function properly handles boolean attributes.\n\t * @param {string} key Normalized key. (ie ngAttribute)\n\t * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n\t * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n\t * Defaults to true.\n\t * @param {string=} attrName Optional none normalized name. Defaults to key.\n\t */\n\t $set: function(key, value, writeAttr, attrName) {\n\t // TODO: decide whether or not to throw an error if \"class\"\n\t //is set through this function since it may cause $updateClass to\n\t //become unstable.\n\t\n\t var node = this.$$element[0],\n\t booleanKey = getBooleanAttrName(node, key),\n\t aliasedKey = getAliasedAttrName(key),\n\t observer = key,\n\t nodeName;\n\t\n\t if (booleanKey) {\n\t this.$$element.prop(key, value);\n\t attrName = booleanKey;\n\t } else if (aliasedKey) {\n\t this[aliasedKey] = value;\n\t observer = aliasedKey;\n\t }\n\t\n\t this[key] = value;\n\t\n\t // translate normalized key to actual key\n\t if (attrName) {\n\t this.$attr[key] = attrName;\n\t } else {\n\t attrName = this.$attr[key];\n\t if (!attrName) {\n\t this.$attr[key] = attrName = snake_case(key, '-');\n\t }\n\t }\n\t\n\t nodeName = nodeName_(this.$$element);\n\t\n\t if ((nodeName === 'a' && (key === 'href' || key === 'xlinkHref')) ||\n\t (nodeName === 'img' && key === 'src')) {\n\t // sanitize a[href] and img[src] values\n\t this[key] = value = $$sanitizeUri(value, key === 'src');\n\t } else if (nodeName === 'img' && key === 'srcset' && isDefined(value)) {\n\t // sanitize img[srcset] values\n\t var result = \"\";\n\t\n\t // first check if there are spaces because it's not the same pattern\n\t var trimmedSrcset = trim(value);\n\t // ( 999x ,| 999w ,| ,|, )\n\t var srcPattern = /(\\s+\\d+x\\s*,|\\s+\\d+w\\s*,|\\s+,|,\\s+)/;\n\t var pattern = /\\s/.test(trimmedSrcset) ? srcPattern : /(,)/;\n\t\n\t // split srcset into tuple of uri and descriptor except for the last item\n\t var rawUris = trimmedSrcset.split(pattern);\n\t\n\t // for each tuples\n\t var nbrUrisWith2parts = Math.floor(rawUris.length / 2);\n\t for (var i = 0; i < nbrUrisWith2parts; i++) {\n\t var innerIdx = i * 2;\n\t // sanitize the uri\n\t result += $$sanitizeUri(trim(rawUris[innerIdx]), true);\n\t // add the descriptor\n\t result += (\" \" + trim(rawUris[innerIdx + 1]));\n\t }\n\t\n\t // split the last item into uri and descriptor\n\t var lastTuple = trim(rawUris[i * 2]).split(/\\s/);\n\t\n\t // sanitize the last uri\n\t result += $$sanitizeUri(trim(lastTuple[0]), true);\n\t\n\t // and add the last descriptor if any\n\t if (lastTuple.length === 2) {\n\t result += (\" \" + trim(lastTuple[1]));\n\t }\n\t this[key] = value = result;\n\t }\n\t\n\t if (writeAttr !== false) {\n\t if (value === null || isUndefined(value)) {\n\t this.$$element.removeAttr(attrName);\n\t } else {\n\t if (SIMPLE_ATTR_NAME.test(attrName)) {\n\t this.$$element.attr(attrName, value);\n\t } else {\n\t setSpecialAttr(this.$$element[0], attrName, value);\n\t }\n\t }\n\t }\n\t\n\t // fire observers\n\t var $$observers = this.$$observers;\n\t $$observers && forEach($$observers[observer], function(fn) {\n\t try {\n\t fn(value);\n\t } catch (e) {\n\t $exceptionHandler(e);\n\t }\n\t });\n\t },\n\t\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $compile.directive.Attributes#$observe\n\t * @kind function\n\t *\n\t * @description\n\t * Observes an interpolated attribute.\n\t *\n\t * The observer function will be invoked once during the next `$digest` following\n\t * compilation. The observer is then invoked whenever the interpolated value\n\t * changes.\n\t *\n\t * @param {string} key Normalized key. (ie ngAttribute) .\n\t * @param {function(interpolatedValue)} fn Function that will be called whenever\n\t the interpolated value of the attribute changes.\n\t * See the {@link guide/interpolation#how-text-and-attribute-bindings-work Interpolation\n\t * guide} for more info.\n\t * @returns {function()} Returns a deregistration function for this observer.\n\t */\n\t $observe: function(key, fn) {\n\t var attrs = this,\n\t $$observers = (attrs.$$observers || (attrs.$$observers = createMap())),\n\t listeners = ($$observers[key] || ($$observers[key] = []));\n\t\n\t listeners.push(fn);\n\t $rootScope.$evalAsync(function() {\n\t if (!listeners.$$inter && attrs.hasOwnProperty(key) && !isUndefined(attrs[key])) {\n\t // no one registered attribute interpolation function, so lets call it manually\n\t fn(attrs[key]);\n\t }\n\t });\n\t\n\t return function() {\n\t arrayRemove(listeners, fn);\n\t };\n\t }\n\t };\n\t\n\t function setSpecialAttr(element, attrName, value) {\n\t // Attributes names that do not start with letters (such as `(click)`) cannot be set using `setAttribute`\n\t // so we have to jump through some hoops to get such an attribute\n\t // https://github.com/angular/angular.js/pull/13318\n\t specialAttrHolder.innerHTML = \"\";\n\t var attributes = specialAttrHolder.firstChild.attributes;\n\t var attribute = attributes[0];\n\t // We have to remove the attribute from its container element before we can add it to the destination element\n\t attributes.removeNamedItem(attribute.name);\n\t attribute.value = value;\n\t element.attributes.setNamedItem(attribute);\n\t }\n\t\n\t function safeAddClass($element, className) {\n\t try {\n\t $element.addClass(className);\n\t } catch (e) {\n\t // ignore, since it means that we are trying to set class on\n\t // SVG element, where class name is read-only.\n\t }\n\t }\n\t\n\t\n\t var startSymbol = $interpolate.startSymbol(),\n\t endSymbol = $interpolate.endSymbol(),\n\t denormalizeTemplate = (startSymbol == '{{' && endSymbol == '}}')\n\t ? identity\n\t : function denormalizeTemplate(template) {\n\t return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n\t },\n\t NG_ATTR_BINDING = /^ngAttr[A-Z]/;\n\t var MULTI_ELEMENT_DIR_RE = /^(.+)Start$/;\n\t\n\t compile.$$addBindingInfo = debugInfoEnabled ? function $$addBindingInfo($element, binding) {\n\t var bindings = $element.data('$binding') || [];\n\t\n\t if (isArray(binding)) {\n\t bindings = bindings.concat(binding);\n\t } else {\n\t bindings.push(binding);\n\t }\n\t\n\t $element.data('$binding', bindings);\n\t } : noop;\n\t\n\t compile.$$addBindingClass = debugInfoEnabled ? function $$addBindingClass($element) {\n\t safeAddClass($element, 'ng-binding');\n\t } : noop;\n\t\n\t compile.$$addScopeInfo = debugInfoEnabled ? function $$addScopeInfo($element, scope, isolated, noTemplate) {\n\t var dataName = isolated ? (noTemplate ? '$isolateScopeNoTemplate' : '$isolateScope') : '$scope';\n\t $element.data(dataName, scope);\n\t } : noop;\n\t\n\t compile.$$addScopeClass = debugInfoEnabled ? function $$addScopeClass($element, isolated) {\n\t safeAddClass($element, isolated ? 'ng-isolate-scope' : 'ng-scope');\n\t } : noop;\n\t\n\t compile.$$createComment = function(directiveName, comment) {\n\t var content = '';\n\t if (debugInfoEnabled) {\n\t content = ' ' + (directiveName || '') + ': ';\n\t if (comment) content += comment + ' ';\n\t }\n\t return window.document.createComment(content);\n\t };\n\t\n\t return compile;\n\t\n\t //================================\n\t\n\t function compile($compileNodes, transcludeFn, maxPriority, ignoreDirective,\n\t previousCompileContext) {\n\t if (!($compileNodes instanceof jqLite)) {\n\t // jquery always rewraps, whereas we need to preserve the original selector so that we can\n\t // modify it.\n\t $compileNodes = jqLite($compileNodes);\n\t }\n\t\n\t var NOT_EMPTY = /\\S+/;\n\t\n\t // We can not compile top level text elements since text nodes can be merged and we will\n\t // not be able to attach scope data to them, so we will wrap them in \n\t for (var i = 0, len = $compileNodes.length; i < len; i++) {\n\t var domNode = $compileNodes[i];\n\t\n\t if (domNode.nodeType === NODE_TYPE_TEXT && domNode.nodeValue.match(NOT_EMPTY) /* non-empty */) {\n\t jqLiteWrapNode(domNode, $compileNodes[i] = window.document.createElement('span'));\n\t }\n\t }\n\t\n\t var compositeLinkFn =\n\t compileNodes($compileNodes, transcludeFn, $compileNodes,\n\t maxPriority, ignoreDirective, previousCompileContext);\n\t compile.$$addScopeClass($compileNodes);\n\t var namespace = null;\n\t return function publicLinkFn(scope, cloneConnectFn, options) {\n\t assertArg(scope, 'scope');\n\t\n\t if (previousCompileContext && previousCompileContext.needsNewScope) {\n\t // A parent directive did a replace and a directive on this element asked\n\t // for transclusion, which caused us to lose a layer of element on which\n\t // we could hold the new transclusion scope, so we will create it manually\n\t // here.\n\t scope = scope.$parent.$new();\n\t }\n\t\n\t options = options || {};\n\t var parentBoundTranscludeFn = options.parentBoundTranscludeFn,\n\t transcludeControllers = options.transcludeControllers,\n\t futureParentElement = options.futureParentElement;\n\t\n\t // When `parentBoundTranscludeFn` is passed, it is a\n\t // `controllersBoundTransclude` function (it was previously passed\n\t // as `transclude` to directive.link) so we must unwrap it to get\n\t // its `boundTranscludeFn`\n\t if (parentBoundTranscludeFn && parentBoundTranscludeFn.$$boundTransclude) {\n\t parentBoundTranscludeFn = parentBoundTranscludeFn.$$boundTransclude;\n\t }\n\t\n\t if (!namespace) {\n\t namespace = detectNamespaceForChildElements(futureParentElement);\n\t }\n\t var $linkNode;\n\t if (namespace !== 'html') {\n\t // When using a directive with replace:true and templateUrl the $compileNodes\n\t // (or a child element inside of them)\n\t // might change, so we need to recreate the namespace adapted compileNodes\n\t // for call to the link function.\n\t // Note: This will already clone the nodes...\n\t $linkNode = jqLite(\n\t wrapTemplate(namespace, jqLite('
').append($compileNodes).html())\n\t );\n\t } else if (cloneConnectFn) {\n\t // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n\t // and sometimes changes the structure of the DOM.\n\t $linkNode = JQLitePrototype.clone.call($compileNodes);\n\t } else {\n\t $linkNode = $compileNodes;\n\t }\n\t\n\t if (transcludeControllers) {\n\t for (var controllerName in transcludeControllers) {\n\t $linkNode.data('$' + controllerName + 'Controller', transcludeControllers[controllerName].instance);\n\t }\n\t }\n\t\n\t compile.$$addScopeInfo($linkNode, scope);\n\t\n\t if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n\t if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode, parentBoundTranscludeFn);\n\t return $linkNode;\n\t };\n\t }\n\t\n\t function detectNamespaceForChildElements(parentElement) {\n\t // TODO: Make this detect MathML as well...\n\t var node = parentElement && parentElement[0];\n\t if (!node) {\n\t return 'html';\n\t } else {\n\t return nodeName_(node) !== 'foreignobject' && toString.call(node).match(/SVG/) ? 'svg' : 'html';\n\t }\n\t }\n\t\n\t /**\n\t * Compile function matches each node in nodeList against the directives. Once all directives\n\t * for a particular node are collected their compile functions are executed. The compile\n\t * functions return values - the linking functions - are combined into a composite linking\n\t * function, which is the a linking function for the node.\n\t *\n\t * @param {NodeList} nodeList an array of nodes or NodeList to compile\n\t * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the\n\t * scope argument is auto-generated to the new child of the transcluded parent scope.\n\t * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then\n\t * the rootElement must be set the jqLite collection of the compile root. This is\n\t * needed so that the jqLite collection items can be replaced with widgets.\n\t * @param {number=} maxPriority Max directive priority.\n\t * @returns {Function} A composite linking function of all of the matched directives or null.\n\t */\n\t function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority, ignoreDirective,\n\t previousCompileContext) {\n\t var linkFns = [],\n\t attrs, directives, nodeLinkFn, childNodes, childLinkFn, linkFnFound, nodeLinkFnFound;\n\t\n\t for (var i = 0; i < nodeList.length; i++) {\n\t attrs = new Attributes();\n\t\n\t // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n\t directives = collectDirectives(nodeList[i], [], attrs, i === 0 ? maxPriority : undefined,\n\t ignoreDirective);\n\t\n\t nodeLinkFn = (directives.length)\n\t ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement,\n\t null, [], [], previousCompileContext)\n\t : null;\n\t\n\t if (nodeLinkFn && nodeLinkFn.scope) {\n\t compile.$$addScopeClass(attrs.$$element);\n\t }\n\t\n\t childLinkFn = (nodeLinkFn && nodeLinkFn.terminal ||\n\t !(childNodes = nodeList[i].childNodes) ||\n\t !childNodes.length)\n\t ? null\n\t : compileNodes(childNodes,\n\t nodeLinkFn ? (\n\t (nodeLinkFn.transcludeOnThisElement || !nodeLinkFn.templateOnThisElement)\n\t && nodeLinkFn.transclude) : transcludeFn);\n\t\n\t if (nodeLinkFn || childLinkFn) {\n\t linkFns.push(i, nodeLinkFn, childLinkFn);\n\t linkFnFound = true;\n\t nodeLinkFnFound = nodeLinkFnFound || nodeLinkFn;\n\t }\n\t\n\t //use the previous context only for the first element in the virtual group\n\t previousCompileContext = null;\n\t }\n\t\n\t // return a linking function if we have found anything, null otherwise\n\t return linkFnFound ? compositeLinkFn : null;\n\t\n\t function compositeLinkFn(scope, nodeList, $rootElement, parentBoundTranscludeFn) {\n\t var nodeLinkFn, childLinkFn, node, childScope, i, ii, idx, childBoundTranscludeFn;\n\t var stableNodeList;\n\t\n\t\n\t if (nodeLinkFnFound) {\n\t // copy nodeList so that if a nodeLinkFn removes or adds an element at this DOM level our\n\t // offsets don't get screwed up\n\t var nodeListLength = nodeList.length;\n\t stableNodeList = new Array(nodeListLength);\n\t\n\t // create a sparse array by only copying the elements which have a linkFn\n\t for (i = 0; i < linkFns.length; i+=3) {\n\t idx = linkFns[i];\n\t stableNodeList[idx] = nodeList[idx];\n\t }\n\t } else {\n\t stableNodeList = nodeList;\n\t }\n\t\n\t for (i = 0, ii = linkFns.length; i < ii;) {\n\t node = stableNodeList[linkFns[i++]];\n\t nodeLinkFn = linkFns[i++];\n\t childLinkFn = linkFns[i++];\n\t\n\t if (nodeLinkFn) {\n\t if (nodeLinkFn.scope) {\n\t childScope = scope.$new();\n\t compile.$$addScopeInfo(jqLite(node), childScope);\n\t } else {\n\t childScope = scope;\n\t }\n\t\n\t if (nodeLinkFn.transcludeOnThisElement) {\n\t childBoundTranscludeFn = createBoundTranscludeFn(\n\t scope, nodeLinkFn.transclude, parentBoundTranscludeFn);\n\t\n\t } else if (!nodeLinkFn.templateOnThisElement && parentBoundTranscludeFn) {\n\t childBoundTranscludeFn = parentBoundTranscludeFn;\n\t\n\t } else if (!parentBoundTranscludeFn && transcludeFn) {\n\t childBoundTranscludeFn = createBoundTranscludeFn(scope, transcludeFn);\n\t\n\t } else {\n\t childBoundTranscludeFn = null;\n\t }\n\t\n\t nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn);\n\t\n\t } else if (childLinkFn) {\n\t childLinkFn(scope, node.childNodes, undefined, parentBoundTranscludeFn);\n\t }\n\t }\n\t }\n\t }\n\t\n\t function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn) {\n\t function boundTranscludeFn(transcludedScope, cloneFn, controllers, futureParentElement, containingScope) {\n\t\n\t if (!transcludedScope) {\n\t transcludedScope = scope.$new(false, containingScope);\n\t transcludedScope.$$transcluded = true;\n\t }\n\t\n\t return transcludeFn(transcludedScope, cloneFn, {\n\t parentBoundTranscludeFn: previousBoundTranscludeFn,\n\t transcludeControllers: controllers,\n\t futureParentElement: futureParentElement\n\t });\n\t }\n\t\n\t // We need to attach the transclusion slots onto the `boundTranscludeFn`\n\t // so that they are available inside the `controllersBoundTransclude` function\n\t var boundSlots = boundTranscludeFn.$$slots = createMap();\n\t for (var slotName in transcludeFn.$$slots) {\n\t if (transcludeFn.$$slots[slotName]) {\n\t boundSlots[slotName] = createBoundTranscludeFn(scope, transcludeFn.$$slots[slotName], previousBoundTranscludeFn);\n\t } else {\n\t boundSlots[slotName] = null;\n\t }\n\t }\n\t\n\t return boundTranscludeFn;\n\t }\n\t\n\t /**\n\t * Looks for directives on the given node and adds them to the directive collection which is\n\t * sorted.\n\t *\n\t * @param node Node to search.\n\t * @param directives An array to which the directives are added to. This array is sorted before\n\t * the function returns.\n\t * @param attrs The shared attrs object which is used to populate the normalized attributes.\n\t * @param {number=} maxPriority Max directive priority.\n\t */\n\t function collectDirectives(node, directives, attrs, maxPriority, ignoreDirective) {\n\t var nodeType = node.nodeType,\n\t attrsMap = attrs.$attr,\n\t match,\n\t className;\n\t\n\t switch (nodeType) {\n\t case NODE_TYPE_ELEMENT: /* Element */\n\t // use the node name: \n\t addDirective(directives,\n\t directiveNormalize(nodeName_(node)), 'E', maxPriority, ignoreDirective);\n\t\n\t // iterate over the attributes\n\t for (var attr, name, nName, ngAttrName, value, isNgAttr, nAttrs = node.attributes,\n\t j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n\t var attrStartName = false;\n\t var attrEndName = false;\n\t\n\t attr = nAttrs[j];\n\t name = attr.name;\n\t value = trim(attr.value);\n\t\n\t // support ngAttr attribute binding\n\t ngAttrName = directiveNormalize(name);\n\t if (isNgAttr = NG_ATTR_BINDING.test(ngAttrName)) {\n\t name = name.replace(PREFIX_REGEXP, '')\n\t .substr(8).replace(/_(.)/g, function(match, letter) {\n\t return letter.toUpperCase();\n\t });\n\t }\n\t\n\t var multiElementMatch = ngAttrName.match(MULTI_ELEMENT_DIR_RE);\n\t if (multiElementMatch && directiveIsMultiElement(multiElementMatch[1])) {\n\t attrStartName = name;\n\t attrEndName = name.substr(0, name.length - 5) + 'end';\n\t name = name.substr(0, name.length - 6);\n\t }\n\t\n\t nName = directiveNormalize(name.toLowerCase());\n\t attrsMap[nName] = name;\n\t if (isNgAttr || !attrs.hasOwnProperty(nName)) {\n\t attrs[nName] = value;\n\t if (getBooleanAttrName(node, nName)) {\n\t attrs[nName] = true; // presence means true\n\t }\n\t }\n\t addAttrInterpolateDirective(node, directives, value, nName, isNgAttr);\n\t addDirective(directives, nName, 'A', maxPriority, ignoreDirective, attrStartName,\n\t attrEndName);\n\t }\n\t\n\t // use class as directive\n\t className = node.className;\n\t if (isObject(className)) {\n\t // Maybe SVGAnimatedString\n\t className = className.animVal;\n\t }\n\t if (isString(className) && className !== '') {\n\t while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n\t nName = directiveNormalize(match[2]);\n\t if (addDirective(directives, nName, 'C', maxPriority, ignoreDirective)) {\n\t attrs[nName] = trim(match[3]);\n\t }\n\t className = className.substr(match.index + match[0].length);\n\t }\n\t }\n\t break;\n\t case NODE_TYPE_TEXT: /* Text Node */\n\t if (msie === 11) {\n\t // Workaround for #11781\n\t while (node.parentNode && node.nextSibling && node.nextSibling.nodeType === NODE_TYPE_TEXT) {\n\t node.nodeValue = node.nodeValue + node.nextSibling.nodeValue;\n\t node.parentNode.removeChild(node.nextSibling);\n\t }\n\t }\n\t addTextInterpolateDirective(directives, node.nodeValue);\n\t break;\n\t case NODE_TYPE_COMMENT: /* Comment */\n\t collectCommentDirectives(node, directives, attrs, maxPriority, ignoreDirective);\n\t break;\n\t }\n\t\n\t directives.sort(byPriority);\n\t return directives;\n\t }\n\t\n\t function collectCommentDirectives(node, directives, attrs, maxPriority, ignoreDirective) {\n\t // function created because of performance, try/catch disables\n\t // the optimization of the whole function #14848\n\t try {\n\t var match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n\t if (match) {\n\t var nName = directiveNormalize(match[1]);\n\t if (addDirective(directives, nName, 'M', maxPriority, ignoreDirective)) {\n\t attrs[nName] = trim(match[2]);\n\t }\n\t }\n\t } catch (e) {\n\t // turns out that under some circumstances IE9 throws errors when one attempts to read\n\t // comment's node value.\n\t // Just ignore it and continue. (Can't seem to reproduce in test case.)\n\t }\n\t }\n\t\n\t /**\n\t * Given a node with an directive-start it collects all of the siblings until it finds\n\t * directive-end.\n\t * @param node\n\t * @param attrStart\n\t * @param attrEnd\n\t * @returns {*}\n\t */\n\t function groupScan(node, attrStart, attrEnd) {\n\t var nodes = [];\n\t var depth = 0;\n\t if (attrStart && node.hasAttribute && node.hasAttribute(attrStart)) {\n\t do {\n\t if (!node) {\n\t throw $compileMinErr('uterdir',\n\t \"Unterminated attribute, found '{0}' but no matching '{1}' found.\",\n\t attrStart, attrEnd);\n\t }\n\t if (node.nodeType == NODE_TYPE_ELEMENT) {\n\t if (node.hasAttribute(attrStart)) depth++;\n\t if (node.hasAttribute(attrEnd)) depth--;\n\t }\n\t nodes.push(node);\n\t node = node.nextSibling;\n\t } while (depth > 0);\n\t } else {\n\t nodes.push(node);\n\t }\n\t\n\t return jqLite(nodes);\n\t }\n\t\n\t /**\n\t * Wrapper for linking function which converts normal linking function into a grouped\n\t * linking function.\n\t * @param linkFn\n\t * @param attrStart\n\t * @param attrEnd\n\t * @returns {Function}\n\t */\n\t function groupElementsLinkFnWrapper(linkFn, attrStart, attrEnd) {\n\t return function groupedElementsLink(scope, element, attrs, controllers, transcludeFn) {\n\t element = groupScan(element[0], attrStart, attrEnd);\n\t return linkFn(scope, element, attrs, controllers, transcludeFn);\n\t };\n\t }\n\t\n\t /**\n\t * A function generator that is used to support both eager and lazy compilation\n\t * linking function.\n\t * @param eager\n\t * @param $compileNodes\n\t * @param transcludeFn\n\t * @param maxPriority\n\t * @param ignoreDirective\n\t * @param previousCompileContext\n\t * @returns {Function}\n\t */\n\t function compilationGenerator(eager, $compileNodes, transcludeFn, maxPriority, ignoreDirective, previousCompileContext) {\n\t var compiled;\n\t\n\t if (eager) {\n\t return compile($compileNodes, transcludeFn, maxPriority, ignoreDirective, previousCompileContext);\n\t }\n\t return function lazyCompilation() {\n\t if (!compiled) {\n\t compiled = compile($compileNodes, transcludeFn, maxPriority, ignoreDirective, previousCompileContext);\n\t\n\t // Null out all of these references in order to make them eligible for garbage collection\n\t // since this is a potentially long lived closure\n\t $compileNodes = transcludeFn = previousCompileContext = null;\n\t }\n\t return compiled.apply(this, arguments);\n\t };\n\t }\n\t\n\t /**\n\t * Once the directives have been collected, their compile functions are executed. This method\n\t * is responsible for inlining directive templates as well as terminating the application\n\t * of the directives if the terminal directive has been reached.\n\t *\n\t * @param {Array} directives Array of collected directives to execute their compile function.\n\t * this needs to be pre-sorted by priority order.\n\t * @param {Node} compileNode The raw DOM node to apply the compile functions to\n\t * @param {Object} templateAttrs The shared attribute function\n\t * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the\n\t * scope argument is auto-generated to the new\n\t * child of the transcluded parent scope.\n\t * @param {JQLite} jqCollection If we are working on the root of the compile tree then this\n\t * argument has the root jqLite array so that we can replace nodes\n\t * on it.\n\t * @param {Object=} originalReplaceDirective An optional directive that will be ignored when\n\t * compiling the transclusion.\n\t * @param {Array.} preLinkFns\n\t * @param {Array.} postLinkFns\n\t * @param {Object} previousCompileContext Context used for previous compilation of the current\n\t * node\n\t * @returns {Function} linkFn\n\t */\n\t function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn,\n\t jqCollection, originalReplaceDirective, preLinkFns, postLinkFns,\n\t previousCompileContext) {\n\t previousCompileContext = previousCompileContext || {};\n\t\n\t var terminalPriority = -Number.MAX_VALUE,\n\t newScopeDirective = previousCompileContext.newScopeDirective,\n\t controllerDirectives = previousCompileContext.controllerDirectives,\n\t newIsolateScopeDirective = previousCompileContext.newIsolateScopeDirective,\n\t templateDirective = previousCompileContext.templateDirective,\n\t nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective,\n\t hasTranscludeDirective = false,\n\t hasTemplate = false,\n\t hasElementTranscludeDirective = previousCompileContext.hasElementTranscludeDirective,\n\t $compileNode = templateAttrs.$$element = jqLite(compileNode),\n\t directive,\n\t directiveName,\n\t $template,\n\t replaceDirective = originalReplaceDirective,\n\t childTranscludeFn = transcludeFn,\n\t linkFn,\n\t didScanForMultipleTransclusion = false,\n\t mightHaveMultipleTransclusionError = false,\n\t directiveValue;\n\t\n\t // executes all directives on the current element\n\t for (var i = 0, ii = directives.length; i < ii; i++) {\n\t directive = directives[i];\n\t var attrStart = directive.$$start;\n\t var attrEnd = directive.$$end;\n\t\n\t // collect multiblock sections\n\t if (attrStart) {\n\t $compileNode = groupScan(compileNode, attrStart, attrEnd);\n\t }\n\t $template = undefined;\n\t\n\t if (terminalPriority > directive.priority) {\n\t break; // prevent further processing of directives\n\t }\n\t\n\t if (directiveValue = directive.scope) {\n\t\n\t // skip the check for directives with async templates, we'll check the derived sync\n\t // directive when the template arrives\n\t if (!directive.templateUrl) {\n\t if (isObject(directiveValue)) {\n\t // This directive is trying to add an isolated scope.\n\t // Check that there is no scope of any kind already\n\t assertNoDuplicate('new/isolated scope', newIsolateScopeDirective || newScopeDirective,\n\t directive, $compileNode);\n\t newIsolateScopeDirective = directive;\n\t } else {\n\t // This directive is trying to add a child scope.\n\t // Check that there is no isolated scope already\n\t assertNoDuplicate('new/isolated scope', newIsolateScopeDirective, directive,\n\t $compileNode);\n\t }\n\t }\n\t\n\t newScopeDirective = newScopeDirective || directive;\n\t }\n\t\n\t directiveName = directive.name;\n\t\n\t // If we encounter a condition that can result in transclusion on the directive,\n\t // then scan ahead in the remaining directives for others that may cause a multiple\n\t // transclusion error to be thrown during the compilation process. If a matching directive\n\t // is found, then we know that when we encounter a transcluded directive, we need to eagerly\n\t // compile the `transclude` function rather than doing it lazily in order to throw\n\t // exceptions at the correct time\n\t if (!didScanForMultipleTransclusion && ((directive.replace && (directive.templateUrl || directive.template))\n\t || (directive.transclude && !directive.$$tlb))) {\n\t var candidateDirective;\n\t\n\t for (var scanningIndex = i + 1; candidateDirective = directives[scanningIndex++];) {\n\t if ((candidateDirective.transclude && !candidateDirective.$$tlb)\n\t || (candidateDirective.replace && (candidateDirective.templateUrl || candidateDirective.template))) {\n\t mightHaveMultipleTransclusionError = true;\n\t break;\n\t }\n\t }\n\t\n\t didScanForMultipleTransclusion = true;\n\t }\n\t\n\t if (!directive.templateUrl && directive.controller) {\n\t directiveValue = directive.controller;\n\t controllerDirectives = controllerDirectives || createMap();\n\t assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n\t controllerDirectives[directiveName], directive, $compileNode);\n\t controllerDirectives[directiveName] = directive;\n\t }\n\t\n\t if (directiveValue = directive.transclude) {\n\t hasTranscludeDirective = true;\n\t\n\t // Special case ngIf and ngRepeat so that we don't complain about duplicate transclusion.\n\t // This option should only be used by directives that know how to safely handle element transclusion,\n\t // where the transcluded nodes are added or replaced after linking.\n\t if (!directive.$$tlb) {\n\t assertNoDuplicate('transclusion', nonTlbTranscludeDirective, directive, $compileNode);\n\t nonTlbTranscludeDirective = directive;\n\t }\n\t\n\t if (directiveValue == 'element') {\n\t hasElementTranscludeDirective = true;\n\t terminalPriority = directive.priority;\n\t $template = $compileNode;\n\t $compileNode = templateAttrs.$$element =\n\t jqLite(compile.$$createComment(directiveName, templateAttrs[directiveName]));\n\t compileNode = $compileNode[0];\n\t replaceWith(jqCollection, sliceArgs($template), compileNode);\n\t\n\t // Support: Chrome < 50\n\t // https://github.com/angular/angular.js/issues/14041\n\t\n\t // In the versions of V8 prior to Chrome 50, the document fragment that is created\n\t // in the `replaceWith` function is improperly garbage collected despite still\n\t // being referenced by the `parentNode` property of all of the child nodes. By adding\n\t // a reference to the fragment via a different property, we can avoid that incorrect\n\t // behavior.\n\t // TODO: remove this line after Chrome 50 has been released\n\t $template[0].$$parentNode = $template[0].parentNode;\n\t\n\t childTranscludeFn = compilationGenerator(mightHaveMultipleTransclusionError, $template, transcludeFn, terminalPriority,\n\t replaceDirective && replaceDirective.name, {\n\t // Don't pass in:\n\t // - controllerDirectives - otherwise we'll create duplicates controllers\n\t // - newIsolateScopeDirective or templateDirective - combining templates with\n\t // element transclusion doesn't make sense.\n\t //\n\t // We need only nonTlbTranscludeDirective so that we prevent putting transclusion\n\t // on the same element more than once.\n\t nonTlbTranscludeDirective: nonTlbTranscludeDirective\n\t });\n\t } else {\n\t\n\t var slots = createMap();\n\t\n\t $template = jqLite(jqLiteClone(compileNode)).contents();\n\t\n\t if (isObject(directiveValue)) {\n\t\n\t // We have transclusion slots,\n\t // collect them up, compile them and store their transclusion functions\n\t $template = [];\n\t\n\t var slotMap = createMap();\n\t var filledSlots = createMap();\n\t\n\t // Parse the element selectors\n\t forEach(directiveValue, function(elementSelector, slotName) {\n\t // If an element selector starts with a ? then it is optional\n\t var optional = (elementSelector.charAt(0) === '?');\n\t elementSelector = optional ? elementSelector.substring(1) : elementSelector;\n\t\n\t slotMap[elementSelector] = slotName;\n\t\n\t // We explicitly assign `null` since this implies that a slot was defined but not filled.\n\t // Later when calling boundTransclusion functions with a slot name we only error if the\n\t // slot is `undefined`\n\t slots[slotName] = null;\n\t\n\t // filledSlots contains `true` for all slots that are either optional or have been\n\t // filled. This is used to check that we have not missed any required slots\n\t filledSlots[slotName] = optional;\n\t });\n\t\n\t // Add the matching elements into their slot\n\t forEach($compileNode.contents(), function(node) {\n\t var slotName = slotMap[directiveNormalize(nodeName_(node))];\n\t if (slotName) {\n\t filledSlots[slotName] = true;\n\t slots[slotName] = slots[slotName] || [];\n\t slots[slotName].push(node);\n\t } else {\n\t $template.push(node);\n\t }\n\t });\n\t\n\t // Check for required slots that were not filled\n\t forEach(filledSlots, function(filled, slotName) {\n\t if (!filled) {\n\t throw $compileMinErr('reqslot', 'Required transclusion slot `{0}` was not filled.', slotName);\n\t }\n\t });\n\t\n\t for (var slotName in slots) {\n\t if (slots[slotName]) {\n\t // Only define a transclusion function if the slot was filled\n\t slots[slotName] = compilationGenerator(mightHaveMultipleTransclusionError, slots[slotName], transcludeFn);\n\t }\n\t }\n\t }\n\t\n\t $compileNode.empty(); // clear contents\n\t childTranscludeFn = compilationGenerator(mightHaveMultipleTransclusionError, $template, transcludeFn, undefined,\n\t undefined, { needsNewScope: directive.$$isolateScope || directive.$$newScope});\n\t childTranscludeFn.$$slots = slots;\n\t }\n\t }\n\t\n\t if (directive.template) {\n\t hasTemplate = true;\n\t assertNoDuplicate('template', templateDirective, directive, $compileNode);\n\t templateDirective = directive;\n\t\n\t directiveValue = (isFunction(directive.template))\n\t ? directive.template($compileNode, templateAttrs)\n\t : directive.template;\n\t\n\t directiveValue = denormalizeTemplate(directiveValue);\n\t\n\t if (directive.replace) {\n\t replaceDirective = directive;\n\t if (jqLiteIsTextNode(directiveValue)) {\n\t $template = [];\n\t } else {\n\t $template = removeComments(wrapTemplate(directive.templateNamespace, trim(directiveValue)));\n\t }\n\t compileNode = $template[0];\n\t\n\t if ($template.length != 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) {\n\t throw $compileMinErr('tplrt',\n\t \"Template for directive '{0}' must have exactly one root element. {1}\",\n\t directiveName, '');\n\t }\n\t\n\t replaceWith(jqCollection, $compileNode, compileNode);\n\t\n\t var newTemplateAttrs = {$attr: {}};\n\t\n\t // combine directives from the original node and from the template:\n\t // - take the array of directives for this element\n\t // - split it into two parts, those that already applied (processed) and those that weren't (unprocessed)\n\t // - collect directives from the template and sort them by priority\n\t // - combine directives as: processed + template + unprocessed\n\t var templateDirectives = collectDirectives(compileNode, [], newTemplateAttrs);\n\t var unprocessedDirectives = directives.splice(i + 1, directives.length - (i + 1));\n\t\n\t if (newIsolateScopeDirective || newScopeDirective) {\n\t // The original directive caused the current element to be replaced but this element\n\t // also needs to have a new scope, so we need to tell the template directives\n\t // that they would need to get their scope from further up, if they require transclusion\n\t markDirectiveScope(templateDirectives, newIsolateScopeDirective, newScopeDirective);\n\t }\n\t directives = directives.concat(templateDirectives).concat(unprocessedDirectives);\n\t mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\t\n\t ii = directives.length;\n\t } else {\n\t $compileNode.html(directiveValue);\n\t }\n\t }\n\t\n\t if (directive.templateUrl) {\n\t hasTemplate = true;\n\t assertNoDuplicate('template', templateDirective, directive, $compileNode);\n\t templateDirective = directive;\n\t\n\t if (directive.replace) {\n\t replaceDirective = directive;\n\t }\n\t\n\t /* jshint -W021 */\n\t nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode,\n\t /* jshint +W021 */\n\t templateAttrs, jqCollection, hasTranscludeDirective && childTranscludeFn, preLinkFns, postLinkFns, {\n\t controllerDirectives: controllerDirectives,\n\t newScopeDirective: (newScopeDirective !== directive) && newScopeDirective,\n\t newIsolateScopeDirective: newIsolateScopeDirective,\n\t templateDirective: templateDirective,\n\t nonTlbTranscludeDirective: nonTlbTranscludeDirective\n\t });\n\t ii = directives.length;\n\t } else if (directive.compile) {\n\t try {\n\t linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n\t var context = directive.$$originalDirective || directive;\n\t if (isFunction(linkFn)) {\n\t addLinkFns(null, bind(context, linkFn), attrStart, attrEnd);\n\t } else if (linkFn) {\n\t addLinkFns(bind(context, linkFn.pre), bind(context, linkFn.post), attrStart, attrEnd);\n\t }\n\t } catch (e) {\n\t $exceptionHandler(e, startingTag($compileNode));\n\t }\n\t }\n\t\n\t if (directive.terminal) {\n\t nodeLinkFn.terminal = true;\n\t terminalPriority = Math.max(terminalPriority, directive.priority);\n\t }\n\t\n\t }\n\t\n\t nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true;\n\t nodeLinkFn.transcludeOnThisElement = hasTranscludeDirective;\n\t nodeLinkFn.templateOnThisElement = hasTemplate;\n\t nodeLinkFn.transclude = childTranscludeFn;\n\t\n\t previousCompileContext.hasElementTranscludeDirective = hasElementTranscludeDirective;\n\t\n\t // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n\t return nodeLinkFn;\n\t\n\t ////////////////////\n\t\n\t function addLinkFns(pre, post, attrStart, attrEnd) {\n\t if (pre) {\n\t if (attrStart) pre = groupElementsLinkFnWrapper(pre, attrStart, attrEnd);\n\t pre.require = directive.require;\n\t pre.directiveName = directiveName;\n\t if (newIsolateScopeDirective === directive || directive.$$isolateScope) {\n\t pre = cloneAndAnnotateFn(pre, {isolateScope: true});\n\t }\n\t preLinkFns.push(pre);\n\t }\n\t if (post) {\n\t if (attrStart) post = groupElementsLinkFnWrapper(post, attrStart, attrEnd);\n\t post.require = directive.require;\n\t post.directiveName = directiveName;\n\t if (newIsolateScopeDirective === directive || directive.$$isolateScope) {\n\t post = cloneAndAnnotateFn(post, {isolateScope: true});\n\t }\n\t postLinkFns.push(post);\n\t }\n\t }\n\t\n\t function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n\t var i, ii, linkFn, isolateScope, controllerScope, elementControllers, transcludeFn, $element,\n\t attrs, scopeBindingInfo;\n\t\n\t if (compileNode === linkNode) {\n\t attrs = templateAttrs;\n\t $element = templateAttrs.$$element;\n\t } else {\n\t $element = jqLite(linkNode);\n\t attrs = new Attributes($element, templateAttrs);\n\t }\n\t\n\t controllerScope = scope;\n\t if (newIsolateScopeDirective) {\n\t isolateScope = scope.$new(true);\n\t } else if (newScopeDirective) {\n\t controllerScope = scope.$parent;\n\t }\n\t\n\t if (boundTranscludeFn) {\n\t // track `boundTranscludeFn` so it can be unwrapped if `transcludeFn`\n\t // is later passed as `parentBoundTranscludeFn` to `publicLinkFn`\n\t transcludeFn = controllersBoundTransclude;\n\t transcludeFn.$$boundTransclude = boundTranscludeFn;\n\t // expose the slots on the `$transclude` function\n\t transcludeFn.isSlotFilled = function(slotName) {\n\t return !!boundTranscludeFn.$$slots[slotName];\n\t };\n\t }\n\t\n\t if (controllerDirectives) {\n\t elementControllers = setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope, newIsolateScopeDirective);\n\t }\n\t\n\t if (newIsolateScopeDirective) {\n\t // Initialize isolate scope bindings for new isolate scope directive.\n\t compile.$$addScopeInfo($element, isolateScope, true, !(templateDirective && (templateDirective === newIsolateScopeDirective ||\n\t templateDirective === newIsolateScopeDirective.$$originalDirective)));\n\t compile.$$addScopeClass($element, true);\n\t isolateScope.$$isolateBindings =\n\t newIsolateScopeDirective.$$isolateBindings;\n\t scopeBindingInfo = initializeDirectiveBindings(scope, attrs, isolateScope,\n\t isolateScope.$$isolateBindings,\n\t newIsolateScopeDirective);\n\t if (scopeBindingInfo.removeWatches) {\n\t isolateScope.$on('$destroy', scopeBindingInfo.removeWatches);\n\t }\n\t }\n\t\n\t // Initialize bindToController bindings\n\t for (var name in elementControllers) {\n\t var controllerDirective = controllerDirectives[name];\n\t var controller = elementControllers[name];\n\t var bindings = controllerDirective.$$bindings.bindToController;\n\t\n\t if (controller.identifier && bindings) {\n\t controller.bindingInfo =\n\t initializeDirectiveBindings(controllerScope, attrs, controller.instance, bindings, controllerDirective);\n\t } else {\n\t controller.bindingInfo = {};\n\t }\n\t\n\t var controllerResult = controller();\n\t if (controllerResult !== controller.instance) {\n\t // If the controller constructor has a return value, overwrite the instance\n\t // from setupControllers\n\t controller.instance = controllerResult;\n\t $element.data('$' + controllerDirective.name + 'Controller', controllerResult);\n\t controller.bindingInfo.removeWatches && controller.bindingInfo.removeWatches();\n\t controller.bindingInfo =\n\t initializeDirectiveBindings(controllerScope, attrs, controller.instance, bindings, controllerDirective);\n\t }\n\t }\n\t\n\t // Bind the required controllers to the controller, if `require` is an object and `bindToController` is truthy\n\t forEach(controllerDirectives, function(controllerDirective, name) {\n\t var require = controllerDirective.require;\n\t if (controllerDirective.bindToController && !isArray(require) && isObject(require)) {\n\t extend(elementControllers[name].instance, getControllers(name, require, $element, elementControllers));\n\t }\n\t });\n\t\n\t // Handle the init and destroy lifecycle hooks on all controllers that have them\n\t forEach(elementControllers, function(controller) {\n\t var controllerInstance = controller.instance;\n\t if (isFunction(controllerInstance.$onChanges)) {\n\t try {\n\t controllerInstance.$onChanges(controller.bindingInfo.initialChanges);\n\t } catch (e) {\n\t $exceptionHandler(e);\n\t }\n\t }\n\t if (isFunction(controllerInstance.$onInit)) {\n\t try {\n\t controllerInstance.$onInit();\n\t } catch (e) {\n\t $exceptionHandler(e);\n\t }\n\t }\n\t if (isFunction(controllerInstance.$doCheck)) {\n\t controllerScope.$watch(function() { controllerInstance.$doCheck(); });\n\t controllerInstance.$doCheck();\n\t }\n\t if (isFunction(controllerInstance.$onDestroy)) {\n\t controllerScope.$on('$destroy', function callOnDestroyHook() {\n\t controllerInstance.$onDestroy();\n\t });\n\t }\n\t });\n\t\n\t // PRELINKING\n\t for (i = 0, ii = preLinkFns.length; i < ii; i++) {\n\t linkFn = preLinkFns[i];\n\t invokeLinkFn(linkFn,\n\t linkFn.isolateScope ? isolateScope : scope,\n\t $element,\n\t attrs,\n\t linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers),\n\t transcludeFn\n\t );\n\t }\n\t\n\t // RECURSION\n\t // We only pass the isolate scope, if the isolate directive has a template,\n\t // otherwise the child elements do not belong to the isolate directive.\n\t var scopeToChild = scope;\n\t if (newIsolateScopeDirective && (newIsolateScopeDirective.template || newIsolateScopeDirective.templateUrl === null)) {\n\t scopeToChild = isolateScope;\n\t }\n\t childLinkFn && childLinkFn(scopeToChild, linkNode.childNodes, undefined, boundTranscludeFn);\n\t\n\t // POSTLINKING\n\t for (i = postLinkFns.length - 1; i >= 0; i--) {\n\t linkFn = postLinkFns[i];\n\t invokeLinkFn(linkFn,\n\t linkFn.isolateScope ? isolateScope : scope,\n\t $element,\n\t attrs,\n\t linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers),\n\t transcludeFn\n\t );\n\t }\n\t\n\t // Trigger $postLink lifecycle hooks\n\t forEach(elementControllers, function(controller) {\n\t var controllerInstance = controller.instance;\n\t if (isFunction(controllerInstance.$postLink)) {\n\t controllerInstance.$postLink();\n\t }\n\t });\n\t\n\t // This is the function that is injected as `$transclude`.\n\t // Note: all arguments are optional!\n\t function controllersBoundTransclude(scope, cloneAttachFn, futureParentElement, slotName) {\n\t var transcludeControllers;\n\t // No scope passed in:\n\t if (!isScope(scope)) {\n\t slotName = futureParentElement;\n\t futureParentElement = cloneAttachFn;\n\t cloneAttachFn = scope;\n\t scope = undefined;\n\t }\n\t\n\t if (hasElementTranscludeDirective) {\n\t transcludeControllers = elementControllers;\n\t }\n\t if (!futureParentElement) {\n\t futureParentElement = hasElementTranscludeDirective ? $element.parent() : $element;\n\t }\n\t if (slotName) {\n\t // slotTranscludeFn can be one of three things:\n\t // * a transclude function - a filled slot\n\t // * `null` - an optional slot that was not filled\n\t // * `undefined` - a slot that was not declared (i.e. invalid)\n\t var slotTranscludeFn = boundTranscludeFn.$$slots[slotName];\n\t if (slotTranscludeFn) {\n\t return slotTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild);\n\t } else if (isUndefined(slotTranscludeFn)) {\n\t throw $compileMinErr('noslot',\n\t 'No parent directive that requires a transclusion with slot name \"{0}\". ' +\n\t 'Element: {1}',\n\t slotName, startingTag($element));\n\t }\n\t } else {\n\t return boundTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild);\n\t }\n\t }\n\t }\n\t }\n\t\n\t function getControllers(directiveName, require, $element, elementControllers) {\n\t var value;\n\t\n\t if (isString(require)) {\n\t var match = require.match(REQUIRE_PREFIX_REGEXP);\n\t var name = require.substring(match[0].length);\n\t var inheritType = match[1] || match[3];\n\t var optional = match[2] === '?';\n\t\n\t //If only parents then start at the parent element\n\t if (inheritType === '^^') {\n\t $element = $element.parent();\n\t //Otherwise attempt getting the controller from elementControllers in case\n\t //the element is transcluded (and has no data) and to avoid .data if possible\n\t } else {\n\t value = elementControllers && elementControllers[name];\n\t value = value && value.instance;\n\t }\n\t\n\t if (!value) {\n\t var dataName = '$' + name + 'Controller';\n\t value = inheritType ? $element.inheritedData(dataName) : $element.data(dataName);\n\t }\n\t\n\t if (!value && !optional) {\n\t throw $compileMinErr('ctreq',\n\t \"Controller '{0}', required by directive '{1}', can't be found!\",\n\t name, directiveName);\n\t }\n\t } else if (isArray(require)) {\n\t value = [];\n\t for (var i = 0, ii = require.length; i < ii; i++) {\n\t value[i] = getControllers(directiveName, require[i], $element, elementControllers);\n\t }\n\t } else if (isObject(require)) {\n\t value = {};\n\t forEach(require, function(controller, property) {\n\t value[property] = getControllers(directiveName, controller, $element, elementControllers);\n\t });\n\t }\n\t\n\t return value || null;\n\t }\n\t\n\t function setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope, newIsolateScopeDirective) {\n\t var elementControllers = createMap();\n\t for (var controllerKey in controllerDirectives) {\n\t var directive = controllerDirectives[controllerKey];\n\t var locals = {\n\t $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope,\n\t $element: $element,\n\t $attrs: attrs,\n\t $transclude: transcludeFn\n\t };\n\t\n\t var controller = directive.controller;\n\t if (controller == '@') {\n\t controller = attrs[directive.name];\n\t }\n\t\n\t var controllerInstance = $controller(controller, locals, true, directive.controllerAs);\n\t\n\t // For directives with element transclusion the element is a comment.\n\t // In this case .data will not attach any data.\n\t // Instead, we save the controllers for the element in a local hash and attach to .data\n\t // later, once we have the actual element.\n\t elementControllers[directive.name] = controllerInstance;\n\t $element.data('$' + directive.name + 'Controller', controllerInstance.instance);\n\t }\n\t return elementControllers;\n\t }\n\t\n\t // Depending upon the context in which a directive finds itself it might need to have a new isolated\n\t // or child scope created. For instance:\n\t // * if the directive has been pulled into a template because another directive with a higher priority\n\t // asked for element transclusion\n\t // * if the directive itself asks for transclusion but it is at the root of a template and the original\n\t // element was replaced. See https://github.com/angular/angular.js/issues/12936\n\t function markDirectiveScope(directives, isolateScope, newScope) {\n\t for (var j = 0, jj = directives.length; j < jj; j++) {\n\t directives[j] = inherit(directives[j], {$$isolateScope: isolateScope, $$newScope: newScope});\n\t }\n\t }\n\t\n\t /**\n\t * looks up the directive and decorates it with exception handling and proper parameters. We\n\t * call this the boundDirective.\n\t *\n\t * @param {string} name name of the directive to look up.\n\t * @param {string} location The directive must be found in specific format.\n\t * String containing any of theses characters:\n\t *\n\t * * `E`: element name\n\t * * `A': attribute\n\t * * `C`: class\n\t * * `M`: comment\n\t * @returns {boolean} true if directive was added.\n\t */\n\t function addDirective(tDirectives, name, location, maxPriority, ignoreDirective, startAttrName,\n\t endAttrName) {\n\t if (name === ignoreDirective) return null;\n\t var match = null;\n\t if (hasDirectives.hasOwnProperty(name)) {\n\t for (var directive, directives = $injector.get(name + Suffix),\n\t i = 0, ii = directives.length; i < ii; i++) {\n\t try {\n\t directive = directives[i];\n\t if ((isUndefined(maxPriority) || maxPriority > directive.priority) &&\n\t directive.restrict.indexOf(location) != -1) {\n\t if (startAttrName) {\n\t directive = inherit(directive, {$$start: startAttrName, $$end: endAttrName});\n\t }\n\t if (!directive.$$bindings) {\n\t var bindings = directive.$$bindings =\n\t parseDirectiveBindings(directive, directive.name);\n\t if (isObject(bindings.isolateScope)) {\n\t directive.$$isolateBindings = bindings.isolateScope;\n\t }\n\t }\n\t tDirectives.push(directive);\n\t match = directive;\n\t }\n\t } catch (e) { $exceptionHandler(e); }\n\t }\n\t }\n\t return match;\n\t }\n\t\n\t\n\t /**\n\t * looks up the directive and returns true if it is a multi-element directive,\n\t * and therefore requires DOM nodes between -start and -end markers to be grouped\n\t * together.\n\t *\n\t * @param {string} name name of the directive to look up.\n\t * @returns true if directive was registered as multi-element.\n\t */\n\t function directiveIsMultiElement(name) {\n\t if (hasDirectives.hasOwnProperty(name)) {\n\t for (var directive, directives = $injector.get(name + Suffix),\n\t i = 0, ii = directives.length; i < ii; i++) {\n\t directive = directives[i];\n\t if (directive.multiElement) {\n\t return true;\n\t }\n\t }\n\t }\n\t return false;\n\t }\n\t\n\t /**\n\t * When the element is replaced with HTML template then the new attributes\n\t * on the template need to be merged with the existing attributes in the DOM.\n\t * The desired effect is to have both of the attributes present.\n\t *\n\t * @param {object} dst destination attributes (original DOM)\n\t * @param {object} src source attributes (from the directive template)\n\t */\n\t function mergeTemplateAttributes(dst, src) {\n\t var srcAttr = src.$attr,\n\t dstAttr = dst.$attr,\n\t $element = dst.$$element;\n\t\n\t // reapply the old attributes to the new element\n\t forEach(dst, function(value, key) {\n\t if (key.charAt(0) != '$') {\n\t if (src[key] && src[key] !== value) {\n\t value += (key === 'style' ? ';' : ' ') + src[key];\n\t }\n\t dst.$set(key, value, true, srcAttr[key]);\n\t }\n\t });\n\t\n\t // copy the new attributes on the old attrs object\n\t forEach(src, function(value, key) {\n\t // Check if we already set this attribute in the loop above.\n\t // `dst` will never contain hasOwnProperty as DOM parser won't let it.\n\t // You will get an \"InvalidCharacterError: DOM Exception 5\" error if you\n\t // have an attribute like \"has-own-property\" or \"data-has-own-property\", etc.\n\t if (!dst.hasOwnProperty(key) && key.charAt(0) !== '$') {\n\t dst[key] = value;\n\t\n\t if (key !== 'class' && key !== 'style') {\n\t dstAttr[key] = srcAttr[key];\n\t }\n\t }\n\t });\n\t }\n\t\n\t\n\t function compileTemplateUrl(directives, $compileNode, tAttrs,\n\t $rootElement, childTranscludeFn, preLinkFns, postLinkFns, previousCompileContext) {\n\t var linkQueue = [],\n\t afterTemplateNodeLinkFn,\n\t afterTemplateChildLinkFn,\n\t beforeTemplateCompileNode = $compileNode[0],\n\t origAsyncDirective = directives.shift(),\n\t derivedSyncDirective = inherit(origAsyncDirective, {\n\t templateUrl: null, transclude: null, replace: null, $$originalDirective: origAsyncDirective\n\t }),\n\t templateUrl = (isFunction(origAsyncDirective.templateUrl))\n\t ? origAsyncDirective.templateUrl($compileNode, tAttrs)\n\t : origAsyncDirective.templateUrl,\n\t templateNamespace = origAsyncDirective.templateNamespace;\n\t\n\t $compileNode.empty();\n\t\n\t $templateRequest(templateUrl)\n\t .then(function(content) {\n\t var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn;\n\t\n\t content = denormalizeTemplate(content);\n\t\n\t if (origAsyncDirective.replace) {\n\t if (jqLiteIsTextNode(content)) {\n\t $template = [];\n\t } else {\n\t $template = removeComments(wrapTemplate(templateNamespace, trim(content)));\n\t }\n\t compileNode = $template[0];\n\t\n\t if ($template.length != 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) {\n\t throw $compileMinErr('tplrt',\n\t \"Template for directive '{0}' must have exactly one root element. {1}\",\n\t origAsyncDirective.name, templateUrl);\n\t }\n\t\n\t tempTemplateAttrs = {$attr: {}};\n\t replaceWith($rootElement, $compileNode, compileNode);\n\t var templateDirectives = collectDirectives(compileNode, [], tempTemplateAttrs);\n\t\n\t if (isObject(origAsyncDirective.scope)) {\n\t // the original directive that caused the template to be loaded async required\n\t // an isolate scope\n\t markDirectiveScope(templateDirectives, true);\n\t }\n\t directives = templateDirectives.concat(directives);\n\t mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n\t } else {\n\t compileNode = beforeTemplateCompileNode;\n\t $compileNode.html(content);\n\t }\n\t\n\t directives.unshift(derivedSyncDirective);\n\t\n\t afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs,\n\t childTranscludeFn, $compileNode, origAsyncDirective, preLinkFns, postLinkFns,\n\t previousCompileContext);\n\t forEach($rootElement, function(node, i) {\n\t if (node == compileNode) {\n\t $rootElement[i] = $compileNode[0];\n\t }\n\t });\n\t afterTemplateChildLinkFn = compileNodes($compileNode[0].childNodes, childTranscludeFn);\n\t\n\t while (linkQueue.length) {\n\t var scope = linkQueue.shift(),\n\t beforeTemplateLinkNode = linkQueue.shift(),\n\t linkRootElement = linkQueue.shift(),\n\t boundTranscludeFn = linkQueue.shift(),\n\t linkNode = $compileNode[0];\n\t\n\t if (scope.$$destroyed) continue;\n\t\n\t if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n\t var oldClasses = beforeTemplateLinkNode.className;\n\t\n\t if (!(previousCompileContext.hasElementTranscludeDirective &&\n\t origAsyncDirective.replace)) {\n\t // it was cloned therefore we have to clone as well.\n\t linkNode = jqLiteClone(compileNode);\n\t }\n\t replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n\t\n\t // Copy in CSS classes from original node\n\t safeAddClass(jqLite(linkNode), oldClasses);\n\t }\n\t if (afterTemplateNodeLinkFn.transcludeOnThisElement) {\n\t childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);\n\t } else {\n\t childBoundTranscludeFn = boundTranscludeFn;\n\t }\n\t afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement,\n\t childBoundTranscludeFn);\n\t }\n\t linkQueue = null;\n\t });\n\t\n\t return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, boundTranscludeFn) {\n\t var childBoundTranscludeFn = boundTranscludeFn;\n\t if (scope.$$destroyed) return;\n\t if (linkQueue) {\n\t linkQueue.push(scope,\n\t node,\n\t rootElement,\n\t childBoundTranscludeFn);\n\t } else {\n\t if (afterTemplateNodeLinkFn.transcludeOnThisElement) {\n\t childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);\n\t }\n\t afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, childBoundTranscludeFn);\n\t }\n\t };\n\t }\n\t\n\t\n\t /**\n\t * Sorting function for bound directives.\n\t */\n\t function byPriority(a, b) {\n\t var diff = b.priority - a.priority;\n\t if (diff !== 0) return diff;\n\t if (a.name !== b.name) return (a.name < b.name) ? -1 : 1;\n\t return a.index - b.index;\n\t }\n\t\n\t function assertNoDuplicate(what, previousDirective, directive, element) {\n\t\n\t function wrapModuleNameIfDefined(moduleName) {\n\t return moduleName ?\n\t (' (module: ' + moduleName + ')') :\n\t '';\n\t }\n\t\n\t if (previousDirective) {\n\t throw $compileMinErr('multidir', 'Multiple directives [{0}{1}, {2}{3}] asking for {4} on: {5}',\n\t previousDirective.name, wrapModuleNameIfDefined(previousDirective.$$moduleName),\n\t directive.name, wrapModuleNameIfDefined(directive.$$moduleName), what, startingTag(element));\n\t }\n\t }\n\t\n\t\n\t function addTextInterpolateDirective(directives, text) {\n\t var interpolateFn = $interpolate(text, true);\n\t if (interpolateFn) {\n\t directives.push({\n\t priority: 0,\n\t compile: function textInterpolateCompileFn(templateNode) {\n\t var templateNodeParent = templateNode.parent(),\n\t hasCompileParent = !!templateNodeParent.length;\n\t\n\t // When transcluding a template that has bindings in the root\n\t // we don't have a parent and thus need to add the class during linking fn.\n\t if (hasCompileParent) compile.$$addBindingClass(templateNodeParent);\n\t\n\t return function textInterpolateLinkFn(scope, node) {\n\t var parent = node.parent();\n\t if (!hasCompileParent) compile.$$addBindingClass(parent);\n\t compile.$$addBindingInfo(parent, interpolateFn.expressions);\n\t scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n\t node[0].nodeValue = value;\n\t });\n\t };\n\t }\n\t });\n\t }\n\t }\n\t\n\t\n\t function wrapTemplate(type, template) {\n\t type = lowercase(type || 'html');\n\t switch (type) {\n\t case 'svg':\n\t case 'math':\n\t var wrapper = window.document.createElement('div');\n\t wrapper.innerHTML = '<' + type + '>' + template + '';\n\t return wrapper.childNodes[0].childNodes;\n\t default:\n\t return template;\n\t }\n\t }\n\t\n\t\n\t function getTrustedContext(node, attrNormalizedName) {\n\t if (attrNormalizedName == \"srcdoc\") {\n\t return $sce.HTML;\n\t }\n\t var tag = nodeName_(node);\n\t // maction[xlink:href] can source SVG. It's not limited to .\n\t if (attrNormalizedName == \"xlinkHref\" ||\n\t (tag == \"form\" && attrNormalizedName == \"action\") ||\n\t (tag != \"img\" && (attrNormalizedName == \"src\" ||\n\t attrNormalizedName == \"ngSrc\"))) {\n\t return $sce.RESOURCE_URL;\n\t }\n\t }\n\t\n\t\n\t function addAttrInterpolateDirective(node, directives, value, name, allOrNothing) {\n\t var trustedContext = getTrustedContext(node, name);\n\t allOrNothing = ALL_OR_NOTHING_ATTRS[name] || allOrNothing;\n\t\n\t var interpolateFn = $interpolate(value, true, trustedContext, allOrNothing);\n\t\n\t // no interpolation found -> ignore\n\t if (!interpolateFn) return;\n\t\n\t\n\t if (name === \"multiple\" && nodeName_(node) === \"select\") {\n\t throw $compileMinErr(\"selmulti\",\n\t \"Binding to the 'multiple' attribute is not supported. Element: {0}\",\n\t startingTag(node));\n\t }\n\t\n\t directives.push({\n\t priority: 100,\n\t compile: function() {\n\t return {\n\t pre: function attrInterpolatePreLinkFn(scope, element, attr) {\n\t var $$observers = (attr.$$observers || (attr.$$observers = createMap()));\n\t\n\t if (EVENT_HANDLER_ATTR_REGEXP.test(name)) {\n\t throw $compileMinErr('nodomevents',\n\t \"Interpolations for HTML DOM event attributes are disallowed. Please use the \" +\n\t \"ng- versions (such as ng-click instead of onclick) instead.\");\n\t }\n\t\n\t // If the attribute has changed since last $interpolate()ed\n\t var newValue = attr[name];\n\t if (newValue !== value) {\n\t // we need to interpolate again since the attribute value has been updated\n\t // (e.g. by another directive's compile function)\n\t // ensure unset/empty values make interpolateFn falsy\n\t interpolateFn = newValue && $interpolate(newValue, true, trustedContext, allOrNothing);\n\t value = newValue;\n\t }\n\t\n\t // if attribute was updated so that there is no interpolation going on we don't want to\n\t // register any observers\n\t if (!interpolateFn) return;\n\t\n\t // initialize attr object so that it's ready in case we need the value for isolate\n\t // scope initialization, otherwise the value would not be available from isolate\n\t // directive's linking fn during linking phase\n\t attr[name] = interpolateFn(scope);\n\t\n\t ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n\t (attr.$$observers && attr.$$observers[name].$$scope || scope).\n\t $watch(interpolateFn, function interpolateFnWatchAction(newValue, oldValue) {\n\t //special case for class attribute addition + removal\n\t //so that class changes can tap into the animation\n\t //hooks provided by the $animate service. Be sure to\n\t //skip animations when the first digest occurs (when\n\t //both the new and the old values are the same) since\n\t //the CSS classes are the non-interpolated values\n\t if (name === 'class' && newValue != oldValue) {\n\t attr.$updateClass(newValue, oldValue);\n\t } else {\n\t attr.$set(name, newValue);\n\t }\n\t });\n\t }\n\t };\n\t }\n\t });\n\t }\n\t\n\t\n\t /**\n\t * This is a special jqLite.replaceWith, which can replace items which\n\t * have no parents, provided that the containing jqLite collection is provided.\n\t *\n\t * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n\t * in the root of the tree.\n\t * @param {JqLite} elementsToRemove The jqLite element which we are going to replace. We keep\n\t * the shell, but replace its DOM node reference.\n\t * @param {Node} newNode The new DOM node.\n\t */\n\t function replaceWith($rootElement, elementsToRemove, newNode) {\n\t var firstElementToRemove = elementsToRemove[0],\n\t removeCount = elementsToRemove.length,\n\t parent = firstElementToRemove.parentNode,\n\t i, ii;\n\t\n\t if ($rootElement) {\n\t for (i = 0, ii = $rootElement.length; i < ii; i++) {\n\t if ($rootElement[i] == firstElementToRemove) {\n\t $rootElement[i++] = newNode;\n\t for (var j = i, j2 = j + removeCount - 1,\n\t jj = $rootElement.length;\n\t j < jj; j++, j2++) {\n\t if (j2 < jj) {\n\t $rootElement[j] = $rootElement[j2];\n\t } else {\n\t delete $rootElement[j];\n\t }\n\t }\n\t $rootElement.length -= removeCount - 1;\n\t\n\t // If the replaced element is also the jQuery .context then replace it\n\t // .context is a deprecated jQuery api, so we should set it only when jQuery set it\n\t // http://api.jquery.com/context/\n\t if ($rootElement.context === firstElementToRemove) {\n\t $rootElement.context = newNode;\n\t }\n\t break;\n\t }\n\t }\n\t }\n\t\n\t if (parent) {\n\t parent.replaceChild(newNode, firstElementToRemove);\n\t }\n\t\n\t // Append all the `elementsToRemove` to a fragment. This will...\n\t // - remove them from the DOM\n\t // - allow them to still be traversed with .nextSibling\n\t // - allow a single fragment.qSA to fetch all elements being removed\n\t var fragment = window.document.createDocumentFragment();\n\t for (i = 0; i < removeCount; i++) {\n\t fragment.appendChild(elementsToRemove[i]);\n\t }\n\t\n\t if (jqLite.hasData(firstElementToRemove)) {\n\t // Copy over user data (that includes Angular's $scope etc.). Don't copy private\n\t // data here because there's no public interface in jQuery to do that and copying over\n\t // event listeners (which is the main use of private data) wouldn't work anyway.\n\t jqLite.data(newNode, jqLite.data(firstElementToRemove));\n\t\n\t // Remove $destroy event listeners from `firstElementToRemove`\n\t jqLite(firstElementToRemove).off('$destroy');\n\t }\n\t\n\t // Cleanup any data/listeners on the elements and children.\n\t // This includes invoking the $destroy event on any elements with listeners.\n\t jqLite.cleanData(fragment.querySelectorAll('*'));\n\t\n\t // Update the jqLite collection to only contain the `newNode`\n\t for (i = 1; i < removeCount; i++) {\n\t delete elementsToRemove[i];\n\t }\n\t elementsToRemove[0] = newNode;\n\t elementsToRemove.length = 1;\n\t }\n\t\n\t\n\t function cloneAndAnnotateFn(fn, annotation) {\n\t return extend(function() { return fn.apply(null, arguments); }, fn, annotation);\n\t }\n\t\n\t\n\t function invokeLinkFn(linkFn, scope, $element, attrs, controllers, transcludeFn) {\n\t try {\n\t linkFn(scope, $element, attrs, controllers, transcludeFn);\n\t } catch (e) {\n\t $exceptionHandler(e, startingTag($element));\n\t }\n\t }\n\t\n\t\n\t // Set up $watches for isolate scope and controller bindings. This process\n\t // only occurs for isolate scopes and new scopes with controllerAs.\n\t function initializeDirectiveBindings(scope, attrs, destination, bindings, directive) {\n\t var removeWatchCollection = [];\n\t var initialChanges = {};\n\t var changes;\n\t forEach(bindings, function initializeBinding(definition, scopeName) {\n\t var attrName = definition.attrName,\n\t optional = definition.optional,\n\t mode = definition.mode, // @, =, <, or &\n\t lastValue,\n\t parentGet, parentSet, compare, removeWatch;\n\t\n\t switch (mode) {\n\t\n\t case '@':\n\t if (!optional && !hasOwnProperty.call(attrs, attrName)) {\n\t destination[scopeName] = attrs[attrName] = void 0;\n\t }\n\t attrs.$observe(attrName, function(value) {\n\t if (isString(value) || isBoolean(value)) {\n\t var oldValue = destination[scopeName];\n\t recordChanges(scopeName, value, oldValue);\n\t destination[scopeName] = value;\n\t }\n\t });\n\t attrs.$$observers[attrName].$$scope = scope;\n\t lastValue = attrs[attrName];\n\t if (isString(lastValue)) {\n\t // If the attribute has been provided then we trigger an interpolation to ensure\n\t // the value is there for use in the link fn\n\t destination[scopeName] = $interpolate(lastValue)(scope);\n\t } else if (isBoolean(lastValue)) {\n\t // If the attributes is one of the BOOLEAN_ATTR then Angular will have converted\n\t // the value to boolean rather than a string, so we special case this situation\n\t destination[scopeName] = lastValue;\n\t }\n\t initialChanges[scopeName] = new SimpleChange(_UNINITIALIZED_VALUE, destination[scopeName]);\n\t break;\n\t\n\t case '=':\n\t if (!hasOwnProperty.call(attrs, attrName)) {\n\t if (optional) break;\n\t attrs[attrName] = void 0;\n\t }\n\t if (optional && !attrs[attrName]) break;\n\t\n\t parentGet = $parse(attrs[attrName]);\n\t if (parentGet.literal) {\n\t compare = equals;\n\t } else {\n\t compare = function simpleCompare(a, b) { return a === b || (a !== a && b !== b); };\n\t }\n\t parentSet = parentGet.assign || function() {\n\t // reset the change, or we will throw this exception on every $digest\n\t lastValue = destination[scopeName] = parentGet(scope);\n\t throw $compileMinErr('nonassign',\n\t \"Expression '{0}' in attribute '{1}' used with directive '{2}' is non-assignable!\",\n\t attrs[attrName], attrName, directive.name);\n\t };\n\t lastValue = destination[scopeName] = parentGet(scope);\n\t var parentValueWatch = function parentValueWatch(parentValue) {\n\t if (!compare(parentValue, destination[scopeName])) {\n\t // we are out of sync and need to copy\n\t if (!compare(parentValue, lastValue)) {\n\t // parent changed and it has precedence\n\t destination[scopeName] = parentValue;\n\t } else {\n\t // if the parent can be assigned then do so\n\t parentSet(scope, parentValue = destination[scopeName]);\n\t }\n\t }\n\t return lastValue = parentValue;\n\t };\n\t parentValueWatch.$stateful = true;\n\t if (definition.collection) {\n\t removeWatch = scope.$watchCollection(attrs[attrName], parentValueWatch);\n\t } else {\n\t removeWatch = scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal);\n\t }\n\t removeWatchCollection.push(removeWatch);\n\t break;\n\t\n\t case '<':\n\t if (!hasOwnProperty.call(attrs, attrName)) {\n\t if (optional) break;\n\t attrs[attrName] = void 0;\n\t }\n\t if (optional && !attrs[attrName]) break;\n\t\n\t parentGet = $parse(attrs[attrName]);\n\t\n\t var initialValue = destination[scopeName] = parentGet(scope);\n\t initialChanges[scopeName] = new SimpleChange(_UNINITIALIZED_VALUE, destination[scopeName]);\n\t\n\t removeWatch = scope.$watch(parentGet, function parentValueWatchAction(newValue, oldValue) {\n\t if (oldValue === newValue) {\n\t if (oldValue === initialValue) return;\n\t oldValue = initialValue;\n\t }\n\t recordChanges(scopeName, newValue, oldValue);\n\t destination[scopeName] = newValue;\n\t }, parentGet.literal);\n\t\n\t removeWatchCollection.push(removeWatch);\n\t break;\n\t\n\t case '&':\n\t // Don't assign Object.prototype method to scope\n\t parentGet = attrs.hasOwnProperty(attrName) ? $parse(attrs[attrName]) : noop;\n\t\n\t // Don't assign noop to destination if expression is not valid\n\t if (parentGet === noop && optional) break;\n\t\n\t destination[scopeName] = function(locals) {\n\t return parentGet(scope, locals);\n\t };\n\t break;\n\t }\n\t });\n\t\n\t function recordChanges(key, currentValue, previousValue) {\n\t if (isFunction(destination.$onChanges) && currentValue !== previousValue) {\n\t // If we have not already scheduled the top level onChangesQueue handler then do so now\n\t if (!onChangesQueue) {\n\t scope.$$postDigest(flushOnChangesQueue);\n\t onChangesQueue = [];\n\t }\n\t // If we have not already queued a trigger of onChanges for this controller then do so now\n\t if (!changes) {\n\t changes = {};\n\t onChangesQueue.push(triggerOnChangesHook);\n\t }\n\t // If the has been a change on this property already then we need to reuse the previous value\n\t if (changes[key]) {\n\t previousValue = changes[key].previousValue;\n\t }\n\t // Store this change\n\t changes[key] = new SimpleChange(previousValue, currentValue);\n\t }\n\t }\n\t\n\t function triggerOnChangesHook() {\n\t destination.$onChanges(changes);\n\t // Now clear the changes so that we schedule onChanges when more changes arrive\n\t changes = undefined;\n\t }\n\t\n\t return {\n\t initialChanges: initialChanges,\n\t removeWatches: removeWatchCollection.length && function removeWatches() {\n\t for (var i = 0, ii = removeWatchCollection.length; i < ii; ++i) {\n\t removeWatchCollection[i]();\n\t }\n\t }\n\t };\n\t }\n\t }];\n\t}\n\t\n\tfunction SimpleChange(previous, current) {\n\t this.previousValue = previous;\n\t this.currentValue = current;\n\t}\n\tSimpleChange.prototype.isFirstChange = function() { return this.previousValue === _UNINITIALIZED_VALUE; };\n\t\n\t\n\tvar PREFIX_REGEXP = /^((?:x|data)[\\:\\-_])/i;\n\t/**\n\t * Converts all accepted directives format into proper directive name.\n\t * @param name Name to normalize\n\t */\n\tfunction directiveNormalize(name) {\n\t return camelCase(name.replace(PREFIX_REGEXP, ''));\n\t}\n\t\n\t/**\n\t * @ngdoc type\n\t * @name $compile.directive.Attributes\n\t *\n\t * @description\n\t * A shared object between directive compile / linking functions which contains normalized DOM\n\t * element attributes. The values reflect current binding state `{{ }}`. The normalization is\n\t * needed since all of these are treated as equivalent in Angular:\n\t *\n\t * ```\n\t * \n\t * ```\n\t */\n\t\n\t/**\n\t * @ngdoc property\n\t * @name $compile.directive.Attributes#$attr\n\t *\n\t * @description\n\t * A map of DOM element attribute names to the normalized name. This is\n\t * needed to do reverse lookup from normalized name back to actual name.\n\t */\n\t\n\t\n\t/**\n\t * @ngdoc method\n\t * @name $compile.directive.Attributes#$set\n\t * @kind function\n\t *\n\t * @description\n\t * Set DOM element attribute value.\n\t *\n\t *\n\t * @param {string} name Normalized element attribute name of the property to modify. The name is\n\t * reverse-translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n\t * property to the original name.\n\t * @param {string} value Value to set the attribute to. The value can be an interpolated string.\n\t */\n\t\n\t\n\t\n\t/**\n\t * Closure compiler type information\n\t */\n\t\n\tfunction nodesetLinkingFn(\n\t /* angular.Scope */ scope,\n\t /* NodeList */ nodeList,\n\t /* Element */ rootElement,\n\t /* function(Function) */ boundTranscludeFn\n\t) {}\n\t\n\tfunction directiveLinkingFn(\n\t /* nodesetLinkingFn */ nodesetLinkingFn,\n\t /* angular.Scope */ scope,\n\t /* Node */ node,\n\t /* Element */ rootElement,\n\t /* function(Function) */ boundTranscludeFn\n\t) {}\n\t\n\tfunction tokenDifference(str1, str2) {\n\t var values = '',\n\t tokens1 = str1.split(/\\s+/),\n\t tokens2 = str2.split(/\\s+/);\n\t\n\t outer:\n\t for (var i = 0; i < tokens1.length; i++) {\n\t var token = tokens1[i];\n\t for (var j = 0; j < tokens2.length; j++) {\n\t if (token == tokens2[j]) continue outer;\n\t }\n\t values += (values.length > 0 ? ' ' : '') + token;\n\t }\n\t return values;\n\t}\n\t\n\tfunction removeComments(jqNodes) {\n\t jqNodes = jqLite(jqNodes);\n\t var i = jqNodes.length;\n\t\n\t if (i <= 1) {\n\t return jqNodes;\n\t }\n\t\n\t while (i--) {\n\t var node = jqNodes[i];\n\t if (node.nodeType === NODE_TYPE_COMMENT) {\n\t splice.call(jqNodes, i, 1);\n\t }\n\t }\n\t return jqNodes;\n\t}\n\t\n\tvar $controllerMinErr = minErr('$controller');\n\t\n\t\n\tvar CNTRL_REG = /^(\\S+)(\\s+as\\s+([\\w$]+))?$/;\n\tfunction identifierForController(controller, ident) {\n\t if (ident && isString(ident)) return ident;\n\t if (isString(controller)) {\n\t var match = CNTRL_REG.exec(controller);\n\t if (match) return match[3];\n\t }\n\t}\n\t\n\t\n\t/**\n\t * @ngdoc provider\n\t * @name $controllerProvider\n\t * @description\n\t * The {@link ng.$controller $controller service} is used by Angular to create new\n\t * controllers.\n\t *\n\t * This provider allows controller registration via the\n\t * {@link ng.$controllerProvider#register register} method.\n\t */\n\tfunction $ControllerProvider() {\n\t var controllers = {},\n\t globals = false;\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $controllerProvider#has\n\t * @param {string} name Controller name to check.\n\t */\n\t this.has = function(name) {\n\t return controllers.hasOwnProperty(name);\n\t };\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $controllerProvider#register\n\t * @param {string|Object} name Controller name, or an object map of controllers where the keys are\n\t * the names and the values are the constructors.\n\t * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n\t * annotations in the array notation).\n\t */\n\t this.register = function(name, constructor) {\n\t assertNotHasOwnProperty(name, 'controller');\n\t if (isObject(name)) {\n\t extend(controllers, name);\n\t } else {\n\t controllers[name] = constructor;\n\t }\n\t };\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $controllerProvider#allowGlobals\n\t * @description If called, allows `$controller` to find controller constructors on `window`\n\t */\n\t this.allowGlobals = function() {\n\t globals = true;\n\t };\n\t\n\t\n\t this.$get = ['$injector', '$window', function($injector, $window) {\n\t\n\t /**\n\t * @ngdoc service\n\t * @name $controller\n\t * @requires $injector\n\t *\n\t * @param {Function|string} constructor If called with a function then it's considered to be the\n\t * controller constructor function. Otherwise it's considered to be a string which is used\n\t * to retrieve the controller constructor using the following steps:\n\t *\n\t * * check if a controller with given name is registered via `$controllerProvider`\n\t * * check if evaluating the string on the current scope returns a constructor\n\t * * if $controllerProvider#allowGlobals, check `window[constructor]` on the global\n\t * `window` object (not recommended)\n\t *\n\t * The string can use the `controller as property` syntax, where the controller instance is published\n\t * as the specified property on the `scope`; the `scope` must be injected into `locals` param for this\n\t * to work correctly.\n\t *\n\t * @param {Object} locals Injection locals for Controller.\n\t * @return {Object} Instance of given controller.\n\t *\n\t * @description\n\t * `$controller` service is responsible for instantiating controllers.\n\t *\n\t * It's just a simple call to {@link auto.$injector $injector}, but extracted into\n\t * a service, so that one can override this service with [BC version](https://gist.github.com/1649788).\n\t */\n\t return function $controller(expression, locals, later, ident) {\n\t // PRIVATE API:\n\t // param `later` --- indicates that the controller's constructor is invoked at a later time.\n\t // If true, $controller will allocate the object with the correct\n\t // prototype chain, but will not invoke the controller until a returned\n\t // callback is invoked.\n\t // param `ident` --- An optional label which overrides the label parsed from the controller\n\t // expression, if any.\n\t var instance, match, constructor, identifier;\n\t later = later === true;\n\t if (ident && isString(ident)) {\n\t identifier = ident;\n\t }\n\t\n\t if (isString(expression)) {\n\t match = expression.match(CNTRL_REG);\n\t if (!match) {\n\t throw $controllerMinErr('ctrlfmt',\n\t \"Badly formed controller string '{0}'. \" +\n\t \"Must match `__name__ as __id__` or `__name__`.\", expression);\n\t }\n\t constructor = match[1],\n\t identifier = identifier || match[3];\n\t expression = controllers.hasOwnProperty(constructor)\n\t ? controllers[constructor]\n\t : getter(locals.$scope, constructor, true) ||\n\t (globals ? getter($window, constructor, true) : undefined);\n\t\n\t assertArgFn(expression, constructor, true);\n\t }\n\t\n\t if (later) {\n\t // Instantiate controller later:\n\t // This machinery is used to create an instance of the object before calling the\n\t // controller's constructor itself.\n\t //\n\t // This allows properties to be added to the controller before the constructor is\n\t // invoked. Primarily, this is used for isolate scope bindings in $compile.\n\t //\n\t // This feature is not intended for use by applications, and is thus not documented\n\t // publicly.\n\t // Object creation: http://jsperf.com/create-constructor/2\n\t var controllerPrototype = (isArray(expression) ?\n\t expression[expression.length - 1] : expression).prototype;\n\t instance = Object.create(controllerPrototype || null);\n\t\n\t if (identifier) {\n\t addIdentifier(locals, identifier, instance, constructor || expression.name);\n\t }\n\t\n\t var instantiate;\n\t return instantiate = extend(function $controllerInit() {\n\t var result = $injector.invoke(expression, instance, locals, constructor);\n\t if (result !== instance && (isObject(result) || isFunction(result))) {\n\t instance = result;\n\t if (identifier) {\n\t // If result changed, re-assign controllerAs value to scope.\n\t addIdentifier(locals, identifier, instance, constructor || expression.name);\n\t }\n\t }\n\t return instance;\n\t }, {\n\t instance: instance,\n\t identifier: identifier\n\t });\n\t }\n\t\n\t instance = $injector.instantiate(expression, locals, constructor);\n\t\n\t if (identifier) {\n\t addIdentifier(locals, identifier, instance, constructor || expression.name);\n\t }\n\t\n\t return instance;\n\t };\n\t\n\t function addIdentifier(locals, identifier, instance, name) {\n\t if (!(locals && isObject(locals.$scope))) {\n\t throw minErr('$controller')('noscp',\n\t \"Cannot export controller '{0}' as '{1}'! No $scope object provided via `locals`.\",\n\t name, identifier);\n\t }\n\t\n\t locals.$scope[identifier] = instance;\n\t }\n\t }];\n\t}\n\t\n\t/**\n\t * @ngdoc service\n\t * @name $document\n\t * @requires $window\n\t *\n\t * @description\n\t * A {@link angular.element jQuery or jqLite} wrapper for the browser's `window.document` object.\n\t *\n\t * @example\n\t \n\t \n\t
\n\t

$document title:

\n\t

window.document title:

\n\t
\n\t
\n\t \n\t angular.module('documentExample', [])\n\t .controller('ExampleController', ['$scope', '$document', function($scope, $document) {\n\t $scope.title = $document[0].title;\n\t $scope.windowTitle = angular.element(window.document)[0].title;\n\t }]);\n\t \n\t
\n\t */\n\tfunction $DocumentProvider() {\n\t this.$get = ['$window', function(window) {\n\t return jqLite(window.document);\n\t }];\n\t}\n\t\n\t/**\n\t * @ngdoc service\n\t * @name $exceptionHandler\n\t * @requires ng.$log\n\t *\n\t * @description\n\t * Any uncaught exception in angular expressions is delegated to this service.\n\t * The default implementation simply delegates to `$log.error` which logs it into\n\t * the browser console.\n\t *\n\t * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n\t * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n\t *\n\t * ## Example:\n\t *\n\t * The example below will overwrite the default `$exceptionHandler` in order to (a) log uncaught\n\t * errors to the backend for later inspection by the developers and (b) to use `$log.warn()` instead\n\t * of `$log.error()`.\n\t *\n\t * ```js\n\t * angular.\n\t * module('exceptionOverwrite', []).\n\t * factory('$exceptionHandler', ['$log', 'logErrorsToBackend', function($log, logErrorsToBackend) {\n\t * return function myExceptionHandler(exception, cause) {\n\t * logErrorsToBackend(exception, cause);\n\t * $log.warn(exception, cause);\n\t * };\n\t * }]);\n\t * ```\n\t *\n\t *
\n\t * Note, that code executed in event-listeners (even those registered using jqLite's `on`/`bind`\n\t * methods) does not delegate exceptions to the {@link ng.$exceptionHandler $exceptionHandler}\n\t * (unless executed during a digest).\n\t *\n\t * If you wish, you can manually delegate exceptions, e.g.\n\t * `try { ... } catch(e) { $exceptionHandler(e); }`\n\t *\n\t * @param {Error} exception Exception associated with the error.\n\t * @param {string=} cause Optional information about the context in which\n\t * the error was thrown.\n\t *\n\t */\n\tfunction $ExceptionHandlerProvider() {\n\t this.$get = ['$log', function($log) {\n\t return function(exception, cause) {\n\t $log.error.apply($log, arguments);\n\t };\n\t }];\n\t}\n\t\n\tvar $$ForceReflowProvider = function() {\n\t this.$get = ['$document', function($document) {\n\t return function(domNode) {\n\t //the line below will force the browser to perform a repaint so\n\t //that all the animated elements within the animation frame will\n\t //be properly updated and drawn on screen. This is required to\n\t //ensure that the preparation animation is properly flushed so that\n\t //the active state picks up from there. DO NOT REMOVE THIS LINE.\n\t //DO NOT OPTIMIZE THIS LINE. THE MINIFIER WILL REMOVE IT OTHERWISE WHICH\n\t //WILL RESULT IN AN UNPREDICTABLE BUG THAT IS VERY HARD TO TRACK DOWN AND\n\t //WILL TAKE YEARS AWAY FROM YOUR LIFE.\n\t if (domNode) {\n\t if (!domNode.nodeType && domNode instanceof jqLite) {\n\t domNode = domNode[0];\n\t }\n\t } else {\n\t domNode = $document[0].body;\n\t }\n\t return domNode.offsetWidth + 1;\n\t };\n\t }];\n\t};\n\t\n\tvar APPLICATION_JSON = 'application/json';\n\tvar CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': APPLICATION_JSON + ';charset=utf-8'};\n\tvar JSON_START = /^\\[|^\\{(?!\\{)/;\n\tvar JSON_ENDS = {\n\t '[': /]$/,\n\t '{': /}$/\n\t};\n\tvar JSON_PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\tvar $httpMinErr = minErr('$http');\n\tvar $httpMinErrLegacyFn = function(method) {\n\t return function() {\n\t throw $httpMinErr('legacy', 'The method `{0}` on the promise returned from `$http` has been disabled.', method);\n\t };\n\t};\n\t\n\tfunction serializeValue(v) {\n\t if (isObject(v)) {\n\t return isDate(v) ? v.toISOString() : toJson(v);\n\t }\n\t return v;\n\t}\n\t\n\t\n\tfunction $HttpParamSerializerProvider() {\n\t /**\n\t * @ngdoc service\n\t * @name $httpParamSerializer\n\t * @description\n\t *\n\t * Default {@link $http `$http`} params serializer that converts objects to strings\n\t * according to the following rules:\n\t *\n\t * * `{'foo': 'bar'}` results in `foo=bar`\n\t * * `{'foo': Date.now()}` results in `foo=2015-04-01T09%3A50%3A49.262Z` (`toISOString()` and encoded representation of a Date object)\n\t * * `{'foo': ['bar', 'baz']}` results in `foo=bar&foo=baz` (repeated key for each array element)\n\t * * `{'foo': {'bar':'baz'}}` results in `foo=%7B%22bar%22%3A%22baz%22%7D` (stringified and encoded representation of an object)\n\t *\n\t * Note that serializer will sort the request parameters alphabetically.\n\t * */\n\t\n\t this.$get = function() {\n\t return function ngParamSerializer(params) {\n\t if (!params) return '';\n\t var parts = [];\n\t forEachSorted(params, function(value, key) {\n\t if (value === null || isUndefined(value)) return;\n\t if (isArray(value)) {\n\t forEach(value, function(v) {\n\t parts.push(encodeUriQuery(key) + '=' + encodeUriQuery(serializeValue(v)));\n\t });\n\t } else {\n\t parts.push(encodeUriQuery(key) + '=' + encodeUriQuery(serializeValue(value)));\n\t }\n\t });\n\t\n\t return parts.join('&');\n\t };\n\t };\n\t}\n\t\n\tfunction $HttpParamSerializerJQLikeProvider() {\n\t /**\n\t * @ngdoc service\n\t * @name $httpParamSerializerJQLike\n\t * @description\n\t *\n\t * Alternative {@link $http `$http`} params serializer that follows\n\t * jQuery's [`param()`](http://api.jquery.com/jquery.param/) method logic.\n\t * The serializer will also sort the params alphabetically.\n\t *\n\t * To use it for serializing `$http` request parameters, set it as the `paramSerializer` property:\n\t *\n\t * ```js\n\t * $http({\n\t * url: myUrl,\n\t * method: 'GET',\n\t * params: myParams,\n\t * paramSerializer: '$httpParamSerializerJQLike'\n\t * });\n\t * ```\n\t *\n\t * It is also possible to set it as the default `paramSerializer` in the\n\t * {@link $httpProvider#defaults `$httpProvider`}.\n\t *\n\t * Additionally, you can inject the serializer and use it explicitly, for example to serialize\n\t * form data for submission:\n\t *\n\t * ```js\n\t * .controller(function($http, $httpParamSerializerJQLike) {\n\t * //...\n\t *\n\t * $http({\n\t * url: myUrl,\n\t * method: 'POST',\n\t * data: $httpParamSerializerJQLike(myData),\n\t * headers: {\n\t * 'Content-Type': 'application/x-www-form-urlencoded'\n\t * }\n\t * });\n\t *\n\t * });\n\t * ```\n\t *\n\t * */\n\t this.$get = function() {\n\t return function jQueryLikeParamSerializer(params) {\n\t if (!params) return '';\n\t var parts = [];\n\t serialize(params, '', true);\n\t return parts.join('&');\n\t\n\t function serialize(toSerialize, prefix, topLevel) {\n\t if (toSerialize === null || isUndefined(toSerialize)) return;\n\t if (isArray(toSerialize)) {\n\t forEach(toSerialize, function(value, index) {\n\t serialize(value, prefix + '[' + (isObject(value) ? index : '') + ']');\n\t });\n\t } else if (isObject(toSerialize) && !isDate(toSerialize)) {\n\t forEachSorted(toSerialize, function(value, key) {\n\t serialize(value, prefix +\n\t (topLevel ? '' : '[') +\n\t key +\n\t (topLevel ? '' : ']'));\n\t });\n\t } else {\n\t parts.push(encodeUriQuery(prefix) + '=' + encodeUriQuery(serializeValue(toSerialize)));\n\t }\n\t }\n\t };\n\t };\n\t}\n\t\n\tfunction defaultHttpResponseTransform(data, headers) {\n\t if (isString(data)) {\n\t // Strip json vulnerability protection prefix and trim whitespace\n\t var tempData = data.replace(JSON_PROTECTION_PREFIX, '').trim();\n\t\n\t if (tempData) {\n\t var contentType = headers('Content-Type');\n\t if ((contentType && (contentType.indexOf(APPLICATION_JSON) === 0)) || isJsonLike(tempData)) {\n\t data = fromJson(tempData);\n\t }\n\t }\n\t }\n\t\n\t return data;\n\t}\n\t\n\tfunction isJsonLike(str) {\n\t var jsonStart = str.match(JSON_START);\n\t return jsonStart && JSON_ENDS[jsonStart[0]].test(str);\n\t}\n\t\n\t/**\n\t * Parse headers into key value object\n\t *\n\t * @param {string} headers Raw headers as a string\n\t * @returns {Object} Parsed headers as key value object\n\t */\n\tfunction parseHeaders(headers) {\n\t var parsed = createMap(), i;\n\t\n\t function fillInParsed(key, val) {\n\t if (key) {\n\t parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val;\n\t }\n\t }\n\t\n\t if (isString(headers)) {\n\t forEach(headers.split('\\n'), function(line) {\n\t i = line.indexOf(':');\n\t fillInParsed(lowercase(trim(line.substr(0, i))), trim(line.substr(i + 1)));\n\t });\n\t } else if (isObject(headers)) {\n\t forEach(headers, function(headerVal, headerKey) {\n\t fillInParsed(lowercase(headerKey), trim(headerVal));\n\t });\n\t }\n\t\n\t return parsed;\n\t}\n\t\n\t\n\t/**\n\t * Returns a function that provides access to parsed headers.\n\t *\n\t * Headers are lazy parsed when first requested.\n\t * @see parseHeaders\n\t *\n\t * @param {(string|Object)} headers Headers to provide access to.\n\t * @returns {function(string=)} Returns a getter function which if called with:\n\t *\n\t * - if called with single an argument returns a single header value or null\n\t * - if called with no arguments returns an object containing all headers.\n\t */\n\tfunction headersGetter(headers) {\n\t var headersObj;\n\t\n\t return function(name) {\n\t if (!headersObj) headersObj = parseHeaders(headers);\n\t\n\t if (name) {\n\t var value = headersObj[lowercase(name)];\n\t if (value === void 0) {\n\t value = null;\n\t }\n\t return value;\n\t }\n\t\n\t return headersObj;\n\t };\n\t}\n\t\n\t\n\t/**\n\t * Chain all given functions\n\t *\n\t * This function is used for both request and response transforming\n\t *\n\t * @param {*} data Data to transform.\n\t * @param {function(string=)} headers HTTP headers getter fn.\n\t * @param {number} status HTTP status code of the response.\n\t * @param {(Function|Array.)} fns Function or an array of functions.\n\t * @returns {*} Transformed data.\n\t */\n\tfunction transformData(data, headers, status, fns) {\n\t if (isFunction(fns)) {\n\t return fns(data, headers, status);\n\t }\n\t\n\t forEach(fns, function(fn) {\n\t data = fn(data, headers, status);\n\t });\n\t\n\t return data;\n\t}\n\t\n\t\n\tfunction isSuccess(status) {\n\t return 200 <= status && status < 300;\n\t}\n\t\n\t\n\t/**\n\t * @ngdoc provider\n\t * @name $httpProvider\n\t * @description\n\t * Use `$httpProvider` to change the default behavior of the {@link ng.$http $http} service.\n\t * */\n\tfunction $HttpProvider() {\n\t /**\n\t * @ngdoc property\n\t * @name $httpProvider#defaults\n\t * @description\n\t *\n\t * Object containing default values for all {@link ng.$http $http} requests.\n\t *\n\t * - **`defaults.cache`** - {boolean|Object} - A boolean value or object created with\n\t * {@link ng.$cacheFactory `$cacheFactory`} to enable or disable caching of HTTP responses\n\t * by default. See {@link $http#caching $http Caching} for more information.\n\t *\n\t * - **`defaults.xsrfCookieName`** - {string} - Name of cookie containing the XSRF token.\n\t * Defaults value is `'XSRF-TOKEN'`.\n\t *\n\t * - **`defaults.xsrfHeaderName`** - {string} - Name of HTTP header to populate with the\n\t * XSRF token. Defaults value is `'X-XSRF-TOKEN'`.\n\t *\n\t * - **`defaults.headers`** - {Object} - Default headers for all $http requests.\n\t * Refer to {@link ng.$http#setting-http-headers $http} for documentation on\n\t * setting default headers.\n\t * - **`defaults.headers.common`**\n\t * - **`defaults.headers.post`**\n\t * - **`defaults.headers.put`**\n\t * - **`defaults.headers.patch`**\n\t *\n\t *\n\t * - **`defaults.paramSerializer`** - `{string|function(Object):string}` - A function\n\t * used to the prepare string representation of request parameters (specified as an object).\n\t * If specified as string, it is interpreted as a function registered with the {@link auto.$injector $injector}.\n\t * Defaults to {@link ng.$httpParamSerializer $httpParamSerializer}.\n\t *\n\t **/\n\t var defaults = this.defaults = {\n\t // transform incoming response data\n\t transformResponse: [defaultHttpResponseTransform],\n\t\n\t // transform outgoing request data\n\t transformRequest: [function(d) {\n\t return isObject(d) && !isFile(d) && !isBlob(d) && !isFormData(d) ? toJson(d) : d;\n\t }],\n\t\n\t // default headers\n\t headers: {\n\t common: {\n\t 'Accept': 'application/json, text/plain, */*'\n\t },\n\t post: shallowCopy(CONTENT_TYPE_APPLICATION_JSON),\n\t put: shallowCopy(CONTENT_TYPE_APPLICATION_JSON),\n\t patch: shallowCopy(CONTENT_TYPE_APPLICATION_JSON)\n\t },\n\t\n\t xsrfCookieName: 'XSRF-TOKEN',\n\t xsrfHeaderName: 'X-XSRF-TOKEN',\n\t\n\t paramSerializer: '$httpParamSerializer'\n\t };\n\t\n\t var useApplyAsync = false;\n\t /**\n\t * @ngdoc method\n\t * @name $httpProvider#useApplyAsync\n\t * @description\n\t *\n\t * Configure $http service to combine processing of multiple http responses received at around\n\t * the same time via {@link ng.$rootScope.Scope#$applyAsync $rootScope.$applyAsync}. This can result in\n\t * significant performance improvement for bigger applications that make many HTTP requests\n\t * concurrently (common during application bootstrap).\n\t *\n\t * Defaults to false. If no value is specified, returns the current configured value.\n\t *\n\t * @param {boolean=} value If true, when requests are loaded, they will schedule a deferred\n\t * \"apply\" on the next tick, giving time for subsequent requests in a roughly ~10ms window\n\t * to load and share the same digest cycle.\n\t *\n\t * @returns {boolean|Object} If a value is specified, returns the $httpProvider for chaining.\n\t * otherwise, returns the current configured value.\n\t **/\n\t this.useApplyAsync = function(value) {\n\t if (isDefined(value)) {\n\t useApplyAsync = !!value;\n\t return this;\n\t }\n\t return useApplyAsync;\n\t };\n\t\n\t var useLegacyPromise = true;\n\t /**\n\t * @ngdoc method\n\t * @name $httpProvider#useLegacyPromiseExtensions\n\t * @description\n\t *\n\t * Configure `$http` service to return promises without the shorthand methods `success` and `error`.\n\t * This should be used to make sure that applications work without these methods.\n\t *\n\t * Defaults to true. If no value is specified, returns the current configured value.\n\t *\n\t * @param {boolean=} value If true, `$http` will return a promise with the deprecated legacy `success` and `error` methods.\n\t *\n\t * @returns {boolean|Object} If a value is specified, returns the $httpProvider for chaining.\n\t * otherwise, returns the current configured value.\n\t **/\n\t this.useLegacyPromiseExtensions = function(value) {\n\t if (isDefined(value)) {\n\t useLegacyPromise = !!value;\n\t return this;\n\t }\n\t return useLegacyPromise;\n\t };\n\t\n\t /**\n\t * @ngdoc property\n\t * @name $httpProvider#interceptors\n\t * @description\n\t *\n\t * Array containing service factories for all synchronous or asynchronous {@link ng.$http $http}\n\t * pre-processing of request or postprocessing of responses.\n\t *\n\t * These service factories are ordered by request, i.e. they are applied in the same order as the\n\t * array, on request, but reverse order, on response.\n\t *\n\t * {@link ng.$http#interceptors Interceptors detailed info}\n\t **/\n\t var interceptorFactories = this.interceptors = [];\n\t\n\t this.$get = ['$httpBackend', '$$cookieReader', '$cacheFactory', '$rootScope', '$q', '$injector',\n\t function($httpBackend, $$cookieReader, $cacheFactory, $rootScope, $q, $injector) {\n\t\n\t var defaultCache = $cacheFactory('$http');\n\t\n\t /**\n\t * Make sure that default param serializer is exposed as a function\n\t */\n\t defaults.paramSerializer = isString(defaults.paramSerializer) ?\n\t $injector.get(defaults.paramSerializer) : defaults.paramSerializer;\n\t\n\t /**\n\t * Interceptors stored in reverse order. Inner interceptors before outer interceptors.\n\t * The reversal is needed so that we can build up the interception chain around the\n\t * server request.\n\t */\n\t var reversedInterceptors = [];\n\t\n\t forEach(interceptorFactories, function(interceptorFactory) {\n\t reversedInterceptors.unshift(isString(interceptorFactory)\n\t ? $injector.get(interceptorFactory) : $injector.invoke(interceptorFactory));\n\t });\n\t\n\t /**\n\t * @ngdoc service\n\t * @kind function\n\t * @name $http\n\t * @requires ng.$httpBackend\n\t * @requires $cacheFactory\n\t * @requires $rootScope\n\t * @requires $q\n\t * @requires $injector\n\t *\n\t * @description\n\t * The `$http` service is a core Angular service that facilitates communication with the remote\n\t * HTTP servers via the browser's [XMLHttpRequest](https://developer.mozilla.org/en/xmlhttprequest)\n\t * object or via [JSONP](http://en.wikipedia.org/wiki/JSONP).\n\t *\n\t * For unit testing applications that use `$http` service, see\n\t * {@link ngMock.$httpBackend $httpBackend mock}.\n\t *\n\t * For a higher level of abstraction, please check out the {@link ngResource.$resource\n\t * $resource} service.\n\t *\n\t * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n\t * the $q service. While for simple usage patterns this doesn't matter much, for advanced usage\n\t * it is important to familiarize yourself with these APIs and the guarantees they provide.\n\t *\n\t *\n\t * ## General usage\n\t * The `$http` service is a function which takes a single argument — a {@link $http#usage configuration object} —\n\t * that is used to generate an HTTP request and returns a {@link ng.$q promise}.\n\t *\n\t * ```js\n\t * // Simple GET request example:\n\t * $http({\n\t * method: 'GET',\n\t * url: '/someUrl'\n\t * }).then(function successCallback(response) {\n\t * // this callback will be called asynchronously\n\t * // when the response is available\n\t * }, function errorCallback(response) {\n\t * // called asynchronously if an error occurs\n\t * // or server returns response with an error status.\n\t * });\n\t * ```\n\t *\n\t * The response object has these properties:\n\t *\n\t * - **data** – `{string|Object}` – The response body transformed with the transform\n\t * functions.\n\t * - **status** – `{number}` – HTTP status code of the response.\n\t * - **headers** – `{function([headerName])}` – Header getter function.\n\t * - **config** – `{Object}` – The configuration object that was used to generate the request.\n\t * - **statusText** – `{string}` – HTTP status text of the response.\n\t *\n\t * A response status code between 200 and 299 is considered a success status and will result in\n\t * the success callback being called. Any response status code outside of that range is\n\t * considered an error status and will result in the error callback being called.\n\t * Also, status codes less than -1 are normalized to zero. -1 usually means the request was\n\t * aborted, e.g. using a `config.timeout`.\n\t * Note that if the response is a redirect, XMLHttpRequest will transparently follow it, meaning\n\t * that the outcome (success or error) will be determined by the final response status code.\n\t *\n\t *\n\t * ## Shortcut methods\n\t *\n\t * Shortcut methods are also available. All shortcut methods require passing in the URL, and\n\t * request data must be passed in for POST/PUT requests. An optional config can be passed as the\n\t * last argument.\n\t *\n\t * ```js\n\t * $http.get('/someUrl', config).then(successCallback, errorCallback);\n\t * $http.post('/someUrl', data, config).then(successCallback, errorCallback);\n\t * ```\n\t *\n\t * Complete list of shortcut methods:\n\t *\n\t * - {@link ng.$http#get $http.get}\n\t * - {@link ng.$http#head $http.head}\n\t * - {@link ng.$http#post $http.post}\n\t * - {@link ng.$http#put $http.put}\n\t * - {@link ng.$http#delete $http.delete}\n\t * - {@link ng.$http#jsonp $http.jsonp}\n\t * - {@link ng.$http#patch $http.patch}\n\t *\n\t *\n\t * ## Writing Unit Tests that use $http\n\t * When unit testing (using {@link ngMock ngMock}), it is necessary to call\n\t * {@link ngMock.$httpBackend#flush $httpBackend.flush()} to flush each pending\n\t * request using trained responses.\n\t *\n\t * ```\n\t * $httpBackend.expectGET(...);\n\t * $http.get(...);\n\t * $httpBackend.flush();\n\t * ```\n\t *\n\t * ## Deprecation Notice\n\t *
\n\t * The `$http` legacy promise methods `success` and `error` have been deprecated.\n\t * Use the standard `then` method instead.\n\t * If {@link $httpProvider#useLegacyPromiseExtensions `$httpProvider.useLegacyPromiseExtensions`} is set to\n\t * `false` then these methods will throw {@link $http:legacy `$http/legacy`} error.\n\t *
\n\t *\n\t * ## Setting HTTP Headers\n\t *\n\t * The $http service will automatically add certain HTTP headers to all requests. These defaults\n\t * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n\t * object, which currently contains this default configuration:\n\t *\n\t * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n\t * - `Accept: application/json, text/plain, * / *`\n\t * - `$httpProvider.defaults.headers.post`: (header defaults for POST requests)\n\t * - `Content-Type: application/json`\n\t * - `$httpProvider.defaults.headers.put` (header defaults for PUT requests)\n\t * - `Content-Type: application/json`\n\t *\n\t * To add or overwrite these defaults, simply add or remove a property from these configuration\n\t * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n\t * with the lowercased HTTP method name as the key, e.g.\n\t * `$httpProvider.defaults.headers.get = { 'My-Header' : 'value' }`.\n\t *\n\t * The defaults can also be set at runtime via the `$http.defaults` object in the same\n\t * fashion. For example:\n\t *\n\t * ```\n\t * module.run(function($http) {\n\t * $http.defaults.headers.common.Authorization = 'Basic YmVlcDpib29w';\n\t * });\n\t * ```\n\t *\n\t * In addition, you can supply a `headers` property in the config object passed when\n\t * calling `$http(config)`, which overrides the defaults without changing them globally.\n\t *\n\t * To explicitly remove a header automatically added via $httpProvider.defaults.headers on a per request basis,\n\t * Use the `headers` property, setting the desired header to `undefined`. For example:\n\t *\n\t * ```js\n\t * var req = {\n\t * method: 'POST',\n\t * url: 'http://example.com',\n\t * headers: {\n\t * 'Content-Type': undefined\n\t * },\n\t * data: { test: 'test' }\n\t * }\n\t *\n\t * $http(req).then(function(){...}, function(){...});\n\t * ```\n\t *\n\t * ## Transforming Requests and Responses\n\t *\n\t * Both requests and responses can be transformed using transformation functions: `transformRequest`\n\t * and `transformResponse`. These properties can be a single function that returns\n\t * the transformed value (`function(data, headersGetter, status)`) or an array of such transformation functions,\n\t * which allows you to `push` or `unshift` a new transformation function into the transformation chain.\n\t *\n\t *
\n\t * **Note:** Angular does not make a copy of the `data` parameter before it is passed into the `transformRequest` pipeline.\n\t * That means changes to the properties of `data` are not local to the transform function (since Javascript passes objects by reference).\n\t * For example, when calling `$http.get(url, $scope.myObject)`, modifications to the object's properties in a transformRequest\n\t * function will be reflected on the scope and in any templates where the object is data-bound.\n\t * To prevent this, transform functions should have no side-effects.\n\t * If you need to modify properties, it is recommended to make a copy of the data, or create new object to return.\n\t *
\n\t *\n\t * ### Default Transformations\n\t *\n\t * The `$httpProvider` provider and `$http` service expose `defaults.transformRequest` and\n\t * `defaults.transformResponse` properties. If a request does not provide its own transformations\n\t * then these will be applied.\n\t *\n\t * You can augment or replace the default transformations by modifying these properties by adding to or\n\t * replacing the array.\n\t *\n\t * Angular provides the following default transformations:\n\t *\n\t * Request transformations (`$httpProvider.defaults.transformRequest` and `$http.defaults.transformRequest`):\n\t *\n\t * - If the `data` property of the request configuration object contains an object, serialize it\n\t * into JSON format.\n\t *\n\t * Response transformations (`$httpProvider.defaults.transformResponse` and `$http.defaults.transformResponse`):\n\t *\n\t * - If XSRF prefix is detected, strip it (see Security Considerations section below).\n\t * - If JSON response is detected, deserialize it using a JSON parser.\n\t *\n\t *\n\t * ### Overriding the Default Transformations Per Request\n\t *\n\t * If you wish to override the request/response transformations only for a single request then provide\n\t * `transformRequest` and/or `transformResponse` properties on the configuration object passed\n\t * into `$http`.\n\t *\n\t * Note that if you provide these properties on the config object the default transformations will be\n\t * overwritten. If you wish to augment the default transformations then you must include them in your\n\t * local transformation array.\n\t *\n\t * The following code demonstrates adding a new response transformation to be run after the default response\n\t * transformations have been run.\n\t *\n\t * ```js\n\t * function appendTransform(defaults, transform) {\n\t *\n\t * // We can't guarantee that the default transformation is an array\n\t * defaults = angular.isArray(defaults) ? defaults : [defaults];\n\t *\n\t * // Append the new transformation to the defaults\n\t * return defaults.concat(transform);\n\t * }\n\t *\n\t * $http({\n\t * url: '...',\n\t * method: 'GET',\n\t * transformResponse: appendTransform($http.defaults.transformResponse, function(value) {\n\t * return doTransform(value);\n\t * })\n\t * });\n\t * ```\n\t *\n\t *\n\t * ## Caching\n\t *\n\t * {@link ng.$http `$http`} responses are not cached by default. To enable caching, you must\n\t * set the config.cache value or the default cache value to TRUE or to a cache object (created\n\t * with {@link ng.$cacheFactory `$cacheFactory`}). If defined, the value of config.cache takes\n\t * precedence over the default cache value.\n\t *\n\t * In order to:\n\t * * cache all responses - set the default cache value to TRUE or to a cache object\n\t * * cache a specific response - set config.cache value to TRUE or to a cache object\n\t *\n\t * If caching is enabled, but neither the default cache nor config.cache are set to a cache object,\n\t * then the default `$cacheFactory(\"$http\")` object is used.\n\t *\n\t * The default cache value can be set by updating the\n\t * {@link ng.$http#defaults `$http.defaults.cache`} property or the\n\t * {@link $httpProvider#defaults `$httpProvider.defaults.cache`} property.\n\t *\n\t * When caching is enabled, {@link ng.$http `$http`} stores the response from the server using\n\t * the relevant cache object. The next time the same request is made, the response is returned\n\t * from the cache without sending a request to the server.\n\t *\n\t * Take note that:\n\t *\n\t * * Only GET and JSONP requests are cached.\n\t * * The cache key is the request URL including search parameters; headers are not considered.\n\t * * Cached responses are returned asynchronously, in the same way as responses from the server.\n\t * * If multiple identical requests are made using the same cache, which is not yet populated,\n\t * one request will be made to the server and remaining requests will return the same response.\n\t * * A cache-control header on the response does not affect if or how responses are cached.\n\t *\n\t *\n\t * ## Interceptors\n\t *\n\t * Before you start creating interceptors, be sure to understand the\n\t * {@link ng.$q $q and deferred/promise APIs}.\n\t *\n\t * For purposes of global error handling, authentication, or any kind of synchronous or\n\t * asynchronous pre-processing of request or postprocessing of responses, it is desirable to be\n\t * able to intercept requests before they are handed to the server and\n\t * responses before they are handed over to the application code that\n\t * initiated these requests. The interceptors leverage the {@link ng.$q\n\t * promise APIs} to fulfill this need for both synchronous and asynchronous pre-processing.\n\t *\n\t * The interceptors are service factories that are registered with the `$httpProvider` by\n\t * adding them to the `$httpProvider.interceptors` array. The factory is called and\n\t * injected with dependencies (if specified) and returns the interceptor.\n\t *\n\t * There are two kinds of interceptors (and two kinds of rejection interceptors):\n\t *\n\t * * `request`: interceptors get called with a http {@link $http#usage config} object. The function is free to\n\t * modify the `config` object or create a new one. The function needs to return the `config`\n\t * object directly, or a promise containing the `config` or a new `config` object.\n\t * * `requestError`: interceptor gets called when a previous interceptor threw an error or\n\t * resolved with a rejection.\n\t * * `response`: interceptors get called with http `response` object. The function is free to\n\t * modify the `response` object or create a new one. The function needs to return the `response`\n\t * object directly, or as a promise containing the `response` or a new `response` object.\n\t * * `responseError`: interceptor gets called when a previous interceptor threw an error or\n\t * resolved with a rejection.\n\t *\n\t *\n\t * ```js\n\t * // register the interceptor as a service\n\t * $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n\t * return {\n\t * // optional method\n\t * 'request': function(config) {\n\t * // do something on success\n\t * return config;\n\t * },\n\t *\n\t * // optional method\n\t * 'requestError': function(rejection) {\n\t * // do something on error\n\t * if (canRecover(rejection)) {\n\t * return responseOrNewPromise\n\t * }\n\t * return $q.reject(rejection);\n\t * },\n\t *\n\t *\n\t *\n\t * // optional method\n\t * 'response': function(response) {\n\t * // do something on success\n\t * return response;\n\t * },\n\t *\n\t * // optional method\n\t * 'responseError': function(rejection) {\n\t * // do something on error\n\t * if (canRecover(rejection)) {\n\t * return responseOrNewPromise\n\t * }\n\t * return $q.reject(rejection);\n\t * }\n\t * };\n\t * });\n\t *\n\t * $httpProvider.interceptors.push('myHttpInterceptor');\n\t *\n\t *\n\t * // alternatively, register the interceptor via an anonymous factory\n\t * $httpProvider.interceptors.push(function($q, dependency1, dependency2) {\n\t * return {\n\t * 'request': function(config) {\n\t * // same as above\n\t * },\n\t *\n\t * 'response': function(response) {\n\t * // same as above\n\t * }\n\t * };\n\t * });\n\t * ```\n\t *\n\t * ## Security Considerations\n\t *\n\t * When designing web applications, consider security threats from:\n\t *\n\t * - [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx)\n\t * - [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery)\n\t *\n\t * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n\t * pre-configured with strategies that address these issues, but for this to work backend server\n\t * cooperation is required.\n\t *\n\t * ### JSON Vulnerability Protection\n\t *\n\t * A [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx)\n\t * allows third party website to turn your JSON resource URL into\n\t * [JSONP](http://en.wikipedia.org/wiki/JSONP) request under some conditions. To\n\t * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n\t * Angular will automatically strip the prefix before processing it as JSON.\n\t *\n\t * For example if your server needs to return:\n\t * ```js\n\t * ['one','two']\n\t * ```\n\t *\n\t * which is vulnerable to attack, your server can return:\n\t * ```js\n\t * )]}',\n\t * ['one','two']\n\t * ```\n\t *\n\t * Angular will strip the prefix, before processing the JSON.\n\t *\n\t *\n\t * ### Cross Site Request Forgery (XSRF) Protection\n\t *\n\t * [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) is an attack technique by\n\t * which the attacker can trick an authenticated user into unknowingly executing actions on your\n\t * website. Angular provides a mechanism to counter XSRF. When performing XHR requests, the\n\t * $http service reads a token from a cookie (by default, `XSRF-TOKEN`) and sets it as an HTTP\n\t * header (`X-XSRF-TOKEN`). Since only JavaScript that runs on your domain could read the\n\t * cookie, your server can be assured that the XHR came from JavaScript running on your domain.\n\t * The header will not be set for cross-domain requests.\n\t *\n\t * To take advantage of this, your server needs to set a token in a JavaScript readable session\n\t * cookie called `XSRF-TOKEN` on the first HTTP GET request. On subsequent XHR requests the\n\t * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n\t * that only JavaScript running on your domain could have sent the request. The token must be\n\t * unique for each user and must be verifiable by the server (to prevent the JavaScript from\n\t * making up its own tokens). We recommend that the token is a digest of your site's\n\t * authentication cookie with a [salt](https://en.wikipedia.org/wiki/Salt_(cryptography))\n\t * for added security.\n\t *\n\t * The name of the headers can be specified using the xsrfHeaderName and xsrfCookieName\n\t * properties of either $httpProvider.defaults at config-time, $http.defaults at run-time,\n\t * or the per-request config object.\n\t *\n\t * In order to prevent collisions in environments where multiple Angular apps share the\n\t * same domain or subdomain, we recommend that each application uses unique cookie name.\n\t *\n\t * @param {object} config Object describing the request to be made and how it should be\n\t * processed. The object has following properties:\n\t *\n\t * - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n\t * - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n\t * - **params** – `{Object.}` – Map of strings or objects which will be serialized\n\t * with the `paramSerializer` and appended as GET parameters.\n\t * - **data** – `{string|Object}` – Data to be sent as the request message data.\n\t * - **headers** – `{Object}` – Map of strings or functions which return strings representing\n\t * HTTP headers to send to the server. If the return value of a function is null, the\n\t * header will not be sent. Functions accept a config object as an argument.\n\t * - **eventHandlers** - `{Object}` - Event listeners to be bound to the XMLHttpRequest object.\n\t * To bind events to the XMLHttpRequest upload object, use `uploadEventHandlers`.\n\t * The handler will be called in the context of a `$apply` block.\n\t * - **uploadEventHandlers** - `{Object}` - Event listeners to be bound to the XMLHttpRequest upload\n\t * object. To bind events to the XMLHttpRequest object, use `eventHandlers`.\n\t * The handler will be called in the context of a `$apply` block.\n\t * - **xsrfHeaderName** – `{string}` – Name of HTTP header to populate with the XSRF token.\n\t * - **xsrfCookieName** – `{string}` – Name of cookie containing the XSRF token.\n\t * - **transformRequest** –\n\t * `{function(data, headersGetter)|Array.}` –\n\t * transform function or an array of such functions. The transform function takes the http\n\t * request body and headers and returns its transformed (typically serialized) version.\n\t * See {@link ng.$http#overriding-the-default-transformations-per-request\n\t * Overriding the Default Transformations}\n\t * - **transformResponse** –\n\t * `{function(data, headersGetter, status)|Array.}` –\n\t * transform function or an array of such functions. The transform function takes the http\n\t * response body, headers and status and returns its transformed (typically deserialized) version.\n\t * See {@link ng.$http#overriding-the-default-transformations-per-request\n\t * Overriding the Default Transformations}\n\t * - **paramSerializer** - `{string|function(Object):string}` - A function used to\n\t * prepare the string representation of request parameters (specified as an object).\n\t * If specified as string, it is interpreted as function registered with the\n\t * {@link $injector $injector}, which means you can create your own serializer\n\t * by registering it as a {@link auto.$provide#service service}.\n\t * The default serializer is the {@link $httpParamSerializer $httpParamSerializer};\n\t * alternatively, you can use the {@link $httpParamSerializerJQLike $httpParamSerializerJQLike}\n\t * - **cache** – `{boolean|Object}` – A boolean value or object created with\n\t * {@link ng.$cacheFactory `$cacheFactory`} to enable or disable caching of the HTTP response.\n\t * See {@link $http#caching $http Caching} for more information.\n\t * - **timeout** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise}\n\t * that should abort the request when resolved.\n\t * - **withCredentials** - `{boolean}` - whether to set the `withCredentials` flag on the\n\t * XHR object. See [requests with credentials](https://developer.mozilla.org/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials)\n\t * for more information.\n\t * - **responseType** - `{string}` - see\n\t * [XMLHttpRequest.responseType](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#xmlhttprequest-responsetype).\n\t *\n\t * @returns {HttpPromise} Returns a {@link ng.$q `Promise}` that will be resolved to a response object\n\t * when the request succeeds or fails.\n\t *\n\t *\n\t * @property {Array.} pendingRequests Array of config objects for currently pending\n\t * requests. This is primarily meant to be used for debugging purposes.\n\t *\n\t *\n\t * @example\n\t\n\t\n\t
\n\t \n\t \n\t
\n\t \n\t \n\t \n\t
http status code: {{status}}
\n\t
http response data: {{data}}
\n\t
\n\t
\n\t\n\t angular.module('httpExample', [])\n\t .controller('FetchController', ['$scope', '$http', '$templateCache',\n\t function($scope, $http, $templateCache) {\n\t $scope.method = 'GET';\n\t $scope.url = 'http-hello.html';\n\t\n\t $scope.fetch = function() {\n\t $scope.code = null;\n\t $scope.response = null;\n\t\n\t $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n\t then(function(response) {\n\t $scope.status = response.status;\n\t $scope.data = response.data;\n\t }, function(response) {\n\t $scope.data = response.data || \"Request failed\";\n\t $scope.status = response.status;\n\t });\n\t };\n\t\n\t $scope.updateModel = function(method, url) {\n\t $scope.method = method;\n\t $scope.url = url;\n\t };\n\t }]);\n\t\n\t\n\t Hello, $http!\n\t\n\t\n\t var status = element(by.binding('status'));\n\t var data = element(by.binding('data'));\n\t var fetchBtn = element(by.id('fetchbtn'));\n\t var sampleGetBtn = element(by.id('samplegetbtn'));\n\t var sampleJsonpBtn = element(by.id('samplejsonpbtn'));\n\t var invalidJsonpBtn = element(by.id('invalidjsonpbtn'));\n\t\n\t it('should make an xhr GET request', function() {\n\t sampleGetBtn.click();\n\t fetchBtn.click();\n\t expect(status.getText()).toMatch('200');\n\t expect(data.getText()).toMatch(/Hello, \\$http!/);\n\t });\n\t\n\t// Commented out due to flakes. See https://github.com/angular/angular.js/issues/9185\n\t// it('should make a JSONP request to angularjs.org', function() {\n\t// sampleJsonpBtn.click();\n\t// fetchBtn.click();\n\t// expect(status.getText()).toMatch('200');\n\t// expect(data.getText()).toMatch(/Super Hero!/);\n\t// });\n\t\n\t it('should make JSONP request to invalid URL and invoke the error handler',\n\t function() {\n\t invalidJsonpBtn.click();\n\t fetchBtn.click();\n\t expect(status.getText()).toMatch('0');\n\t expect(data.getText()).toMatch('Request failed');\n\t });\n\t\n\t
\n\t */\n\t function $http(requestConfig) {\n\t\n\t if (!isObject(requestConfig)) {\n\t throw minErr('$http')('badreq', 'Http request configuration must be an object. Received: {0}', requestConfig);\n\t }\n\t\n\t if (!isString(requestConfig.url)) {\n\t throw minErr('$http')('badreq', 'Http request configuration url must be a string. Received: {0}', requestConfig.url);\n\t }\n\t\n\t var config = extend({\n\t method: 'get',\n\t transformRequest: defaults.transformRequest,\n\t transformResponse: defaults.transformResponse,\n\t paramSerializer: defaults.paramSerializer\n\t }, requestConfig);\n\t\n\t config.headers = mergeHeaders(requestConfig);\n\t config.method = uppercase(config.method);\n\t config.paramSerializer = isString(config.paramSerializer) ?\n\t $injector.get(config.paramSerializer) : config.paramSerializer;\n\t\n\t var requestInterceptors = [];\n\t var responseInterceptors = [];\n\t var promise = $q.when(config);\n\t\n\t // apply interceptors\n\t forEach(reversedInterceptors, function(interceptor) {\n\t if (interceptor.request || interceptor.requestError) {\n\t requestInterceptors.unshift(interceptor.request, interceptor.requestError);\n\t }\n\t if (interceptor.response || interceptor.responseError) {\n\t responseInterceptors.push(interceptor.response, interceptor.responseError);\n\t }\n\t });\n\t\n\t promise = chainInterceptors(promise, requestInterceptors);\n\t promise = promise.then(serverRequest);\n\t promise = chainInterceptors(promise, responseInterceptors);\n\t\n\t if (useLegacyPromise) {\n\t promise.success = function(fn) {\n\t assertArgFn(fn, 'fn');\n\t\n\t promise.then(function(response) {\n\t fn(response.data, response.status, response.headers, config);\n\t });\n\t return promise;\n\t };\n\t\n\t promise.error = function(fn) {\n\t assertArgFn(fn, 'fn');\n\t\n\t promise.then(null, function(response) {\n\t fn(response.data, response.status, response.headers, config);\n\t });\n\t return promise;\n\t };\n\t } else {\n\t promise.success = $httpMinErrLegacyFn('success');\n\t promise.error = $httpMinErrLegacyFn('error');\n\t }\n\t\n\t return promise;\n\t\n\t\n\t function chainInterceptors(promise, interceptors) {\n\t for (var i = 0, ii = interceptors.length; i < ii;) {\n\t var thenFn = interceptors[i++];\n\t var rejectFn = interceptors[i++];\n\t\n\t promise = promise.then(thenFn, rejectFn);\n\t }\n\t\n\t interceptors.length = 0;\n\t\n\t return promise;\n\t }\n\t\n\t function executeHeaderFns(headers, config) {\n\t var headerContent, processedHeaders = {};\n\t\n\t forEach(headers, function(headerFn, header) {\n\t if (isFunction(headerFn)) {\n\t headerContent = headerFn(config);\n\t if (headerContent != null) {\n\t processedHeaders[header] = headerContent;\n\t }\n\t } else {\n\t processedHeaders[header] = headerFn;\n\t }\n\t });\n\t\n\t return processedHeaders;\n\t }\n\t\n\t function mergeHeaders(config) {\n\t var defHeaders = defaults.headers,\n\t reqHeaders = extend({}, config.headers),\n\t defHeaderName, lowercaseDefHeaderName, reqHeaderName;\n\t\n\t defHeaders = extend({}, defHeaders.common, defHeaders[lowercase(config.method)]);\n\t\n\t // using for-in instead of forEach to avoid unnecessary iteration after header has been found\n\t defaultHeadersIteration:\n\t for (defHeaderName in defHeaders) {\n\t lowercaseDefHeaderName = lowercase(defHeaderName);\n\t\n\t for (reqHeaderName in reqHeaders) {\n\t if (lowercase(reqHeaderName) === lowercaseDefHeaderName) {\n\t continue defaultHeadersIteration;\n\t }\n\t }\n\t\n\t reqHeaders[defHeaderName] = defHeaders[defHeaderName];\n\t }\n\t\n\t // execute if header value is a function for merged headers\n\t return executeHeaderFns(reqHeaders, shallowCopy(config));\n\t }\n\t\n\t function serverRequest(config) {\n\t var headers = config.headers;\n\t var reqData = transformData(config.data, headersGetter(headers), undefined, config.transformRequest);\n\t\n\t // strip content-type if data is undefined\n\t if (isUndefined(reqData)) {\n\t forEach(headers, function(value, header) {\n\t if (lowercase(header) === 'content-type') {\n\t delete headers[header];\n\t }\n\t });\n\t }\n\t\n\t if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) {\n\t config.withCredentials = defaults.withCredentials;\n\t }\n\t\n\t // send request\n\t return sendReq(config, reqData).then(transformResponse, transformResponse);\n\t }\n\t\n\t function transformResponse(response) {\n\t // make a copy since the response must be cacheable\n\t var resp = extend({}, response);\n\t resp.data = transformData(response.data, response.headers, response.status,\n\t config.transformResponse);\n\t return (isSuccess(response.status))\n\t ? resp\n\t : $q.reject(resp);\n\t }\n\t }\n\t\n\t $http.pendingRequests = [];\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $http#get\n\t *\n\t * @description\n\t * Shortcut method to perform `GET` request.\n\t *\n\t * @param {string} url Relative or absolute URL specifying the destination of the request\n\t * @param {Object=} config Optional configuration object\n\t * @returns {HttpPromise} Future object\n\t */\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $http#delete\n\t *\n\t * @description\n\t * Shortcut method to perform `DELETE` request.\n\t *\n\t * @param {string} url Relative or absolute URL specifying the destination of the request\n\t * @param {Object=} config Optional configuration object\n\t * @returns {HttpPromise} Future object\n\t */\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $http#head\n\t *\n\t * @description\n\t * Shortcut method to perform `HEAD` request.\n\t *\n\t * @param {string} url Relative or absolute URL specifying the destination of the request\n\t * @param {Object=} config Optional configuration object\n\t * @returns {HttpPromise} Future object\n\t */\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $http#jsonp\n\t *\n\t * @description\n\t * Shortcut method to perform `JSONP` request.\n\t * If you would like to customise where and how the callbacks are stored then try overriding\n\t * or decorating the {@link $jsonpCallbacks} service.\n\t *\n\t * @param {string} url Relative or absolute URL specifying the destination of the request.\n\t * The name of the callback should be the string `JSON_CALLBACK`.\n\t * @param {Object=} config Optional configuration object\n\t * @returns {HttpPromise} Future object\n\t */\n\t createShortMethods('get', 'delete', 'head', 'jsonp');\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $http#post\n\t *\n\t * @description\n\t * Shortcut method to perform `POST` request.\n\t *\n\t * @param {string} url Relative or absolute URL specifying the destination of the request\n\t * @param {*} data Request content\n\t * @param {Object=} config Optional configuration object\n\t * @returns {HttpPromise} Future object\n\t */\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $http#put\n\t *\n\t * @description\n\t * Shortcut method to perform `PUT` request.\n\t *\n\t * @param {string} url Relative or absolute URL specifying the destination of the request\n\t * @param {*} data Request content\n\t * @param {Object=} config Optional configuration object\n\t * @returns {HttpPromise} Future object\n\t */\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $http#patch\n\t *\n\t * @description\n\t * Shortcut method to perform `PATCH` request.\n\t *\n\t * @param {string} url Relative or absolute URL specifying the destination of the request\n\t * @param {*} data Request content\n\t * @param {Object=} config Optional configuration object\n\t * @returns {HttpPromise} Future object\n\t */\n\t createShortMethodsWithData('post', 'put', 'patch');\n\t\n\t /**\n\t * @ngdoc property\n\t * @name $http#defaults\n\t *\n\t * @description\n\t * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n\t * default headers, withCredentials as well as request and response transformations.\n\t *\n\t * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n\t */\n\t $http.defaults = defaults;\n\t\n\t\n\t return $http;\n\t\n\t\n\t function createShortMethods(names) {\n\t forEach(arguments, function(name) {\n\t $http[name] = function(url, config) {\n\t return $http(extend({}, config || {}, {\n\t method: name,\n\t url: url\n\t }));\n\t };\n\t });\n\t }\n\t\n\t\n\t function createShortMethodsWithData(name) {\n\t forEach(arguments, function(name) {\n\t $http[name] = function(url, data, config) {\n\t return $http(extend({}, config || {}, {\n\t method: name,\n\t url: url,\n\t data: data\n\t }));\n\t };\n\t });\n\t }\n\t\n\t\n\t /**\n\t * Makes the request.\n\t *\n\t * !!! ACCESSES CLOSURE VARS:\n\t * $httpBackend, defaults, $log, $rootScope, defaultCache, $http.pendingRequests\n\t */\n\t function sendReq(config, reqData) {\n\t var deferred = $q.defer(),\n\t promise = deferred.promise,\n\t cache,\n\t cachedResp,\n\t reqHeaders = config.headers,\n\t url = buildUrl(config.url, config.paramSerializer(config.params));\n\t\n\t $http.pendingRequests.push(config);\n\t promise.then(removePendingReq, removePendingReq);\n\t\n\t\n\t if ((config.cache || defaults.cache) && config.cache !== false &&\n\t (config.method === 'GET' || config.method === 'JSONP')) {\n\t cache = isObject(config.cache) ? config.cache\n\t : isObject(defaults.cache) ? defaults.cache\n\t : defaultCache;\n\t }\n\t\n\t if (cache) {\n\t cachedResp = cache.get(url);\n\t if (isDefined(cachedResp)) {\n\t if (isPromiseLike(cachedResp)) {\n\t // cached request has already been sent, but there is no response yet\n\t cachedResp.then(resolvePromiseWithResult, resolvePromiseWithResult);\n\t } else {\n\t // serving from cache\n\t if (isArray(cachedResp)) {\n\t resolvePromise(cachedResp[1], cachedResp[0], shallowCopy(cachedResp[2]), cachedResp[3]);\n\t } else {\n\t resolvePromise(cachedResp, 200, {}, 'OK');\n\t }\n\t }\n\t } else {\n\t // put the promise for the non-transformed response into cache as a placeholder\n\t cache.put(url, promise);\n\t }\n\t }\n\t\n\t\n\t // if we won't have the response in cache, set the xsrf headers and\n\t // send the request to the backend\n\t if (isUndefined(cachedResp)) {\n\t var xsrfValue = urlIsSameOrigin(config.url)\n\t ? $$cookieReader()[config.xsrfCookieName || defaults.xsrfCookieName]\n\t : undefined;\n\t if (xsrfValue) {\n\t reqHeaders[(config.xsrfHeaderName || defaults.xsrfHeaderName)] = xsrfValue;\n\t }\n\t\n\t $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n\t config.withCredentials, config.responseType,\n\t createApplyHandlers(config.eventHandlers),\n\t createApplyHandlers(config.uploadEventHandlers));\n\t }\n\t\n\t return promise;\n\t\n\t function createApplyHandlers(eventHandlers) {\n\t if (eventHandlers) {\n\t var applyHandlers = {};\n\t forEach(eventHandlers, function(eventHandler, key) {\n\t applyHandlers[key] = function(event) {\n\t if (useApplyAsync) {\n\t $rootScope.$applyAsync(callEventHandler);\n\t } else if ($rootScope.$$phase) {\n\t callEventHandler();\n\t } else {\n\t $rootScope.$apply(callEventHandler);\n\t }\n\t\n\t function callEventHandler() {\n\t eventHandler(event);\n\t }\n\t };\n\t });\n\t return applyHandlers;\n\t }\n\t }\n\t\n\t\n\t /**\n\t * Callback registered to $httpBackend():\n\t * - caches the response if desired\n\t * - resolves the raw $http promise\n\t * - calls $apply\n\t */\n\t function done(status, response, headersString, statusText) {\n\t if (cache) {\n\t if (isSuccess(status)) {\n\t cache.put(url, [status, response, parseHeaders(headersString), statusText]);\n\t } else {\n\t // remove promise from the cache\n\t cache.remove(url);\n\t }\n\t }\n\t\n\t function resolveHttpPromise() {\n\t resolvePromise(response, status, headersString, statusText);\n\t }\n\t\n\t if (useApplyAsync) {\n\t $rootScope.$applyAsync(resolveHttpPromise);\n\t } else {\n\t resolveHttpPromise();\n\t if (!$rootScope.$$phase) $rootScope.$apply();\n\t }\n\t }\n\t\n\t\n\t /**\n\t * Resolves the raw $http promise.\n\t */\n\t function resolvePromise(response, status, headers, statusText) {\n\t //status: HTTP response status code, 0, -1 (aborted by timeout / promise)\n\t status = status >= -1 ? status : 0;\n\t\n\t (isSuccess(status) ? deferred.resolve : deferred.reject)({\n\t data: response,\n\t status: status,\n\t headers: headersGetter(headers),\n\t config: config,\n\t statusText: statusText\n\t });\n\t }\n\t\n\t function resolvePromiseWithResult(result) {\n\t resolvePromise(result.data, result.status, shallowCopy(result.headers()), result.statusText);\n\t }\n\t\n\t function removePendingReq() {\n\t var idx = $http.pendingRequests.indexOf(config);\n\t if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n\t }\n\t }\n\t\n\t\n\t function buildUrl(url, serializedParams) {\n\t if (serializedParams.length > 0) {\n\t url += ((url.indexOf('?') == -1) ? '?' : '&') + serializedParams;\n\t }\n\t return url;\n\t }\n\t }];\n\t}\n\t\n\t/**\n\t * @ngdoc service\n\t * @name $xhrFactory\n\t *\n\t * @description\n\t * Factory function used to create XMLHttpRequest objects.\n\t *\n\t * Replace or decorate this service to create your own custom XMLHttpRequest objects.\n\t *\n\t * ```\n\t * angular.module('myApp', [])\n\t * .factory('$xhrFactory', function() {\n\t * return function createXhr(method, url) {\n\t * return new window.XMLHttpRequest({mozSystem: true});\n\t * };\n\t * });\n\t * ```\n\t *\n\t * @param {string} method HTTP method of the request (GET, POST, PUT, ..)\n\t * @param {string} url URL of the request.\n\t */\n\tfunction $xhrFactoryProvider() {\n\t this.$get = function() {\n\t return function createXhr() {\n\t return new window.XMLHttpRequest();\n\t };\n\t };\n\t}\n\t\n\t/**\n\t * @ngdoc service\n\t * @name $httpBackend\n\t * @requires $jsonpCallbacks\n\t * @requires $document\n\t * @requires $xhrFactory\n\t *\n\t * @description\n\t * HTTP backend used by the {@link ng.$http service} that delegates to\n\t * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n\t *\n\t * You should never need to use this service directly, instead use the higher-level abstractions:\n\t * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n\t *\n\t * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n\t * $httpBackend} which can be trained with responses.\n\t */\n\tfunction $HttpBackendProvider() {\n\t this.$get = ['$browser', '$jsonpCallbacks', '$document', '$xhrFactory', function($browser, $jsonpCallbacks, $document, $xhrFactory) {\n\t return createHttpBackend($browser, $xhrFactory, $browser.defer, $jsonpCallbacks, $document[0]);\n\t }];\n\t}\n\t\n\tfunction createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) {\n\t // TODO(vojta): fix the signature\n\t return function(method, url, post, callback, headers, timeout, withCredentials, responseType, eventHandlers, uploadEventHandlers) {\n\t $browser.$$incOutstandingRequestCount();\n\t url = url || $browser.url();\n\t\n\t if (lowercase(method) === 'jsonp') {\n\t var callbackPath = callbacks.createCallback(url);\n\t var jsonpDone = jsonpReq(url, callbackPath, function(status, text) {\n\t // jsonpReq only ever sets status to 200 (OK), 404 (ERROR) or -1 (WAITING)\n\t var response = (status === 200) && callbacks.getResponse(callbackPath);\n\t completeRequest(callback, status, response, \"\", text);\n\t callbacks.removeCallback(callbackPath);\n\t });\n\t } else {\n\t\n\t var xhr = createXhr(method, url);\n\t\n\t xhr.open(method, url, true);\n\t forEach(headers, function(value, key) {\n\t if (isDefined(value)) {\n\t xhr.setRequestHeader(key, value);\n\t }\n\t });\n\t\n\t xhr.onload = function requestLoaded() {\n\t var statusText = xhr.statusText || '';\n\t\n\t // responseText is the old-school way of retrieving response (supported by IE9)\n\t // response/responseType properties were introduced in XHR Level2 spec (supported by IE10)\n\t var response = ('response' in xhr) ? xhr.response : xhr.responseText;\n\t\n\t // normalize IE9 bug (http://bugs.jquery.com/ticket/1450)\n\t var status = xhr.status === 1223 ? 204 : xhr.status;\n\t\n\t // fix status code when it is 0 (0 status is undocumented).\n\t // Occurs when accessing file resources or on Android 4.1 stock browser\n\t // while retrieving files from application cache.\n\t if (status === 0) {\n\t status = response ? 200 : urlResolve(url).protocol == 'file' ? 404 : 0;\n\t }\n\t\n\t completeRequest(callback,\n\t status,\n\t response,\n\t xhr.getAllResponseHeaders(),\n\t statusText);\n\t };\n\t\n\t var requestError = function() {\n\t // The response is always empty\n\t // See https://xhr.spec.whatwg.org/#request-error-steps and https://fetch.spec.whatwg.org/#concept-network-error\n\t completeRequest(callback, -1, null, null, '');\n\t };\n\t\n\t xhr.onerror = requestError;\n\t xhr.onabort = requestError;\n\t\n\t forEach(eventHandlers, function(value, key) {\n\t xhr.addEventListener(key, value);\n\t });\n\t\n\t forEach(uploadEventHandlers, function(value, key) {\n\t xhr.upload.addEventListener(key, value);\n\t });\n\t\n\t if (withCredentials) {\n\t xhr.withCredentials = true;\n\t }\n\t\n\t if (responseType) {\n\t try {\n\t xhr.responseType = responseType;\n\t } catch (e) {\n\t // WebKit added support for the json responseType value on 09/03/2013\n\t // https://bugs.webkit.org/show_bug.cgi?id=73648. Versions of Safari prior to 7 are\n\t // known to throw when setting the value \"json\" as the response type. Other older\n\t // browsers implementing the responseType\n\t //\n\t // The json response type can be ignored if not supported, because JSON payloads are\n\t // parsed on the client-side regardless.\n\t if (responseType !== 'json') {\n\t throw e;\n\t }\n\t }\n\t }\n\t\n\t xhr.send(isUndefined(post) ? null : post);\n\t }\n\t\n\t if (timeout > 0) {\n\t var timeoutId = $browserDefer(timeoutRequest, timeout);\n\t } else if (isPromiseLike(timeout)) {\n\t timeout.then(timeoutRequest);\n\t }\n\t\n\t\n\t function timeoutRequest() {\n\t jsonpDone && jsonpDone();\n\t xhr && xhr.abort();\n\t }\n\t\n\t function completeRequest(callback, status, response, headersString, statusText) {\n\t // cancel timeout and subsequent timeout promise resolution\n\t if (isDefined(timeoutId)) {\n\t $browserDefer.cancel(timeoutId);\n\t }\n\t jsonpDone = xhr = null;\n\t\n\t callback(status, response, headersString, statusText);\n\t $browser.$$completeOutstandingRequest(noop);\n\t }\n\t };\n\t\n\t function jsonpReq(url, callbackPath, done) {\n\t url = url.replace('JSON_CALLBACK', callbackPath);\n\t // we can't use jQuery/jqLite here because jQuery does crazy stuff with script elements, e.g.:\n\t // - fetches local scripts via XHR and evals them\n\t // - adds and immediately removes script elements from the document\n\t var script = rawDocument.createElement('script'), callback = null;\n\t script.type = \"text/javascript\";\n\t script.src = url;\n\t script.async = true;\n\t\n\t callback = function(event) {\n\t removeEventListenerFn(script, \"load\", callback);\n\t removeEventListenerFn(script, \"error\", callback);\n\t rawDocument.body.removeChild(script);\n\t script = null;\n\t var status = -1;\n\t var text = \"unknown\";\n\t\n\t if (event) {\n\t if (event.type === \"load\" && !callbacks.wasCalled(callbackPath)) {\n\t event = { type: \"error\" };\n\t }\n\t text = event.type;\n\t status = event.type === \"error\" ? 404 : 200;\n\t }\n\t\n\t if (done) {\n\t done(status, text);\n\t }\n\t };\n\t\n\t addEventListenerFn(script, \"load\", callback);\n\t addEventListenerFn(script, \"error\", callback);\n\t rawDocument.body.appendChild(script);\n\t return callback;\n\t }\n\t}\n\t\n\tvar $interpolateMinErr = angular.$interpolateMinErr = minErr('$interpolate');\n\t$interpolateMinErr.throwNoconcat = function(text) {\n\t throw $interpolateMinErr('noconcat',\n\t \"Error while interpolating: {0}\\nStrict Contextual Escaping disallows \" +\n\t \"interpolations that concatenate multiple expressions when a trusted value is \" +\n\t \"required. See http://docs.angularjs.org/api/ng.$sce\", text);\n\t};\n\t\n\t$interpolateMinErr.interr = function(text, err) {\n\t return $interpolateMinErr('interr', \"Can't interpolate: {0}\\n{1}\", text, err.toString());\n\t};\n\t\n\t/**\n\t * @ngdoc provider\n\t * @name $interpolateProvider\n\t *\n\t * @description\n\t *\n\t * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n\t *\n\t *
\n\t * This feature is sometimes used to mix different markup languages, e.g. to wrap an Angular\n\t * template within a Python Jinja template (or any other template language). Mixing templating\n\t * languages is **very dangerous**. The embedding template language will not safely escape Angular\n\t * expressions, so any user-controlled values in the template will cause Cross Site Scripting (XSS)\n\t * security bugs!\n\t *
\n\t *\n\t * @example\n\t\n\t\n\t\n\t
\n\t //demo.label//\n\t
\n\t
\n\t\n\t it('should interpolate binding with custom symbols', function() {\n\t expect(element(by.binding('demo.label')).getText()).toBe('This binding is brought you by // interpolation symbols.');\n\t });\n\t\n\t
\n\t */\n\tfunction $InterpolateProvider() {\n\t var startSymbol = '{{';\n\t var endSymbol = '}}';\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $interpolateProvider#startSymbol\n\t * @description\n\t * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n\t *\n\t * @param {string=} value new value to set the starting symbol to.\n\t * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n\t */\n\t this.startSymbol = function(value) {\n\t if (value) {\n\t startSymbol = value;\n\t return this;\n\t } else {\n\t return startSymbol;\n\t }\n\t };\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $interpolateProvider#endSymbol\n\t * @description\n\t * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n\t *\n\t * @param {string=} value new value to set the ending symbol to.\n\t * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n\t */\n\t this.endSymbol = function(value) {\n\t if (value) {\n\t endSymbol = value;\n\t return this;\n\t } else {\n\t return endSymbol;\n\t }\n\t };\n\t\n\t\n\t this.$get = ['$parse', '$exceptionHandler', '$sce', function($parse, $exceptionHandler, $sce) {\n\t var startSymbolLength = startSymbol.length,\n\t endSymbolLength = endSymbol.length,\n\t escapedStartRegexp = new RegExp(startSymbol.replace(/./g, escape), 'g'),\n\t escapedEndRegexp = new RegExp(endSymbol.replace(/./g, escape), 'g');\n\t\n\t function escape(ch) {\n\t return '\\\\\\\\\\\\' + ch;\n\t }\n\t\n\t function unescapeText(text) {\n\t return text.replace(escapedStartRegexp, startSymbol).\n\t replace(escapedEndRegexp, endSymbol);\n\t }\n\t\n\t function stringify(value) {\n\t if (value == null) { // null || undefined\n\t return '';\n\t }\n\t switch (typeof value) {\n\t case 'string':\n\t break;\n\t case 'number':\n\t value = '' + value;\n\t break;\n\t default:\n\t value = toJson(value);\n\t }\n\t\n\t return value;\n\t }\n\t\n\t //TODO: this is the same as the constantWatchDelegate in parse.js\n\t function constantWatchDelegate(scope, listener, objectEquality, constantInterp) {\n\t var unwatch;\n\t return unwatch = scope.$watch(function constantInterpolateWatch(scope) {\n\t unwatch();\n\t return constantInterp(scope);\n\t }, listener, objectEquality);\n\t }\n\t\n\t /**\n\t * @ngdoc service\n\t * @name $interpolate\n\t * @kind function\n\t *\n\t * @requires $parse\n\t * @requires $sce\n\t *\n\t * @description\n\t *\n\t * Compiles a string with markup into an interpolation function. This service is used by the\n\t * HTML {@link ng.$compile $compile} service for data binding. See\n\t * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n\t * interpolation markup.\n\t *\n\t *\n\t * ```js\n\t * var $interpolate = ...; // injected\n\t * var exp = $interpolate('Hello {{name | uppercase}}!');\n\t * expect(exp({name:'Angular'})).toEqual('Hello ANGULAR!');\n\t * ```\n\t *\n\t * `$interpolate` takes an optional fourth argument, `allOrNothing`. If `allOrNothing` is\n\t * `true`, the interpolation function will return `undefined` unless all embedded expressions\n\t * evaluate to a value other than `undefined`.\n\t *\n\t * ```js\n\t * var $interpolate = ...; // injected\n\t * var context = {greeting: 'Hello', name: undefined };\n\t *\n\t * // default \"forgiving\" mode\n\t * var exp = $interpolate('{{greeting}} {{name}}!');\n\t * expect(exp(context)).toEqual('Hello !');\n\t *\n\t * // \"allOrNothing\" mode\n\t * exp = $interpolate('{{greeting}} {{name}}!', false, null, true);\n\t * expect(exp(context)).toBeUndefined();\n\t * context.name = 'Angular';\n\t * expect(exp(context)).toEqual('Hello Angular!');\n\t * ```\n\t *\n\t * `allOrNothing` is useful for interpolating URLs. `ngSrc` and `ngSrcset` use this behavior.\n\t *\n\t * #### Escaped Interpolation\n\t * $interpolate provides a mechanism for escaping interpolation markers. Start and end markers\n\t * can be escaped by preceding each of their characters with a REVERSE SOLIDUS U+005C (backslash).\n\t * It will be rendered as a regular start/end marker, and will not be interpreted as an expression\n\t * or binding.\n\t *\n\t * This enables web-servers to prevent script injection attacks and defacing attacks, to some\n\t * degree, while also enabling code examples to work without relying on the\n\t * {@link ng.directive:ngNonBindable ngNonBindable} directive.\n\t *\n\t * **For security purposes, it is strongly encouraged that web servers escape user-supplied data,\n\t * replacing angle brackets (<, >) with &lt; and &gt; respectively, and replacing all\n\t * interpolation start/end markers with their escaped counterparts.**\n\t *\n\t * Escaped interpolation markers are only replaced with the actual interpolation markers in rendered\n\t * output when the $interpolate service processes the text. So, for HTML elements interpolated\n\t * by {@link ng.$compile $compile}, or otherwise interpolated with the `mustHaveExpression` parameter\n\t * set to `true`, the interpolated text must contain an unescaped interpolation expression. As such,\n\t * this is typically useful only when user-data is used in rendering a template from the server, or\n\t * when otherwise untrusted data is used by a directive.\n\t *\n\t * \n\t * \n\t *
\n\t *

{{apptitle}}: \\{\\{ username = \"defaced value\"; \\}\\}\n\t *

\n\t *

{{username}} attempts to inject code which will deface the\n\t * application, but fails to accomplish their task, because the server has correctly\n\t * escaped the interpolation start/end markers with REVERSE SOLIDUS U+005C (backslash)\n\t * characters.

\n\t *

Instead, the result of the attempted script injection is visible, and can be removed\n\t * from the database by an administrator.

\n\t *
\n\t *
\n\t *
\n\t *\n\t * @knownIssue\n\t * It is currently not possible for an interpolated expression to contain the interpolation end\n\t * symbol. For example, `{{ '}}' }}` will be incorrectly interpreted as `{{ ' }}` + `' }}`, i.e.\n\t * an interpolated expression consisting of a single-quote (`'`) and the `' }}` string.\n\t *\n\t * @knownIssue\n\t * All directives and components must use the standard `{{` `}}` interpolation symbols\n\t * in their templates. If you change the application interpolation symbols the {@link $compile}\n\t * service will attempt to denormalize the standard symbols to the custom symbols.\n\t * The denormalization process is not clever enough to know not to replace instances of the standard\n\t * symbols where they would not normally be treated as interpolation symbols. For example in the following\n\t * code snippet the closing braces of the literal object will get incorrectly denormalized:\n\t *\n\t * ```\n\t *
\n\t * ```\n\t *\n\t * See https://github.com/angular/angular.js/pull/14610#issuecomment-219401099 for more information.\n\t *\n\t * @param {string} text The text with markup to interpolate.\n\t * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n\t * embedded expression in order to return an interpolation function. Strings with no\n\t * embedded expression will return null for the interpolation function.\n\t * @param {string=} trustedContext when provided, the returned function passes the interpolated\n\t * result through {@link ng.$sce#getTrusted $sce.getTrusted(interpolatedResult,\n\t * trustedContext)} before returning it. Refer to the {@link ng.$sce $sce} service that\n\t * provides Strict Contextual Escaping for details.\n\t * @param {boolean=} allOrNothing if `true`, then the returned function returns undefined\n\t * unless all embedded expressions evaluate to a value other than `undefined`.\n\t * @returns {function(context)} an interpolation function which is used to compute the\n\t * interpolated string. The function has these parameters:\n\t *\n\t * - `context`: evaluation context for all expressions embedded in the interpolated text\n\t */\n\t function $interpolate(text, mustHaveExpression, trustedContext, allOrNothing) {\n\t // Provide a quick exit and simplified result function for text with no interpolation\n\t if (!text.length || text.indexOf(startSymbol) === -1) {\n\t var constantInterp;\n\t if (!mustHaveExpression) {\n\t var unescapedText = unescapeText(text);\n\t constantInterp = valueFn(unescapedText);\n\t constantInterp.exp = text;\n\t constantInterp.expressions = [];\n\t constantInterp.$$watchDelegate = constantWatchDelegate;\n\t }\n\t return constantInterp;\n\t }\n\t\n\t allOrNothing = !!allOrNothing;\n\t var startIndex,\n\t endIndex,\n\t index = 0,\n\t expressions = [],\n\t parseFns = [],\n\t textLength = text.length,\n\t exp,\n\t concat = [],\n\t expressionPositions = [];\n\t\n\t while (index < textLength) {\n\t if (((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n\t ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1)) {\n\t if (index !== startIndex) {\n\t concat.push(unescapeText(text.substring(index, startIndex)));\n\t }\n\t exp = text.substring(startIndex + startSymbolLength, endIndex);\n\t expressions.push(exp);\n\t parseFns.push($parse(exp, parseStringifyInterceptor));\n\t index = endIndex + endSymbolLength;\n\t expressionPositions.push(concat.length);\n\t concat.push('');\n\t } else {\n\t // we did not find an interpolation, so we have to add the remainder to the separators array\n\t if (index !== textLength) {\n\t concat.push(unescapeText(text.substring(index)));\n\t }\n\t break;\n\t }\n\t }\n\t\n\t // Concatenating expressions makes it hard to reason about whether some combination of\n\t // concatenated values are unsafe to use and could easily lead to XSS. By requiring that a\n\t // single expression be used for iframe[src], object[src], etc., we ensure that the value\n\t // that's used is assigned or constructed by some JS code somewhere that is more testable or\n\t // make it obvious that you bound the value to some user controlled value. This helps reduce\n\t // the load when auditing for XSS issues.\n\t if (trustedContext && concat.length > 1) {\n\t $interpolateMinErr.throwNoconcat(text);\n\t }\n\t\n\t if (!mustHaveExpression || expressions.length) {\n\t var compute = function(values) {\n\t for (var i = 0, ii = expressions.length; i < ii; i++) {\n\t if (allOrNothing && isUndefined(values[i])) return;\n\t concat[expressionPositions[i]] = values[i];\n\t }\n\t return concat.join('');\n\t };\n\t\n\t var getValue = function(value) {\n\t return trustedContext ?\n\t $sce.getTrusted(trustedContext, value) :\n\t $sce.valueOf(value);\n\t };\n\t\n\t return extend(function interpolationFn(context) {\n\t var i = 0;\n\t var ii = expressions.length;\n\t var values = new Array(ii);\n\t\n\t try {\n\t for (; i < ii; i++) {\n\t values[i] = parseFns[i](context);\n\t }\n\t\n\t return compute(values);\n\t } catch (err) {\n\t $exceptionHandler($interpolateMinErr.interr(text, err));\n\t }\n\t\n\t }, {\n\t // all of these properties are undocumented for now\n\t exp: text, //just for compatibility with regular watchers created via $watch\n\t expressions: expressions,\n\t $$watchDelegate: function(scope, listener) {\n\t var lastValue;\n\t return scope.$watchGroup(parseFns, function interpolateFnWatcher(values, oldValues) {\n\t var currValue = compute(values);\n\t if (isFunction(listener)) {\n\t listener.call(this, currValue, values !== oldValues ? lastValue : currValue, scope);\n\t }\n\t lastValue = currValue;\n\t });\n\t }\n\t });\n\t }\n\t\n\t function parseStringifyInterceptor(value) {\n\t try {\n\t value = getValue(value);\n\t return allOrNothing && !isDefined(value) ? value : stringify(value);\n\t } catch (err) {\n\t $exceptionHandler($interpolateMinErr.interr(text, err));\n\t }\n\t }\n\t }\n\t\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $interpolate#startSymbol\n\t * @description\n\t * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n\t *\n\t * Use {@link ng.$interpolateProvider#startSymbol `$interpolateProvider.startSymbol`} to change\n\t * the symbol.\n\t *\n\t * @returns {string} start symbol.\n\t */\n\t $interpolate.startSymbol = function() {\n\t return startSymbol;\n\t };\n\t\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $interpolate#endSymbol\n\t * @description\n\t * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n\t *\n\t * Use {@link ng.$interpolateProvider#endSymbol `$interpolateProvider.endSymbol`} to change\n\t * the symbol.\n\t *\n\t * @returns {string} end symbol.\n\t */\n\t $interpolate.endSymbol = function() {\n\t return endSymbol;\n\t };\n\t\n\t return $interpolate;\n\t }];\n\t}\n\t\n\tfunction $IntervalProvider() {\n\t this.$get = ['$rootScope', '$window', '$q', '$$q', '$browser',\n\t function($rootScope, $window, $q, $$q, $browser) {\n\t var intervals = {};\n\t\n\t\n\t /**\n\t * @ngdoc service\n\t * @name $interval\n\t *\n\t * @description\n\t * Angular's wrapper for `window.setInterval`. The `fn` function is executed every `delay`\n\t * milliseconds.\n\t *\n\t * The return value of registering an interval function is a promise. This promise will be\n\t * notified upon each tick of the interval, and will be resolved after `count` iterations, or\n\t * run indefinitely if `count` is not defined. The value of the notification will be the\n\t * number of iterations that have run.\n\t * To cancel an interval, call `$interval.cancel(promise)`.\n\t *\n\t * In tests you can use {@link ngMock.$interval#flush `$interval.flush(millis)`} to\n\t * move forward by `millis` milliseconds and trigger any functions scheduled to run in that\n\t * time.\n\t *\n\t *
\n\t * **Note**: Intervals created by this service must be explicitly destroyed when you are finished\n\t * with them. In particular they are not automatically destroyed when a controller's scope or a\n\t * directive's element are destroyed.\n\t * You should take this into consideration and make sure to always cancel the interval at the\n\t * appropriate moment. See the example below for more details on how and when to do this.\n\t *
\n\t *\n\t * @param {function()} fn A function that should be called repeatedly.\n\t * @param {number} delay Number of milliseconds between each function call.\n\t * @param {number=} [count=0] Number of times to repeat. If not set, or 0, will repeat\n\t * indefinitely.\n\t * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise\n\t * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n\t * @param {...*=} Pass additional parameters to the executed function.\n\t * @returns {promise} A promise which will be notified on each iteration.\n\t *\n\t * @example\n\t * \n\t * \n\t * \n\t *\n\t *
\n\t *
\n\t *
\n\t * Current time is: \n\t *
\n\t * Blood 1 : {{blood_1}}\n\t * Blood 2 : {{blood_2}}\n\t * \n\t * \n\t * \n\t *
\n\t *
\n\t *\n\t *
\n\t *
\n\t */\n\t function interval(fn, delay, count, invokeApply) {\n\t var hasParams = arguments.length > 4,\n\t args = hasParams ? sliceArgs(arguments, 4) : [],\n\t setInterval = $window.setInterval,\n\t clearInterval = $window.clearInterval,\n\t iteration = 0,\n\t skipApply = (isDefined(invokeApply) && !invokeApply),\n\t deferred = (skipApply ? $$q : $q).defer(),\n\t promise = deferred.promise;\n\t\n\t count = isDefined(count) ? count : 0;\n\t\n\t promise.$$intervalId = setInterval(function tick() {\n\t if (skipApply) {\n\t $browser.defer(callback);\n\t } else {\n\t $rootScope.$evalAsync(callback);\n\t }\n\t deferred.notify(iteration++);\n\t\n\t if (count > 0 && iteration >= count) {\n\t deferred.resolve(iteration);\n\t clearInterval(promise.$$intervalId);\n\t delete intervals[promise.$$intervalId];\n\t }\n\t\n\t if (!skipApply) $rootScope.$apply();\n\t\n\t }, delay);\n\t\n\t intervals[promise.$$intervalId] = deferred;\n\t\n\t return promise;\n\t\n\t function callback() {\n\t if (!hasParams) {\n\t fn(iteration);\n\t } else {\n\t fn.apply(null, args);\n\t }\n\t }\n\t }\n\t\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $interval#cancel\n\t *\n\t * @description\n\t * Cancels a task associated with the `promise`.\n\t *\n\t * @param {Promise=} promise returned by the `$interval` function.\n\t * @returns {boolean} Returns `true` if the task was successfully canceled.\n\t */\n\t interval.cancel = function(promise) {\n\t if (promise && promise.$$intervalId in intervals) {\n\t intervals[promise.$$intervalId].reject('canceled');\n\t $window.clearInterval(promise.$$intervalId);\n\t delete intervals[promise.$$intervalId];\n\t return true;\n\t }\n\t return false;\n\t };\n\t\n\t return interval;\n\t }];\n\t}\n\t\n\t/**\n\t * @ngdoc service\n\t * @name $jsonpCallbacks\n\t * @requires $window\n\t * @description\n\t * This service handles the lifecycle of callbacks to handle JSONP requests.\n\t * Override this service if you wish to customise where the callbacks are stored and\n\t * how they vary compared to the requested url.\n\t */\n\tvar $jsonpCallbacksProvider = function() {\n\t this.$get = ['$window', function($window) {\n\t var callbacks = $window.angular.callbacks;\n\t var callbackMap = {};\n\t\n\t function createCallback(callbackId) {\n\t var callback = function(data) {\n\t callback.data = data;\n\t callback.called = true;\n\t };\n\t callback.id = callbackId;\n\t return callback;\n\t }\n\t\n\t return {\n\t /**\n\t * @ngdoc method\n\t * @name $jsonpCallbacks#createCallback\n\t * @param {string} url the url of the JSONP request\n\t * @returns {string} the callback path to send to the server as part of the JSONP request\n\t * @description\n\t * {@link $httpBackend} calls this method to create a callback and get hold of the path to the callback\n\t * to pass to the server, which will be used to call the callback with its payload in the JSONP response.\n\t */\n\t createCallback: function(url) {\n\t var callbackId = '_' + (callbacks.$$counter++).toString(36);\n\t var callbackPath = 'angular.callbacks.' + callbackId;\n\t var callback = createCallback(callbackId);\n\t callbackMap[callbackPath] = callbacks[callbackId] = callback;\n\t return callbackPath;\n\t },\n\t /**\n\t * @ngdoc method\n\t * @name $jsonpCallbacks#wasCalled\n\t * @param {string} callbackPath the path to the callback that was sent in the JSONP request\n\t * @returns {boolean} whether the callback has been called, as a result of the JSONP response\n\t * @description\n\t * {@link $httpBackend} calls this method to find out whether the JSONP response actually called the\n\t * callback that was passed in the request.\n\t */\n\t wasCalled: function(callbackPath) {\n\t return callbackMap[callbackPath].called;\n\t },\n\t /**\n\t * @ngdoc method\n\t * @name $jsonpCallbacks#getResponse\n\t * @param {string} callbackPath the path to the callback that was sent in the JSONP request\n\t * @returns {*} the data received from the response via the registered callback\n\t * @description\n\t * {@link $httpBackend} calls this method to get hold of the data that was provided to the callback\n\t * in the JSONP response.\n\t */\n\t getResponse: function(callbackPath) {\n\t return callbackMap[callbackPath].data;\n\t },\n\t /**\n\t * @ngdoc method\n\t * @name $jsonpCallbacks#removeCallback\n\t * @param {string} callbackPath the path to the callback that was sent in the JSONP request\n\t * @description\n\t * {@link $httpBackend} calls this method to remove the callback after the JSONP request has\n\t * completed or timed-out.\n\t */\n\t removeCallback: function(callbackPath) {\n\t var callback = callbackMap[callbackPath];\n\t delete callbacks[callback.id];\n\t delete callbackMap[callbackPath];\n\t }\n\t };\n\t }];\n\t};\n\t\n\t/**\n\t * @ngdoc service\n\t * @name $locale\n\t *\n\t * @description\n\t * $locale service provides localization rules for various Angular components. As of right now the\n\t * only public api is:\n\t *\n\t * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n\t */\n\t\n\tvar PATH_MATCH = /^([^\\?#]*)(\\?([^#]*))?(#(.*))?$/,\n\t DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\n\tvar $locationMinErr = minErr('$location');\n\t\n\t\n\t/**\n\t * Encode path using encodeUriSegment, ignoring forward slashes\n\t *\n\t * @param {string} path Path to encode\n\t * @returns {string}\n\t */\n\tfunction encodePath(path) {\n\t var segments = path.split('/'),\n\t i = segments.length;\n\t\n\t while (i--) {\n\t segments[i] = encodeUriSegment(segments[i]);\n\t }\n\t\n\t return segments.join('/');\n\t}\n\t\n\tfunction parseAbsoluteUrl(absoluteUrl, locationObj) {\n\t var parsedUrl = urlResolve(absoluteUrl);\n\t\n\t locationObj.$$protocol = parsedUrl.protocol;\n\t locationObj.$$host = parsedUrl.hostname;\n\t locationObj.$$port = toInt(parsedUrl.port) || DEFAULT_PORTS[parsedUrl.protocol] || null;\n\t}\n\t\n\t\n\tfunction parseAppUrl(relativeUrl, locationObj) {\n\t var prefixed = (relativeUrl.charAt(0) !== '/');\n\t if (prefixed) {\n\t relativeUrl = '/' + relativeUrl;\n\t }\n\t var match = urlResolve(relativeUrl);\n\t locationObj.$$path = decodeURIComponent(prefixed && match.pathname.charAt(0) === '/' ?\n\t match.pathname.substring(1) : match.pathname);\n\t locationObj.$$search = parseKeyValue(match.search);\n\t locationObj.$$hash = decodeURIComponent(match.hash);\n\t\n\t // make sure path starts with '/';\n\t if (locationObj.$$path && locationObj.$$path.charAt(0) != '/') {\n\t locationObj.$$path = '/' + locationObj.$$path;\n\t }\n\t}\n\t\n\tfunction startsWith(haystack, needle) {\n\t return haystack.lastIndexOf(needle, 0) === 0;\n\t}\n\t\n\t/**\n\t *\n\t * @param {string} base\n\t * @param {string} url\n\t * @returns {string} returns text from `url` after `base` or `undefined` if it does not begin with\n\t * the expected string.\n\t */\n\tfunction stripBaseUrl(base, url) {\n\t if (startsWith(url, base)) {\n\t return url.substr(base.length);\n\t }\n\t}\n\t\n\t\n\tfunction stripHash(url) {\n\t var index = url.indexOf('#');\n\t return index == -1 ? url : url.substr(0, index);\n\t}\n\t\n\tfunction trimEmptyHash(url) {\n\t return url.replace(/(#.+)|#$/, '$1');\n\t}\n\t\n\t\n\tfunction stripFile(url) {\n\t return url.substr(0, stripHash(url).lastIndexOf('/') + 1);\n\t}\n\t\n\t/* return the server only (scheme://host:port) */\n\tfunction serverBase(url) {\n\t return url.substring(0, url.indexOf('/', url.indexOf('//') + 2));\n\t}\n\t\n\t\n\t/**\n\t * LocationHtml5Url represents an url\n\t * This object is exposed as $location service when HTML5 mode is enabled and supported\n\t *\n\t * @constructor\n\t * @param {string} appBase application base URL\n\t * @param {string} appBaseNoFile application base URL stripped of any filename\n\t * @param {string} basePrefix url path prefix\n\t */\n\tfunction LocationHtml5Url(appBase, appBaseNoFile, basePrefix) {\n\t this.$$html5 = true;\n\t basePrefix = basePrefix || '';\n\t parseAbsoluteUrl(appBase, this);\n\t\n\t\n\t /**\n\t * Parse given html5 (regular) url string into properties\n\t * @param {string} url HTML5 url\n\t * @private\n\t */\n\t this.$$parse = function(url) {\n\t var pathUrl = stripBaseUrl(appBaseNoFile, url);\n\t if (!isString(pathUrl)) {\n\t throw $locationMinErr('ipthprfx', 'Invalid url \"{0}\", missing path prefix \"{1}\".', url,\n\t appBaseNoFile);\n\t }\n\t\n\t parseAppUrl(pathUrl, this);\n\t\n\t if (!this.$$path) {\n\t this.$$path = '/';\n\t }\n\t\n\t this.$$compose();\n\t };\n\t\n\t /**\n\t * Compose url and update `absUrl` property\n\t * @private\n\t */\n\t this.$$compose = function() {\n\t var search = toKeyValue(this.$$search),\n\t hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\t\n\t this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n\t this.$$absUrl = appBaseNoFile + this.$$url.substr(1); // first char is always '/'\n\t };\n\t\n\t this.$$parseLinkUrl = function(url, relHref) {\n\t if (relHref && relHref[0] === '#') {\n\t // special case for links to hash fragments:\n\t // keep the old url and only replace the hash fragment\n\t this.hash(relHref.slice(1));\n\t return true;\n\t }\n\t var appUrl, prevAppUrl;\n\t var rewrittenUrl;\n\t\n\t if (isDefined(appUrl = stripBaseUrl(appBase, url))) {\n\t prevAppUrl = appUrl;\n\t if (isDefined(appUrl = stripBaseUrl(basePrefix, appUrl))) {\n\t rewrittenUrl = appBaseNoFile + (stripBaseUrl('/', appUrl) || appUrl);\n\t } else {\n\t rewrittenUrl = appBase + prevAppUrl;\n\t }\n\t } else if (isDefined(appUrl = stripBaseUrl(appBaseNoFile, url))) {\n\t rewrittenUrl = appBaseNoFile + appUrl;\n\t } else if (appBaseNoFile == url + '/') {\n\t rewrittenUrl = appBaseNoFile;\n\t }\n\t if (rewrittenUrl) {\n\t this.$$parse(rewrittenUrl);\n\t }\n\t return !!rewrittenUrl;\n\t };\n\t}\n\t\n\t\n\t/**\n\t * LocationHashbangUrl represents url\n\t * This object is exposed as $location service when developer doesn't opt into html5 mode.\n\t * It also serves as the base class for html5 mode fallback on legacy browsers.\n\t *\n\t * @constructor\n\t * @param {string} appBase application base URL\n\t * @param {string} appBaseNoFile application base URL stripped of any filename\n\t * @param {string} hashPrefix hashbang prefix\n\t */\n\tfunction LocationHashbangUrl(appBase, appBaseNoFile, hashPrefix) {\n\t\n\t parseAbsoluteUrl(appBase, this);\n\t\n\t\n\t /**\n\t * Parse given hashbang url into properties\n\t * @param {string} url Hashbang url\n\t * @private\n\t */\n\t this.$$parse = function(url) {\n\t var withoutBaseUrl = stripBaseUrl(appBase, url) || stripBaseUrl(appBaseNoFile, url);\n\t var withoutHashUrl;\n\t\n\t if (!isUndefined(withoutBaseUrl) && withoutBaseUrl.charAt(0) === '#') {\n\t\n\t // The rest of the url starts with a hash so we have\n\t // got either a hashbang path or a plain hash fragment\n\t withoutHashUrl = stripBaseUrl(hashPrefix, withoutBaseUrl);\n\t if (isUndefined(withoutHashUrl)) {\n\t // There was no hashbang prefix so we just have a hash fragment\n\t withoutHashUrl = withoutBaseUrl;\n\t }\n\t\n\t } else {\n\t // There was no hashbang path nor hash fragment:\n\t // If we are in HTML5 mode we use what is left as the path;\n\t // Otherwise we ignore what is left\n\t if (this.$$html5) {\n\t withoutHashUrl = withoutBaseUrl;\n\t } else {\n\t withoutHashUrl = '';\n\t if (isUndefined(withoutBaseUrl)) {\n\t appBase = url;\n\t this.replace();\n\t }\n\t }\n\t }\n\t\n\t parseAppUrl(withoutHashUrl, this);\n\t\n\t this.$$path = removeWindowsDriveName(this.$$path, withoutHashUrl, appBase);\n\t\n\t this.$$compose();\n\t\n\t /*\n\t * In Windows, on an anchor node on documents loaded from\n\t * the filesystem, the browser will return a pathname\n\t * prefixed with the drive name ('/C:/path') when a\n\t * pathname without a drive is set:\n\t * * a.setAttribute('href', '/foo')\n\t * * a.pathname === '/C:/foo' //true\n\t *\n\t * Inside of Angular, we're always using pathnames that\n\t * do not include drive names for routing.\n\t */\n\t function removeWindowsDriveName(path, url, base) {\n\t /*\n\t Matches paths for file protocol on windows,\n\t such as /C:/foo/bar, and captures only /foo/bar.\n\t */\n\t var windowsFilePathExp = /^\\/[A-Z]:(\\/.*)/;\n\t\n\t var firstPathSegmentMatch;\n\t\n\t //Get the relative path from the input URL.\n\t if (startsWith(url, base)) {\n\t url = url.replace(base, '');\n\t }\n\t\n\t // The input URL intentionally contains a first path segment that ends with a colon.\n\t if (windowsFilePathExp.exec(url)) {\n\t return path;\n\t }\n\t\n\t firstPathSegmentMatch = windowsFilePathExp.exec(path);\n\t return firstPathSegmentMatch ? firstPathSegmentMatch[1] : path;\n\t }\n\t };\n\t\n\t /**\n\t * Compose hashbang url and update `absUrl` property\n\t * @private\n\t */\n\t this.$$compose = function() {\n\t var search = toKeyValue(this.$$search),\n\t hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\t\n\t this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n\t this.$$absUrl = appBase + (this.$$url ? hashPrefix + this.$$url : '');\n\t };\n\t\n\t this.$$parseLinkUrl = function(url, relHref) {\n\t if (stripHash(appBase) == stripHash(url)) {\n\t this.$$parse(url);\n\t return true;\n\t }\n\t return false;\n\t };\n\t}\n\t\n\t\n\t/**\n\t * LocationHashbangUrl represents url\n\t * This object is exposed as $location service when html5 history api is enabled but the browser\n\t * does not support it.\n\t *\n\t * @constructor\n\t * @param {string} appBase application base URL\n\t * @param {string} appBaseNoFile application base URL stripped of any filename\n\t * @param {string} hashPrefix hashbang prefix\n\t */\n\tfunction LocationHashbangInHtml5Url(appBase, appBaseNoFile, hashPrefix) {\n\t this.$$html5 = true;\n\t LocationHashbangUrl.apply(this, arguments);\n\t\n\t this.$$parseLinkUrl = function(url, relHref) {\n\t if (relHref && relHref[0] === '#') {\n\t // special case for links to hash fragments:\n\t // keep the old url and only replace the hash fragment\n\t this.hash(relHref.slice(1));\n\t return true;\n\t }\n\t\n\t var rewrittenUrl;\n\t var appUrl;\n\t\n\t if (appBase == stripHash(url)) {\n\t rewrittenUrl = url;\n\t } else if ((appUrl = stripBaseUrl(appBaseNoFile, url))) {\n\t rewrittenUrl = appBase + hashPrefix + appUrl;\n\t } else if (appBaseNoFile === url + '/') {\n\t rewrittenUrl = appBaseNoFile;\n\t }\n\t if (rewrittenUrl) {\n\t this.$$parse(rewrittenUrl);\n\t }\n\t return !!rewrittenUrl;\n\t };\n\t\n\t this.$$compose = function() {\n\t var search = toKeyValue(this.$$search),\n\t hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\t\n\t this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n\t // include hashPrefix in $$absUrl when $$url is empty so IE9 does not reload page because of removal of '#'\n\t this.$$absUrl = appBase + hashPrefix + this.$$url;\n\t };\n\t\n\t}\n\t\n\t\n\tvar locationPrototype = {\n\t\n\t /**\n\t * Ensure absolute url is initialized.\n\t * @private\n\t */\n\t $$absUrl:'',\n\t\n\t /**\n\t * Are we in html5 mode?\n\t * @private\n\t */\n\t $$html5: false,\n\t\n\t /**\n\t * Has any change been replacing?\n\t * @private\n\t */\n\t $$replace: false,\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $location#absUrl\n\t *\n\t * @description\n\t * This method is getter only.\n\t *\n\t * Return full url representation with all segments encoded according to rules specified in\n\t * [RFC 3986](http://www.ietf.org/rfc/rfc3986.txt).\n\t *\n\t *\n\t * ```js\n\t * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n\t * var absUrl = $location.absUrl();\n\t * // => \"http://example.com/#/some/path?foo=bar&baz=xoxo\"\n\t * ```\n\t *\n\t * @return {string} full url\n\t */\n\t absUrl: locationGetter('$$absUrl'),\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $location#url\n\t *\n\t * @description\n\t * This method is getter / setter.\n\t *\n\t * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n\t *\n\t * Change path, search and hash, when called with parameter and return `$location`.\n\t *\n\t *\n\t * ```js\n\t * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n\t * var url = $location.url();\n\t * // => \"/some/path?foo=bar&baz=xoxo\"\n\t * ```\n\t *\n\t * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n\t * @return {string} url\n\t */\n\t url: function(url) {\n\t if (isUndefined(url)) {\n\t return this.$$url;\n\t }\n\t\n\t var match = PATH_MATCH.exec(url);\n\t if (match[1] || url === '') this.path(decodeURIComponent(match[1]));\n\t if (match[2] || match[1] || url === '') this.search(match[3] || '');\n\t this.hash(match[5] || '');\n\t\n\t return this;\n\t },\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $location#protocol\n\t *\n\t * @description\n\t * This method is getter only.\n\t *\n\t * Return protocol of current url.\n\t *\n\t *\n\t * ```js\n\t * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n\t * var protocol = $location.protocol();\n\t * // => \"http\"\n\t * ```\n\t *\n\t * @return {string} protocol of current url\n\t */\n\t protocol: locationGetter('$$protocol'),\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $location#host\n\t *\n\t * @description\n\t * This method is getter only.\n\t *\n\t * Return host of current url.\n\t *\n\t * Note: compared to the non-angular version `location.host` which returns `hostname:port`, this returns the `hostname` portion only.\n\t *\n\t *\n\t * ```js\n\t * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n\t * var host = $location.host();\n\t * // => \"example.com\"\n\t *\n\t * // given url http://user:password@example.com:8080/#/some/path?foo=bar&baz=xoxo\n\t * host = $location.host();\n\t * // => \"example.com\"\n\t * host = location.host;\n\t * // => \"example.com:8080\"\n\t * ```\n\t *\n\t * @return {string} host of current url.\n\t */\n\t host: locationGetter('$$host'),\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $location#port\n\t *\n\t * @description\n\t * This method is getter only.\n\t *\n\t * Return port of current url.\n\t *\n\t *\n\t * ```js\n\t * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n\t * var port = $location.port();\n\t * // => 80\n\t * ```\n\t *\n\t * @return {Number} port\n\t */\n\t port: locationGetter('$$port'),\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $location#path\n\t *\n\t * @description\n\t * This method is getter / setter.\n\t *\n\t * Return path of current url when called without any parameter.\n\t *\n\t * Change path when called with parameter and return `$location`.\n\t *\n\t * Note: Path should always begin with forward slash (/), this method will add the forward slash\n\t * if it is missing.\n\t *\n\t *\n\t * ```js\n\t * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n\t * var path = $location.path();\n\t * // => \"/some/path\"\n\t * ```\n\t *\n\t * @param {(string|number)=} path New path\n\t * @return {(string|object)} path if called with no parameters, or `$location` if called with a parameter\n\t */\n\t path: locationGetterSetter('$$path', function(path) {\n\t path = path !== null ? path.toString() : '';\n\t return path.charAt(0) == '/' ? path : '/' + path;\n\t }),\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $location#search\n\t *\n\t * @description\n\t * This method is getter / setter.\n\t *\n\t * Return search part (as object) of current url when called without any parameter.\n\t *\n\t * Change search part when called with parameter and return `$location`.\n\t *\n\t *\n\t * ```js\n\t * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n\t * var searchObject = $location.search();\n\t * // => {foo: 'bar', baz: 'xoxo'}\n\t *\n\t * // set foo to 'yipee'\n\t * $location.search('foo', 'yipee');\n\t * // $location.search() => {foo: 'yipee', baz: 'xoxo'}\n\t * ```\n\t *\n\t * @param {string|Object.|Object.>} search New search params - string or\n\t * hash object.\n\t *\n\t * When called with a single argument the method acts as a setter, setting the `search` component\n\t * of `$location` to the specified value.\n\t *\n\t * If the argument is a hash object containing an array of values, these values will be encoded\n\t * as duplicate search parameters in the url.\n\t *\n\t * @param {(string|Number|Array|boolean)=} paramValue If `search` is a string or number, then `paramValue`\n\t * will override only a single search property.\n\t *\n\t * If `paramValue` is an array, it will override the property of the `search` component of\n\t * `$location` specified via the first argument.\n\t *\n\t * If `paramValue` is `null`, the property specified via the first argument will be deleted.\n\t *\n\t * If `paramValue` is `true`, the property specified via the first argument will be added with no\n\t * value nor trailing equal sign.\n\t *\n\t * @return {Object} If called with no arguments returns the parsed `search` object. If called with\n\t * one or more arguments returns `$location` object itself.\n\t */\n\t search: function(search, paramValue) {\n\t switch (arguments.length) {\n\t case 0:\n\t return this.$$search;\n\t case 1:\n\t if (isString(search) || isNumber(search)) {\n\t search = search.toString();\n\t this.$$search = parseKeyValue(search);\n\t } else if (isObject(search)) {\n\t search = copy(search, {});\n\t // remove object undefined or null properties\n\t forEach(search, function(value, key) {\n\t if (value == null) delete search[key];\n\t });\n\t\n\t this.$$search = search;\n\t } else {\n\t throw $locationMinErr('isrcharg',\n\t 'The first argument of the `$location#search()` call must be a string or an object.');\n\t }\n\t break;\n\t default:\n\t if (isUndefined(paramValue) || paramValue === null) {\n\t delete this.$$search[search];\n\t } else {\n\t this.$$search[search] = paramValue;\n\t }\n\t }\n\t\n\t this.$$compose();\n\t return this;\n\t },\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $location#hash\n\t *\n\t * @description\n\t * This method is getter / setter.\n\t *\n\t * Returns the hash fragment when called without any parameters.\n\t *\n\t * Changes the hash fragment when called with a parameter and returns `$location`.\n\t *\n\t *\n\t * ```js\n\t * // given url http://example.com/#/some/path?foo=bar&baz=xoxo#hashValue\n\t * var hash = $location.hash();\n\t * // => \"hashValue\"\n\t * ```\n\t *\n\t * @param {(string|number)=} hash New hash fragment\n\t * @return {string} hash\n\t */\n\t hash: locationGetterSetter('$$hash', function(hash) {\n\t return hash !== null ? hash.toString() : '';\n\t }),\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $location#replace\n\t *\n\t * @description\n\t * If called, all changes to $location during the current `$digest` will replace the current history\n\t * record, instead of adding a new one.\n\t */\n\t replace: function() {\n\t this.$$replace = true;\n\t return this;\n\t }\n\t};\n\t\n\tforEach([LocationHashbangInHtml5Url, LocationHashbangUrl, LocationHtml5Url], function(Location) {\n\t Location.prototype = Object.create(locationPrototype);\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $location#state\n\t *\n\t * @description\n\t * This method is getter / setter.\n\t *\n\t * Return the history state object when called without any parameter.\n\t *\n\t * Change the history state object when called with one parameter and return `$location`.\n\t * The state object is later passed to `pushState` or `replaceState`.\n\t *\n\t * NOTE: This method is supported only in HTML5 mode and only in browsers supporting\n\t * the HTML5 History API (i.e. methods `pushState` and `replaceState`). If you need to support\n\t * older browsers (like IE9 or Android < 4.0), don't use this method.\n\t *\n\t * @param {object=} state State object for pushState or replaceState\n\t * @return {object} state\n\t */\n\t Location.prototype.state = function(state) {\n\t if (!arguments.length) {\n\t return this.$$state;\n\t }\n\t\n\t if (Location !== LocationHtml5Url || !this.$$html5) {\n\t throw $locationMinErr('nostate', 'History API state support is available only ' +\n\t 'in HTML5 mode and only in browsers supporting HTML5 History API');\n\t }\n\t // The user might modify `stateObject` after invoking `$location.state(stateObject)`\n\t // but we're changing the $$state reference to $browser.state() during the $digest\n\t // so the modification window is narrow.\n\t this.$$state = isUndefined(state) ? null : state;\n\t\n\t return this;\n\t };\n\t});\n\t\n\t\n\tfunction locationGetter(property) {\n\t return function() {\n\t return this[property];\n\t };\n\t}\n\t\n\t\n\tfunction locationGetterSetter(property, preprocess) {\n\t return function(value) {\n\t if (isUndefined(value)) {\n\t return this[property];\n\t }\n\t\n\t this[property] = preprocess(value);\n\t this.$$compose();\n\t\n\t return this;\n\t };\n\t}\n\t\n\t\n\t/**\n\t * @ngdoc service\n\t * @name $location\n\t *\n\t * @requires $rootElement\n\t *\n\t * @description\n\t * The $location service parses the URL in the browser address bar (based on the\n\t * [window.location](https://developer.mozilla.org/en/window.location)) and makes the URL\n\t * available to your application. Changes to the URL in the address bar are reflected into\n\t * $location service and changes to $location are reflected into the browser address bar.\n\t *\n\t * **The $location service:**\n\t *\n\t * - Exposes the current URL in the browser address bar, so you can\n\t * - Watch and observe the URL.\n\t * - Change the URL.\n\t * - Synchronizes the URL with the browser when the user\n\t * - Changes the address bar.\n\t * - Clicks the back or forward button (or clicks a History link).\n\t * - Clicks on a link.\n\t * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n\t *\n\t * For more information see {@link guide/$location Developer Guide: Using $location}\n\t */\n\t\n\t/**\n\t * @ngdoc provider\n\t * @name $locationProvider\n\t * @description\n\t * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n\t */\n\tfunction $LocationProvider() {\n\t var hashPrefix = '',\n\t html5Mode = {\n\t enabled: false,\n\t requireBase: true,\n\t rewriteLinks: true\n\t };\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $locationProvider#hashPrefix\n\t * @description\n\t * @param {string=} prefix Prefix for hash part (containing path and search)\n\t * @returns {*} current value if used as getter or itself (chaining) if used as setter\n\t */\n\t this.hashPrefix = function(prefix) {\n\t if (isDefined(prefix)) {\n\t hashPrefix = prefix;\n\t return this;\n\t } else {\n\t return hashPrefix;\n\t }\n\t };\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $locationProvider#html5Mode\n\t * @description\n\t * @param {(boolean|Object)=} mode If boolean, sets `html5Mode.enabled` to value.\n\t * If object, sets `enabled`, `requireBase` and `rewriteLinks` to respective values. Supported\n\t * properties:\n\t * - **enabled** – `{boolean}` – (default: false) If true, will rely on `history.pushState` to\n\t * change urls where supported. Will fall back to hash-prefixed paths in browsers that do not\n\t * support `pushState`.\n\t * - **requireBase** - `{boolean}` - (default: `true`) When html5Mode is enabled, specifies\n\t * whether or not a tag is required to be present. If `enabled` and `requireBase` are\n\t * true, and a base tag is not present, an error will be thrown when `$location` is injected.\n\t * See the {@link guide/$location $location guide for more information}\n\t * - **rewriteLinks** - `{boolean}` - (default: `true`) When html5Mode is enabled,\n\t * enables/disables url rewriting for relative links.\n\t *\n\t * @returns {Object} html5Mode object if used as getter or itself (chaining) if used as setter\n\t */\n\t this.html5Mode = function(mode) {\n\t if (isBoolean(mode)) {\n\t html5Mode.enabled = mode;\n\t return this;\n\t } else if (isObject(mode)) {\n\t\n\t if (isBoolean(mode.enabled)) {\n\t html5Mode.enabled = mode.enabled;\n\t }\n\t\n\t if (isBoolean(mode.requireBase)) {\n\t html5Mode.requireBase = mode.requireBase;\n\t }\n\t\n\t if (isBoolean(mode.rewriteLinks)) {\n\t html5Mode.rewriteLinks = mode.rewriteLinks;\n\t }\n\t\n\t return this;\n\t } else {\n\t return html5Mode;\n\t }\n\t };\n\t\n\t /**\n\t * @ngdoc event\n\t * @name $location#$locationChangeStart\n\t * @eventType broadcast on root scope\n\t * @description\n\t * Broadcasted before a URL will change.\n\t *\n\t * This change can be prevented by calling\n\t * `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on} for more\n\t * details about event object. Upon successful change\n\t * {@link ng.$location#$locationChangeSuccess $locationChangeSuccess} is fired.\n\t *\n\t * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when\n\t * the browser supports the HTML5 History API.\n\t *\n\t * @param {Object} angularEvent Synthetic event object.\n\t * @param {string} newUrl New URL\n\t * @param {string=} oldUrl URL that was before it was changed.\n\t * @param {string=} newState New history state object\n\t * @param {string=} oldState History state object that was before it was changed.\n\t */\n\t\n\t /**\n\t * @ngdoc event\n\t * @name $location#$locationChangeSuccess\n\t * @eventType broadcast on root scope\n\t * @description\n\t * Broadcasted after a URL was changed.\n\t *\n\t * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when\n\t * the browser supports the HTML5 History API.\n\t *\n\t * @param {Object} angularEvent Synthetic event object.\n\t * @param {string} newUrl New URL\n\t * @param {string=} oldUrl URL that was before it was changed.\n\t * @param {string=} newState New history state object\n\t * @param {string=} oldState History state object that was before it was changed.\n\t */\n\t\n\t this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement', '$window',\n\t function($rootScope, $browser, $sniffer, $rootElement, $window) {\n\t var $location,\n\t LocationMode,\n\t baseHref = $browser.baseHref(), // if base[href] is undefined, it defaults to ''\n\t initialUrl = $browser.url(),\n\t appBase;\n\t\n\t if (html5Mode.enabled) {\n\t if (!baseHref && html5Mode.requireBase) {\n\t throw $locationMinErr('nobase',\n\t \"$location in HTML5 mode requires a tag to be present!\");\n\t }\n\t appBase = serverBase(initialUrl) + (baseHref || '/');\n\t LocationMode = $sniffer.history ? LocationHtml5Url : LocationHashbangInHtml5Url;\n\t } else {\n\t appBase = stripHash(initialUrl);\n\t LocationMode = LocationHashbangUrl;\n\t }\n\t var appBaseNoFile = stripFile(appBase);\n\t\n\t $location = new LocationMode(appBase, appBaseNoFile, '#' + hashPrefix);\n\t $location.$$parseLinkUrl(initialUrl, initialUrl);\n\t\n\t $location.$$state = $browser.state();\n\t\n\t var IGNORE_URI_REGEXP = /^\\s*(javascript|mailto):/i;\n\t\n\t function setBrowserUrlWithFallback(url, replace, state) {\n\t var oldUrl = $location.url();\n\t var oldState = $location.$$state;\n\t try {\n\t $browser.url(url, replace, state);\n\t\n\t // Make sure $location.state() returns referentially identical (not just deeply equal)\n\t // state object; this makes possible quick checking if the state changed in the digest\n\t // loop. Checking deep equality would be too expensive.\n\t $location.$$state = $browser.state();\n\t } catch (e) {\n\t // Restore old values if pushState fails\n\t $location.url(oldUrl);\n\t $location.$$state = oldState;\n\t\n\t throw e;\n\t }\n\t }\n\t\n\t $rootElement.on('click', function(event) {\n\t // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n\t // currently we open nice url link and redirect then\n\t\n\t if (!html5Mode.rewriteLinks || event.ctrlKey || event.metaKey || event.shiftKey || event.which == 2 || event.button == 2) return;\n\t\n\t var elm = jqLite(event.target);\n\t\n\t // traverse the DOM up to find first A tag\n\t while (nodeName_(elm[0]) !== 'a') {\n\t // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n\t if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n\t }\n\t\n\t var absHref = elm.prop('href');\n\t // get the actual href attribute - see\n\t // http://msdn.microsoft.com/en-us/library/ie/dd347148(v=vs.85).aspx\n\t var relHref = elm.attr('href') || elm.attr('xlink:href');\n\t\n\t if (isObject(absHref) && absHref.toString() === '[object SVGAnimatedString]') {\n\t // SVGAnimatedString.animVal should be identical to SVGAnimatedString.baseVal, unless during\n\t // an animation.\n\t absHref = urlResolve(absHref.animVal).href;\n\t }\n\t\n\t // Ignore when url is started with javascript: or mailto:\n\t if (IGNORE_URI_REGEXP.test(absHref)) return;\n\t\n\t if (absHref && !elm.attr('target') && !event.isDefaultPrevented()) {\n\t if ($location.$$parseLinkUrl(absHref, relHref)) {\n\t // We do a preventDefault for all urls that are part of the angular application,\n\t // in html5mode and also without, so that we are able to abort navigation without\n\t // getting double entries in the location history.\n\t event.preventDefault();\n\t // update location manually\n\t if ($location.absUrl() != $browser.url()) {\n\t $rootScope.$apply();\n\t // hack to work around FF6 bug 684208 when scenario runner clicks on links\n\t $window.angular['ff-684208-preventDefault'] = true;\n\t }\n\t }\n\t }\n\t });\n\t\n\t\n\t // rewrite hashbang url <> html5 url\n\t if (trimEmptyHash($location.absUrl()) != trimEmptyHash(initialUrl)) {\n\t $browser.url($location.absUrl(), true);\n\t }\n\t\n\t var initializing = true;\n\t\n\t // update $location when $browser url changes\n\t $browser.onUrlChange(function(newUrl, newState) {\n\t\n\t if (isUndefined(stripBaseUrl(appBaseNoFile, newUrl))) {\n\t // If we are navigating outside of the app then force a reload\n\t $window.location.href = newUrl;\n\t return;\n\t }\n\t\n\t $rootScope.$evalAsync(function() {\n\t var oldUrl = $location.absUrl();\n\t var oldState = $location.$$state;\n\t var defaultPrevented;\n\t newUrl = trimEmptyHash(newUrl);\n\t $location.$$parse(newUrl);\n\t $location.$$state = newState;\n\t\n\t defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl,\n\t newState, oldState).defaultPrevented;\n\t\n\t // if the location was changed by a `$locationChangeStart` handler then stop\n\t // processing this location change\n\t if ($location.absUrl() !== newUrl) return;\n\t\n\t if (defaultPrevented) {\n\t $location.$$parse(oldUrl);\n\t $location.$$state = oldState;\n\t setBrowserUrlWithFallback(oldUrl, false, oldState);\n\t } else {\n\t initializing = false;\n\t afterLocationChange(oldUrl, oldState);\n\t }\n\t });\n\t if (!$rootScope.$$phase) $rootScope.$digest();\n\t });\n\t\n\t // update browser\n\t $rootScope.$watch(function $locationWatch() {\n\t var oldUrl = trimEmptyHash($browser.url());\n\t var newUrl = trimEmptyHash($location.absUrl());\n\t var oldState = $browser.state();\n\t var currentReplace = $location.$$replace;\n\t var urlOrStateChanged = oldUrl !== newUrl ||\n\t ($location.$$html5 && $sniffer.history && oldState !== $location.$$state);\n\t\n\t if (initializing || urlOrStateChanged) {\n\t initializing = false;\n\t\n\t $rootScope.$evalAsync(function() {\n\t var newUrl = $location.absUrl();\n\t var defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl,\n\t $location.$$state, oldState).defaultPrevented;\n\t\n\t // if the location was changed by a `$locationChangeStart` handler then stop\n\t // processing this location change\n\t if ($location.absUrl() !== newUrl) return;\n\t\n\t if (defaultPrevented) {\n\t $location.$$parse(oldUrl);\n\t $location.$$state = oldState;\n\t } else {\n\t if (urlOrStateChanged) {\n\t setBrowserUrlWithFallback(newUrl, currentReplace,\n\t oldState === $location.$$state ? null : $location.$$state);\n\t }\n\t afterLocationChange(oldUrl, oldState);\n\t }\n\t });\n\t }\n\t\n\t $location.$$replace = false;\n\t\n\t // we don't need to return anything because $evalAsync will make the digest loop dirty when\n\t // there is a change\n\t });\n\t\n\t return $location;\n\t\n\t function afterLocationChange(oldUrl, oldState) {\n\t $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl,\n\t $location.$$state, oldState);\n\t }\n\t}];\n\t}\n\t\n\t/**\n\t * @ngdoc service\n\t * @name $log\n\t * @requires $window\n\t *\n\t * @description\n\t * Simple service for logging. Default implementation safely writes the message\n\t * into the browser's console (if present).\n\t *\n\t * The main purpose of this service is to simplify debugging and troubleshooting.\n\t *\n\t * The default is to log `debug` messages. You can use\n\t * {@link ng.$logProvider ng.$logProvider#debugEnabled} to change this.\n\t *\n\t * @example\n\t \n\t \n\t angular.module('logExample', [])\n\t .controller('LogController', ['$scope', '$log', function($scope, $log) {\n\t $scope.$log = $log;\n\t $scope.message = 'Hello World!';\n\t }]);\n\t \n\t \n\t
\n\t

Reload this page with open console, enter text and hit the log button...

\n\t \n\t \n\t \n\t \n\t \n\t \n\t
\n\t
\n\t
\n\t */\n\t\n\t/**\n\t * @ngdoc provider\n\t * @name $logProvider\n\t * @description\n\t * Use the `$logProvider` to configure how the application logs messages\n\t */\n\tfunction $LogProvider() {\n\t var debug = true,\n\t self = this;\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $logProvider#debugEnabled\n\t * @description\n\t * @param {boolean=} flag enable or disable debug level messages\n\t * @returns {*} current value if used as getter or itself (chaining) if used as setter\n\t */\n\t this.debugEnabled = function(flag) {\n\t if (isDefined(flag)) {\n\t debug = flag;\n\t return this;\n\t } else {\n\t return debug;\n\t }\n\t };\n\t\n\t this.$get = ['$window', function($window) {\n\t return {\n\t /**\n\t * @ngdoc method\n\t * @name $log#log\n\t *\n\t * @description\n\t * Write a log message\n\t */\n\t log: consoleLog('log'),\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $log#info\n\t *\n\t * @description\n\t * Write an information message\n\t */\n\t info: consoleLog('info'),\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $log#warn\n\t *\n\t * @description\n\t * Write a warning message\n\t */\n\t warn: consoleLog('warn'),\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $log#error\n\t *\n\t * @description\n\t * Write an error message\n\t */\n\t error: consoleLog('error'),\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $log#debug\n\t *\n\t * @description\n\t * Write a debug message\n\t */\n\t debug: (function() {\n\t var fn = consoleLog('debug');\n\t\n\t return function() {\n\t if (debug) {\n\t fn.apply(self, arguments);\n\t }\n\t };\n\t }())\n\t };\n\t\n\t function formatError(arg) {\n\t if (arg instanceof Error) {\n\t if (arg.stack) {\n\t arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n\t ? 'Error: ' + arg.message + '\\n' + arg.stack\n\t : arg.stack;\n\t } else if (arg.sourceURL) {\n\t arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n\t }\n\t }\n\t return arg;\n\t }\n\t\n\t function consoleLog(type) {\n\t var console = $window.console || {},\n\t logFn = console[type] || console.log || noop,\n\t hasApply = false;\n\t\n\t // Note: reading logFn.apply throws an error in IE11 in IE8 document mode.\n\t // The reason behind this is that console.log has type \"object\" in IE8...\n\t try {\n\t hasApply = !!logFn.apply;\n\t } catch (e) {}\n\t\n\t if (hasApply) {\n\t return function() {\n\t var args = [];\n\t forEach(arguments, function(arg) {\n\t args.push(formatError(arg));\n\t });\n\t return logFn.apply(console, args);\n\t };\n\t }\n\t\n\t // we are IE which either doesn't have window.console => this is noop and we do nothing,\n\t // or we are IE where console.log doesn't have apply so we log at least first 2 args\n\t return function(arg1, arg2) {\n\t logFn(arg1, arg2 == null ? '' : arg2);\n\t };\n\t }\n\t }];\n\t}\n\t\n\t/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n\t * Any commits to this file should be reviewed with security in mind. *\n\t * Changes to this file can potentially create security vulnerabilities. *\n\t * An approval from 2 Core members with history of modifying *\n\t * this file is required. *\n\t * *\n\t * Does the change somehow allow for arbitrary javascript to be executed? *\n\t * Or allows for someone to change the prototype of built-in objects? *\n\t * Or gives undesired access to variables likes document or window? *\n\t * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */\n\t\n\tvar $parseMinErr = minErr('$parse');\n\t\n\t// Sandboxing Angular Expressions\n\t// ------------------------------\n\t// Angular expressions are generally considered safe because these expressions only have direct\n\t// access to `$scope` and locals. However, one can obtain the ability to execute arbitrary JS code by\n\t// obtaining a reference to native JS functions such as the Function constructor.\n\t//\n\t// As an example, consider the following Angular expression:\n\t//\n\t// {}.toString.constructor('alert(\"evil JS code\")')\n\t//\n\t// This sandboxing technique is not perfect and doesn't aim to be. The goal is to prevent exploits\n\t// against the expression language, but not to prevent exploits that were enabled by exposing\n\t// sensitive JavaScript or browser APIs on Scope. Exposing such objects on a Scope is never a good\n\t// practice and therefore we are not even trying to protect against interaction with an object\n\t// explicitly exposed in this way.\n\t//\n\t// In general, it is not possible to access a Window object from an angular expression unless a\n\t// window or some DOM object that has a reference to window is published onto a Scope.\n\t// Similarly we prevent invocations of function known to be dangerous, as well as assignments to\n\t// native objects.\n\t//\n\t// See https://docs.angularjs.org/guide/security\n\t\n\t\n\tfunction ensureSafeMemberName(name, fullExpression) {\n\t if (name === \"__defineGetter__\" || name === \"__defineSetter__\"\n\t || name === \"__lookupGetter__\" || name === \"__lookupSetter__\"\n\t || name === \"__proto__\") {\n\t throw $parseMinErr('isecfld',\n\t 'Attempting to access a disallowed field in Angular expressions! '\n\t + 'Expression: {0}', fullExpression);\n\t }\n\t return name;\n\t}\n\t\n\tfunction getStringValue(name) {\n\t // Property names must be strings. This means that non-string objects cannot be used\n\t // as keys in an object. Any non-string object, including a number, is typecasted\n\t // into a string via the toString method.\n\t // -- MDN, https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Property_accessors#Property_names\n\t //\n\t // So, to ensure that we are checking the same `name` that JavaScript would use, we cast it\n\t // to a string. It's not always possible. If `name` is an object and its `toString` method is\n\t // 'broken' (doesn't return a string, isn't a function, etc.), an error will be thrown:\n\t //\n\t // TypeError: Cannot convert object to primitive value\n\t //\n\t // For performance reasons, we don't catch this error here and allow it to propagate up the call\n\t // stack. Note that you'll get the same error in JavaScript if you try to access a property using\n\t // such a 'broken' object as a key.\n\t return name + '';\n\t}\n\t\n\tfunction ensureSafeObject(obj, fullExpression) {\n\t // nifty check if obj is Function that is fast and works across iframes and other contexts\n\t if (obj) {\n\t if (obj.constructor === obj) {\n\t throw $parseMinErr('isecfn',\n\t 'Referencing Function in Angular expressions is disallowed! Expression: {0}',\n\t fullExpression);\n\t } else if (// isWindow(obj)\n\t obj.window === obj) {\n\t throw $parseMinErr('isecwindow',\n\t 'Referencing the Window in Angular expressions is disallowed! Expression: {0}',\n\t fullExpression);\n\t } else if (// isElement(obj)\n\t obj.children && (obj.nodeName || (obj.prop && obj.attr && obj.find))) {\n\t throw $parseMinErr('isecdom',\n\t 'Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}',\n\t fullExpression);\n\t } else if (// block Object so that we can't get hold of dangerous Object.* methods\n\t obj === Object) {\n\t throw $parseMinErr('isecobj',\n\t 'Referencing Object in Angular expressions is disallowed! Expression: {0}',\n\t fullExpression);\n\t }\n\t }\n\t return obj;\n\t}\n\t\n\tvar CALL = Function.prototype.call;\n\tvar APPLY = Function.prototype.apply;\n\tvar BIND = Function.prototype.bind;\n\t\n\tfunction ensureSafeFunction(obj, fullExpression) {\n\t if (obj) {\n\t if (obj.constructor === obj) {\n\t throw $parseMinErr('isecfn',\n\t 'Referencing Function in Angular expressions is disallowed! Expression: {0}',\n\t fullExpression);\n\t } else if (obj === CALL || obj === APPLY || obj === BIND) {\n\t throw $parseMinErr('isecff',\n\t 'Referencing call, apply or bind in Angular expressions is disallowed! Expression: {0}',\n\t fullExpression);\n\t }\n\t }\n\t}\n\t\n\tfunction ensureSafeAssignContext(obj, fullExpression) {\n\t if (obj) {\n\t if (obj === (0).constructor || obj === (false).constructor || obj === ''.constructor ||\n\t obj === {}.constructor || obj === [].constructor || obj === Function.constructor) {\n\t throw $parseMinErr('isecaf',\n\t 'Assigning to a constructor is disallowed! Expression: {0}', fullExpression);\n\t }\n\t }\n\t}\n\t\n\tvar OPERATORS = createMap();\n\tforEach('+ - * / % === !== == != < > <= >= && || ! = |'.split(' '), function(operator) { OPERATORS[operator] = true; });\n\tvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\t\n\t\n\t/////////////////////////////////////////\n\t\n\t\n\t/**\n\t * @constructor\n\t */\n\tvar Lexer = function(options) {\n\t this.options = options;\n\t};\n\t\n\tLexer.prototype = {\n\t constructor: Lexer,\n\t\n\t lex: function(text) {\n\t this.text = text;\n\t this.index = 0;\n\t this.tokens = [];\n\t\n\t while (this.index < this.text.length) {\n\t var ch = this.text.charAt(this.index);\n\t if (ch === '\"' || ch === \"'\") {\n\t this.readString(ch);\n\t } else if (this.isNumber(ch) || ch === '.' && this.isNumber(this.peek())) {\n\t this.readNumber();\n\t } else if (this.isIdentifierStart(this.peekMultichar())) {\n\t this.readIdent();\n\t } else if (this.is(ch, '(){}[].,;:?')) {\n\t this.tokens.push({index: this.index, text: ch});\n\t this.index++;\n\t } else if (this.isWhitespace(ch)) {\n\t this.index++;\n\t } else {\n\t var ch2 = ch + this.peek();\n\t var ch3 = ch2 + this.peek(2);\n\t var op1 = OPERATORS[ch];\n\t var op2 = OPERATORS[ch2];\n\t var op3 = OPERATORS[ch3];\n\t if (op1 || op2 || op3) {\n\t var token = op3 ? ch3 : (op2 ? ch2 : ch);\n\t this.tokens.push({index: this.index, text: token, operator: true});\n\t this.index += token.length;\n\t } else {\n\t this.throwError('Unexpected next character ', this.index, this.index + 1);\n\t }\n\t }\n\t }\n\t return this.tokens;\n\t },\n\t\n\t is: function(ch, chars) {\n\t return chars.indexOf(ch) !== -1;\n\t },\n\t\n\t peek: function(i) {\n\t var num = i || 1;\n\t return (this.index + num < this.text.length) ? this.text.charAt(this.index + num) : false;\n\t },\n\t\n\t isNumber: function(ch) {\n\t return ('0' <= ch && ch <= '9') && typeof ch === \"string\";\n\t },\n\t\n\t isWhitespace: function(ch) {\n\t // IE treats non-breaking space as \\u00A0\n\t return (ch === ' ' || ch === '\\r' || ch === '\\t' ||\n\t ch === '\\n' || ch === '\\v' || ch === '\\u00A0');\n\t },\n\t\n\t isIdentifierStart: function(ch) {\n\t return this.options.isIdentifierStart ?\n\t this.options.isIdentifierStart(ch, this.codePointAt(ch)) :\n\t this.isValidIdentifierStart(ch);\n\t },\n\t\n\t isValidIdentifierStart: function(ch) {\n\t return ('a' <= ch && ch <= 'z' ||\n\t 'A' <= ch && ch <= 'Z' ||\n\t '_' === ch || ch === '$');\n\t },\n\t\n\t isIdentifierContinue: function(ch) {\n\t return this.options.isIdentifierContinue ?\n\t this.options.isIdentifierContinue(ch, this.codePointAt(ch)) :\n\t this.isValidIdentifierContinue(ch);\n\t },\n\t\n\t isValidIdentifierContinue: function(ch, cp) {\n\t return this.isValidIdentifierStart(ch, cp) || this.isNumber(ch);\n\t },\n\t\n\t codePointAt: function(ch) {\n\t if (ch.length === 1) return ch.charCodeAt(0);\n\t /*jshint bitwise: false*/\n\t return (ch.charCodeAt(0) << 10) + ch.charCodeAt(1) - 0x35FDC00;\n\t /*jshint bitwise: true*/\n\t },\n\t\n\t peekMultichar: function() {\n\t var ch = this.text.charAt(this.index);\n\t var peek = this.peek();\n\t if (!peek) {\n\t return ch;\n\t }\n\t var cp1 = ch.charCodeAt(0);\n\t var cp2 = peek.charCodeAt(0);\n\t if (cp1 >= 0xD800 && cp1 <= 0xDBFF && cp2 >= 0xDC00 && cp2 <= 0xDFFF) {\n\t return ch + peek;\n\t }\n\t return ch;\n\t },\n\t\n\t isExpOperator: function(ch) {\n\t return (ch === '-' || ch === '+' || this.isNumber(ch));\n\t },\n\t\n\t throwError: function(error, start, end) {\n\t end = end || this.index;\n\t var colStr = (isDefined(start)\n\t ? 's ' + start + '-' + this.index + ' [' + this.text.substring(start, end) + ']'\n\t : ' ' + end);\n\t throw $parseMinErr('lexerr', 'Lexer Error: {0} at column{1} in expression [{2}].',\n\t error, colStr, this.text);\n\t },\n\t\n\t readNumber: function() {\n\t var number = '';\n\t var start = this.index;\n\t while (this.index < this.text.length) {\n\t var ch = lowercase(this.text.charAt(this.index));\n\t if (ch == '.' || this.isNumber(ch)) {\n\t number += ch;\n\t } else {\n\t var peekCh = this.peek();\n\t if (ch == 'e' && this.isExpOperator(peekCh)) {\n\t number += ch;\n\t } else if (this.isExpOperator(ch) &&\n\t peekCh && this.isNumber(peekCh) &&\n\t number.charAt(number.length - 1) == 'e') {\n\t number += ch;\n\t } else if (this.isExpOperator(ch) &&\n\t (!peekCh || !this.isNumber(peekCh)) &&\n\t number.charAt(number.length - 1) == 'e') {\n\t this.throwError('Invalid exponent');\n\t } else {\n\t break;\n\t }\n\t }\n\t this.index++;\n\t }\n\t this.tokens.push({\n\t index: start,\n\t text: number,\n\t constant: true,\n\t value: Number(number)\n\t });\n\t },\n\t\n\t readIdent: function() {\n\t var start = this.index;\n\t this.index += this.peekMultichar().length;\n\t while (this.index < this.text.length) {\n\t var ch = this.peekMultichar();\n\t if (!this.isIdentifierContinue(ch)) {\n\t break;\n\t }\n\t this.index += ch.length;\n\t }\n\t this.tokens.push({\n\t index: start,\n\t text: this.text.slice(start, this.index),\n\t identifier: true\n\t });\n\t },\n\t\n\t readString: function(quote) {\n\t var start = this.index;\n\t this.index++;\n\t var string = '';\n\t var rawString = quote;\n\t var escape = false;\n\t while (this.index < this.text.length) {\n\t var ch = this.text.charAt(this.index);\n\t rawString += ch;\n\t if (escape) {\n\t if (ch === 'u') {\n\t var hex = this.text.substring(this.index + 1, this.index + 5);\n\t if (!hex.match(/[\\da-f]{4}/i)) {\n\t this.throwError('Invalid unicode escape [\\\\u' + hex + ']');\n\t }\n\t this.index += 4;\n\t string += String.fromCharCode(parseInt(hex, 16));\n\t } else {\n\t var rep = ESCAPE[ch];\n\t string = string + (rep || ch);\n\t }\n\t escape = false;\n\t } else if (ch === '\\\\') {\n\t escape = true;\n\t } else if (ch === quote) {\n\t this.index++;\n\t this.tokens.push({\n\t index: start,\n\t text: rawString,\n\t constant: true,\n\t value: string\n\t });\n\t return;\n\t } else {\n\t string += ch;\n\t }\n\t this.index++;\n\t }\n\t this.throwError('Unterminated quote', start);\n\t }\n\t};\n\t\n\tvar AST = function(lexer, options) {\n\t this.lexer = lexer;\n\t this.options = options;\n\t};\n\t\n\tAST.Program = 'Program';\n\tAST.ExpressionStatement = 'ExpressionStatement';\n\tAST.AssignmentExpression = 'AssignmentExpression';\n\tAST.ConditionalExpression = 'ConditionalExpression';\n\tAST.LogicalExpression = 'LogicalExpression';\n\tAST.BinaryExpression = 'BinaryExpression';\n\tAST.UnaryExpression = 'UnaryExpression';\n\tAST.CallExpression = 'CallExpression';\n\tAST.MemberExpression = 'MemberExpression';\n\tAST.Identifier = 'Identifier';\n\tAST.Literal = 'Literal';\n\tAST.ArrayExpression = 'ArrayExpression';\n\tAST.Property = 'Property';\n\tAST.ObjectExpression = 'ObjectExpression';\n\tAST.ThisExpression = 'ThisExpression';\n\tAST.LocalsExpression = 'LocalsExpression';\n\t\n\t// Internal use only\n\tAST.NGValueParameter = 'NGValueParameter';\n\t\n\tAST.prototype = {\n\t ast: function(text) {\n\t this.text = text;\n\t this.tokens = this.lexer.lex(text);\n\t\n\t var value = this.program();\n\t\n\t if (this.tokens.length !== 0) {\n\t this.throwError('is an unexpected token', this.tokens[0]);\n\t }\n\t\n\t return value;\n\t },\n\t\n\t program: function() {\n\t var body = [];\n\t while (true) {\n\t if (this.tokens.length > 0 && !this.peek('}', ')', ';', ']'))\n\t body.push(this.expressionStatement());\n\t if (!this.expect(';')) {\n\t return { type: AST.Program, body: body};\n\t }\n\t }\n\t },\n\t\n\t expressionStatement: function() {\n\t return { type: AST.ExpressionStatement, expression: this.filterChain() };\n\t },\n\t\n\t filterChain: function() {\n\t var left = this.expression();\n\t var token;\n\t while ((token = this.expect('|'))) {\n\t left = this.filter(left);\n\t }\n\t return left;\n\t },\n\t\n\t expression: function() {\n\t return this.assignment();\n\t },\n\t\n\t assignment: function() {\n\t var result = this.ternary();\n\t if (this.expect('=')) {\n\t result = { type: AST.AssignmentExpression, left: result, right: this.assignment(), operator: '='};\n\t }\n\t return result;\n\t },\n\t\n\t ternary: function() {\n\t var test = this.logicalOR();\n\t var alternate;\n\t var consequent;\n\t if (this.expect('?')) {\n\t alternate = this.expression();\n\t if (this.consume(':')) {\n\t consequent = this.expression();\n\t return { type: AST.ConditionalExpression, test: test, alternate: alternate, consequent: consequent};\n\t }\n\t }\n\t return test;\n\t },\n\t\n\t logicalOR: function() {\n\t var left = this.logicalAND();\n\t while (this.expect('||')) {\n\t left = { type: AST.LogicalExpression, operator: '||', left: left, right: this.logicalAND() };\n\t }\n\t return left;\n\t },\n\t\n\t logicalAND: function() {\n\t var left = this.equality();\n\t while (this.expect('&&')) {\n\t left = { type: AST.LogicalExpression, operator: '&&', left: left, right: this.equality()};\n\t }\n\t return left;\n\t },\n\t\n\t equality: function() {\n\t var left = this.relational();\n\t var token;\n\t while ((token = this.expect('==','!=','===','!=='))) {\n\t left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.relational() };\n\t }\n\t return left;\n\t },\n\t\n\t relational: function() {\n\t var left = this.additive();\n\t var token;\n\t while ((token = this.expect('<', '>', '<=', '>='))) {\n\t left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.additive() };\n\t }\n\t return left;\n\t },\n\t\n\t additive: function() {\n\t var left = this.multiplicative();\n\t var token;\n\t while ((token = this.expect('+','-'))) {\n\t left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.multiplicative() };\n\t }\n\t return left;\n\t },\n\t\n\t multiplicative: function() {\n\t var left = this.unary();\n\t var token;\n\t while ((token = this.expect('*','/','%'))) {\n\t left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.unary() };\n\t }\n\t return left;\n\t },\n\t\n\t unary: function() {\n\t var token;\n\t if ((token = this.expect('+', '-', '!'))) {\n\t return { type: AST.UnaryExpression, operator: token.text, prefix: true, argument: this.unary() };\n\t } else {\n\t return this.primary();\n\t }\n\t },\n\t\n\t primary: function() {\n\t var primary;\n\t if (this.expect('(')) {\n\t primary = this.filterChain();\n\t this.consume(')');\n\t } else if (this.expect('[')) {\n\t primary = this.arrayDeclaration();\n\t } else if (this.expect('{')) {\n\t primary = this.object();\n\t } else if (this.selfReferential.hasOwnProperty(this.peek().text)) {\n\t primary = copy(this.selfReferential[this.consume().text]);\n\t } else if (this.options.literals.hasOwnProperty(this.peek().text)) {\n\t primary = { type: AST.Literal, value: this.options.literals[this.consume().text]};\n\t } else if (this.peek().identifier) {\n\t primary = this.identifier();\n\t } else if (this.peek().constant) {\n\t primary = this.constant();\n\t } else {\n\t this.throwError('not a primary expression', this.peek());\n\t }\n\t\n\t var next;\n\t while ((next = this.expect('(', '[', '.'))) {\n\t if (next.text === '(') {\n\t primary = {type: AST.CallExpression, callee: primary, arguments: this.parseArguments() };\n\t this.consume(')');\n\t } else if (next.text === '[') {\n\t primary = { type: AST.MemberExpression, object: primary, property: this.expression(), computed: true };\n\t this.consume(']');\n\t } else if (next.text === '.') {\n\t primary = { type: AST.MemberExpression, object: primary, property: this.identifier(), computed: false };\n\t } else {\n\t this.throwError('IMPOSSIBLE');\n\t }\n\t }\n\t return primary;\n\t },\n\t\n\t filter: function(baseExpression) {\n\t var args = [baseExpression];\n\t var result = {type: AST.CallExpression, callee: this.identifier(), arguments: args, filter: true};\n\t\n\t while (this.expect(':')) {\n\t args.push(this.expression());\n\t }\n\t\n\t return result;\n\t },\n\t\n\t parseArguments: function() {\n\t var args = [];\n\t if (this.peekToken().text !== ')') {\n\t do {\n\t args.push(this.filterChain());\n\t } while (this.expect(','));\n\t }\n\t return args;\n\t },\n\t\n\t identifier: function() {\n\t var token = this.consume();\n\t if (!token.identifier) {\n\t this.throwError('is not a valid identifier', token);\n\t }\n\t return { type: AST.Identifier, name: token.text };\n\t },\n\t\n\t constant: function() {\n\t // TODO check that it is a constant\n\t return { type: AST.Literal, value: this.consume().value };\n\t },\n\t\n\t arrayDeclaration: function() {\n\t var elements = [];\n\t if (this.peekToken().text !== ']') {\n\t do {\n\t if (this.peek(']')) {\n\t // Support trailing commas per ES5.1.\n\t break;\n\t }\n\t elements.push(this.expression());\n\t } while (this.expect(','));\n\t }\n\t this.consume(']');\n\t\n\t return { type: AST.ArrayExpression, elements: elements };\n\t },\n\t\n\t object: function() {\n\t var properties = [], property;\n\t if (this.peekToken().text !== '}') {\n\t do {\n\t if (this.peek('}')) {\n\t // Support trailing commas per ES5.1.\n\t break;\n\t }\n\t property = {type: AST.Property, kind: 'init'};\n\t if (this.peek().constant) {\n\t property.key = this.constant();\n\t property.computed = false;\n\t this.consume(':');\n\t property.value = this.expression();\n\t } else if (this.peek().identifier) {\n\t property.key = this.identifier();\n\t property.computed = false;\n\t if (this.peek(':')) {\n\t this.consume(':');\n\t property.value = this.expression();\n\t } else {\n\t property.value = property.key;\n\t }\n\t } else if (this.peek('[')) {\n\t this.consume('[');\n\t property.key = this.expression();\n\t this.consume(']');\n\t property.computed = true;\n\t this.consume(':');\n\t property.value = this.expression();\n\t } else {\n\t this.throwError(\"invalid key\", this.peek());\n\t }\n\t properties.push(property);\n\t } while (this.expect(','));\n\t }\n\t this.consume('}');\n\t\n\t return {type: AST.ObjectExpression, properties: properties };\n\t },\n\t\n\t throwError: function(msg, token) {\n\t throw $parseMinErr('syntax',\n\t 'Syntax Error: Token \\'{0}\\' {1} at column {2} of the expression [{3}] starting at [{4}].',\n\t token.text, msg, (token.index + 1), this.text, this.text.substring(token.index));\n\t },\n\t\n\t consume: function(e1) {\n\t if (this.tokens.length === 0) {\n\t throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text);\n\t }\n\t\n\t var token = this.expect(e1);\n\t if (!token) {\n\t this.throwError('is unexpected, expecting [' + e1 + ']', this.peek());\n\t }\n\t return token;\n\t },\n\t\n\t peekToken: function() {\n\t if (this.tokens.length === 0) {\n\t throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text);\n\t }\n\t return this.tokens[0];\n\t },\n\t\n\t peek: function(e1, e2, e3, e4) {\n\t return this.peekAhead(0, e1, e2, e3, e4);\n\t },\n\t\n\t peekAhead: function(i, e1, e2, e3, e4) {\n\t if (this.tokens.length > i) {\n\t var token = this.tokens[i];\n\t var t = token.text;\n\t if (t === e1 || t === e2 || t === e3 || t === e4 ||\n\t (!e1 && !e2 && !e3 && !e4)) {\n\t return token;\n\t }\n\t }\n\t return false;\n\t },\n\t\n\t expect: function(e1, e2, e3, e4) {\n\t var token = this.peek(e1, e2, e3, e4);\n\t if (token) {\n\t this.tokens.shift();\n\t return token;\n\t }\n\t return false;\n\t },\n\t\n\t selfReferential: {\n\t 'this': {type: AST.ThisExpression },\n\t '$locals': {type: AST.LocalsExpression }\n\t }\n\t};\n\t\n\tfunction ifDefined(v, d) {\n\t return typeof v !== 'undefined' ? v : d;\n\t}\n\t\n\tfunction plusFn(l, r) {\n\t if (typeof l === 'undefined') return r;\n\t if (typeof r === 'undefined') return l;\n\t return l + r;\n\t}\n\t\n\tfunction isStateless($filter, filterName) {\n\t var fn = $filter(filterName);\n\t return !fn.$stateful;\n\t}\n\t\n\tfunction findConstantAndWatchExpressions(ast, $filter) {\n\t var allConstants;\n\t var argsToWatch;\n\t switch (ast.type) {\n\t case AST.Program:\n\t allConstants = true;\n\t forEach(ast.body, function(expr) {\n\t findConstantAndWatchExpressions(expr.expression, $filter);\n\t allConstants = allConstants && expr.expression.constant;\n\t });\n\t ast.constant = allConstants;\n\t break;\n\t case AST.Literal:\n\t ast.constant = true;\n\t ast.toWatch = [];\n\t break;\n\t case AST.UnaryExpression:\n\t findConstantAndWatchExpressions(ast.argument, $filter);\n\t ast.constant = ast.argument.constant;\n\t ast.toWatch = ast.argument.toWatch;\n\t break;\n\t case AST.BinaryExpression:\n\t findConstantAndWatchExpressions(ast.left, $filter);\n\t findConstantAndWatchExpressions(ast.right, $filter);\n\t ast.constant = ast.left.constant && ast.right.constant;\n\t ast.toWatch = ast.left.toWatch.concat(ast.right.toWatch);\n\t break;\n\t case AST.LogicalExpression:\n\t findConstantAndWatchExpressions(ast.left, $filter);\n\t findConstantAndWatchExpressions(ast.right, $filter);\n\t ast.constant = ast.left.constant && ast.right.constant;\n\t ast.toWatch = ast.constant ? [] : [ast];\n\t break;\n\t case AST.ConditionalExpression:\n\t findConstantAndWatchExpressions(ast.test, $filter);\n\t findConstantAndWatchExpressions(ast.alternate, $filter);\n\t findConstantAndWatchExpressions(ast.consequent, $filter);\n\t ast.constant = ast.test.constant && ast.alternate.constant && ast.consequent.constant;\n\t ast.toWatch = ast.constant ? [] : [ast];\n\t break;\n\t case AST.Identifier:\n\t ast.constant = false;\n\t ast.toWatch = [ast];\n\t break;\n\t case AST.MemberExpression:\n\t findConstantAndWatchExpressions(ast.object, $filter);\n\t if (ast.computed) {\n\t findConstantAndWatchExpressions(ast.property, $filter);\n\t }\n\t ast.constant = ast.object.constant && (!ast.computed || ast.property.constant);\n\t ast.toWatch = [ast];\n\t break;\n\t case AST.CallExpression:\n\t allConstants = ast.filter ? isStateless($filter, ast.callee.name) : false;\n\t argsToWatch = [];\n\t forEach(ast.arguments, function(expr) {\n\t findConstantAndWatchExpressions(expr, $filter);\n\t allConstants = allConstants && expr.constant;\n\t if (!expr.constant) {\n\t argsToWatch.push.apply(argsToWatch, expr.toWatch);\n\t }\n\t });\n\t ast.constant = allConstants;\n\t ast.toWatch = ast.filter && isStateless($filter, ast.callee.name) ? argsToWatch : [ast];\n\t break;\n\t case AST.AssignmentExpression:\n\t findConstantAndWatchExpressions(ast.left, $filter);\n\t findConstantAndWatchExpressions(ast.right, $filter);\n\t ast.constant = ast.left.constant && ast.right.constant;\n\t ast.toWatch = [ast];\n\t break;\n\t case AST.ArrayExpression:\n\t allConstants = true;\n\t argsToWatch = [];\n\t forEach(ast.elements, function(expr) {\n\t findConstantAndWatchExpressions(expr, $filter);\n\t allConstants = allConstants && expr.constant;\n\t if (!expr.constant) {\n\t argsToWatch.push.apply(argsToWatch, expr.toWatch);\n\t }\n\t });\n\t ast.constant = allConstants;\n\t ast.toWatch = argsToWatch;\n\t break;\n\t case AST.ObjectExpression:\n\t allConstants = true;\n\t argsToWatch = [];\n\t forEach(ast.properties, function(property) {\n\t findConstantAndWatchExpressions(property.value, $filter);\n\t allConstants = allConstants && property.value.constant && !property.computed;\n\t if (!property.value.constant) {\n\t argsToWatch.push.apply(argsToWatch, property.value.toWatch);\n\t }\n\t });\n\t ast.constant = allConstants;\n\t ast.toWatch = argsToWatch;\n\t break;\n\t case AST.ThisExpression:\n\t ast.constant = false;\n\t ast.toWatch = [];\n\t break;\n\t case AST.LocalsExpression:\n\t ast.constant = false;\n\t ast.toWatch = [];\n\t break;\n\t }\n\t}\n\t\n\tfunction getInputs(body) {\n\t if (body.length != 1) return;\n\t var lastExpression = body[0].expression;\n\t var candidate = lastExpression.toWatch;\n\t if (candidate.length !== 1) return candidate;\n\t return candidate[0] !== lastExpression ? candidate : undefined;\n\t}\n\t\n\tfunction isAssignable(ast) {\n\t return ast.type === AST.Identifier || ast.type === AST.MemberExpression;\n\t}\n\t\n\tfunction assignableAST(ast) {\n\t if (ast.body.length === 1 && isAssignable(ast.body[0].expression)) {\n\t return {type: AST.AssignmentExpression, left: ast.body[0].expression, right: {type: AST.NGValueParameter}, operator: '='};\n\t }\n\t}\n\t\n\tfunction isLiteral(ast) {\n\t return ast.body.length === 0 ||\n\t ast.body.length === 1 && (\n\t ast.body[0].expression.type === AST.Literal ||\n\t ast.body[0].expression.type === AST.ArrayExpression ||\n\t ast.body[0].expression.type === AST.ObjectExpression);\n\t}\n\t\n\tfunction isConstant(ast) {\n\t return ast.constant;\n\t}\n\t\n\tfunction ASTCompiler(astBuilder, $filter) {\n\t this.astBuilder = astBuilder;\n\t this.$filter = $filter;\n\t}\n\t\n\tASTCompiler.prototype = {\n\t compile: function(expression, expensiveChecks) {\n\t var self = this;\n\t var ast = this.astBuilder.ast(expression);\n\t this.state = {\n\t nextId: 0,\n\t filters: {},\n\t expensiveChecks: expensiveChecks,\n\t fn: {vars: [], body: [], own: {}},\n\t assign: {vars: [], body: [], own: {}},\n\t inputs: []\n\t };\n\t findConstantAndWatchExpressions(ast, self.$filter);\n\t var extra = '';\n\t var assignable;\n\t this.stage = 'assign';\n\t if ((assignable = assignableAST(ast))) {\n\t this.state.computing = 'assign';\n\t var result = this.nextId();\n\t this.recurse(assignable, result);\n\t this.return_(result);\n\t extra = 'fn.assign=' + this.generateFunction('assign', 's,v,l');\n\t }\n\t var toWatch = getInputs(ast.body);\n\t self.stage = 'inputs';\n\t forEach(toWatch, function(watch, key) {\n\t var fnKey = 'fn' + key;\n\t self.state[fnKey] = {vars: [], body: [], own: {}};\n\t self.state.computing = fnKey;\n\t var intoId = self.nextId();\n\t self.recurse(watch, intoId);\n\t self.return_(intoId);\n\t self.state.inputs.push(fnKey);\n\t watch.watchId = key;\n\t });\n\t this.state.computing = 'fn';\n\t this.stage = 'main';\n\t this.recurse(ast);\n\t var fnString =\n\t // The build and minification steps remove the string \"use strict\" from the code, but this is done using a regex.\n\t // This is a workaround for this until we do a better job at only removing the prefix only when we should.\n\t '\"' + this.USE + ' ' + this.STRICT + '\";\\n' +\n\t this.filterPrefix() +\n\t 'var fn=' + this.generateFunction('fn', 's,l,a,i') +\n\t extra +\n\t this.watchFns() +\n\t 'return fn;';\n\t\n\t /* jshint -W054 */\n\t var fn = (new Function('$filter',\n\t 'ensureSafeMemberName',\n\t 'ensureSafeObject',\n\t 'ensureSafeFunction',\n\t 'getStringValue',\n\t 'ensureSafeAssignContext',\n\t 'ifDefined',\n\t 'plus',\n\t 'text',\n\t fnString))(\n\t this.$filter,\n\t ensureSafeMemberName,\n\t ensureSafeObject,\n\t ensureSafeFunction,\n\t getStringValue,\n\t ensureSafeAssignContext,\n\t ifDefined,\n\t plusFn,\n\t expression);\n\t /* jshint +W054 */\n\t this.state = this.stage = undefined;\n\t fn.literal = isLiteral(ast);\n\t fn.constant = isConstant(ast);\n\t return fn;\n\t },\n\t\n\t USE: 'use',\n\t\n\t STRICT: 'strict',\n\t\n\t watchFns: function() {\n\t var result = [];\n\t var fns = this.state.inputs;\n\t var self = this;\n\t forEach(fns, function(name) {\n\t result.push('var ' + name + '=' + self.generateFunction(name, 's'));\n\t });\n\t if (fns.length) {\n\t result.push('fn.inputs=[' + fns.join(',') + '];');\n\t }\n\t return result.join('');\n\t },\n\t\n\t generateFunction: function(name, params) {\n\t return 'function(' + params + '){' +\n\t this.varsPrefix(name) +\n\t this.body(name) +\n\t '};';\n\t },\n\t\n\t filterPrefix: function() {\n\t var parts = [];\n\t var self = this;\n\t forEach(this.state.filters, function(id, filter) {\n\t parts.push(id + '=$filter(' + self.escape(filter) + ')');\n\t });\n\t if (parts.length) return 'var ' + parts.join(',') + ';';\n\t return '';\n\t },\n\t\n\t varsPrefix: function(section) {\n\t return this.state[section].vars.length ? 'var ' + this.state[section].vars.join(',') + ';' : '';\n\t },\n\t\n\t body: function(section) {\n\t return this.state[section].body.join('');\n\t },\n\t\n\t recurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) {\n\t var left, right, self = this, args, expression, computed;\n\t recursionFn = recursionFn || noop;\n\t if (!skipWatchIdCheck && isDefined(ast.watchId)) {\n\t intoId = intoId || this.nextId();\n\t this.if_('i',\n\t this.lazyAssign(intoId, this.computedMember('i', ast.watchId)),\n\t this.lazyRecurse(ast, intoId, nameId, recursionFn, create, true)\n\t );\n\t return;\n\t }\n\t switch (ast.type) {\n\t case AST.Program:\n\t forEach(ast.body, function(expression, pos) {\n\t self.recurse(expression.expression, undefined, undefined, function(expr) { right = expr; });\n\t if (pos !== ast.body.length - 1) {\n\t self.current().body.push(right, ';');\n\t } else {\n\t self.return_(right);\n\t }\n\t });\n\t break;\n\t case AST.Literal:\n\t expression = this.escape(ast.value);\n\t this.assign(intoId, expression);\n\t recursionFn(expression);\n\t break;\n\t case AST.UnaryExpression:\n\t this.recurse(ast.argument, undefined, undefined, function(expr) { right = expr; });\n\t expression = ast.operator + '(' + this.ifDefined(right, 0) + ')';\n\t this.assign(intoId, expression);\n\t recursionFn(expression);\n\t break;\n\t case AST.BinaryExpression:\n\t this.recurse(ast.left, undefined, undefined, function(expr) { left = expr; });\n\t this.recurse(ast.right, undefined, undefined, function(expr) { right = expr; });\n\t if (ast.operator === '+') {\n\t expression = this.plus(left, right);\n\t } else if (ast.operator === '-') {\n\t expression = this.ifDefined(left, 0) + ast.operator + this.ifDefined(right, 0);\n\t } else {\n\t expression = '(' + left + ')' + ast.operator + '(' + right + ')';\n\t }\n\t this.assign(intoId, expression);\n\t recursionFn(expression);\n\t break;\n\t case AST.LogicalExpression:\n\t intoId = intoId || this.nextId();\n\t self.recurse(ast.left, intoId);\n\t self.if_(ast.operator === '&&' ? intoId : self.not(intoId), self.lazyRecurse(ast.right, intoId));\n\t recursionFn(intoId);\n\t break;\n\t case AST.ConditionalExpression:\n\t intoId = intoId || this.nextId();\n\t self.recurse(ast.test, intoId);\n\t self.if_(intoId, self.lazyRecurse(ast.alternate, intoId), self.lazyRecurse(ast.consequent, intoId));\n\t recursionFn(intoId);\n\t break;\n\t case AST.Identifier:\n\t intoId = intoId || this.nextId();\n\t if (nameId) {\n\t nameId.context = self.stage === 'inputs' ? 's' : this.assign(this.nextId(), this.getHasOwnProperty('l', ast.name) + '?l:s');\n\t nameId.computed = false;\n\t nameId.name = ast.name;\n\t }\n\t ensureSafeMemberName(ast.name);\n\t self.if_(self.stage === 'inputs' || self.not(self.getHasOwnProperty('l', ast.name)),\n\t function() {\n\t self.if_(self.stage === 'inputs' || 's', function() {\n\t if (create && create !== 1) {\n\t self.if_(\n\t self.not(self.nonComputedMember('s', ast.name)),\n\t self.lazyAssign(self.nonComputedMember('s', ast.name), '{}'));\n\t }\n\t self.assign(intoId, self.nonComputedMember('s', ast.name));\n\t });\n\t }, intoId && self.lazyAssign(intoId, self.nonComputedMember('l', ast.name))\n\t );\n\t if (self.state.expensiveChecks || isPossiblyDangerousMemberName(ast.name)) {\n\t self.addEnsureSafeObject(intoId);\n\t }\n\t recursionFn(intoId);\n\t break;\n\t case AST.MemberExpression:\n\t left = nameId && (nameId.context = this.nextId()) || this.nextId();\n\t intoId = intoId || this.nextId();\n\t self.recurse(ast.object, left, undefined, function() {\n\t self.if_(self.notNull(left), function() {\n\t if (create && create !== 1) {\n\t self.addEnsureSafeAssignContext(left);\n\t }\n\t if (ast.computed) {\n\t right = self.nextId();\n\t self.recurse(ast.property, right);\n\t self.getStringValue(right);\n\t self.addEnsureSafeMemberName(right);\n\t if (create && create !== 1) {\n\t self.if_(self.not(self.computedMember(left, right)), self.lazyAssign(self.computedMember(left, right), '{}'));\n\t }\n\t expression = self.ensureSafeObject(self.computedMember(left, right));\n\t self.assign(intoId, expression);\n\t if (nameId) {\n\t nameId.computed = true;\n\t nameId.name = right;\n\t }\n\t } else {\n\t ensureSafeMemberName(ast.property.name);\n\t if (create && create !== 1) {\n\t self.if_(self.not(self.nonComputedMember(left, ast.property.name)), self.lazyAssign(self.nonComputedMember(left, ast.property.name), '{}'));\n\t }\n\t expression = self.nonComputedMember(left, ast.property.name);\n\t if (self.state.expensiveChecks || isPossiblyDangerousMemberName(ast.property.name)) {\n\t expression = self.ensureSafeObject(expression);\n\t }\n\t self.assign(intoId, expression);\n\t if (nameId) {\n\t nameId.computed = false;\n\t nameId.name = ast.property.name;\n\t }\n\t }\n\t }, function() {\n\t self.assign(intoId, 'undefined');\n\t });\n\t recursionFn(intoId);\n\t }, !!create);\n\t break;\n\t case AST.CallExpression:\n\t intoId = intoId || this.nextId();\n\t if (ast.filter) {\n\t right = self.filter(ast.callee.name);\n\t args = [];\n\t forEach(ast.arguments, function(expr) {\n\t var argument = self.nextId();\n\t self.recurse(expr, argument);\n\t args.push(argument);\n\t });\n\t expression = right + '(' + args.join(',') + ')';\n\t self.assign(intoId, expression);\n\t recursionFn(intoId);\n\t } else {\n\t right = self.nextId();\n\t left = {};\n\t args = [];\n\t self.recurse(ast.callee, right, left, function() {\n\t self.if_(self.notNull(right), function() {\n\t self.addEnsureSafeFunction(right);\n\t forEach(ast.arguments, function(expr) {\n\t self.recurse(expr, self.nextId(), undefined, function(argument) {\n\t args.push(self.ensureSafeObject(argument));\n\t });\n\t });\n\t if (left.name) {\n\t if (!self.state.expensiveChecks) {\n\t self.addEnsureSafeObject(left.context);\n\t }\n\t expression = self.member(left.context, left.name, left.computed) + '(' + args.join(',') + ')';\n\t } else {\n\t expression = right + '(' + args.join(',') + ')';\n\t }\n\t expression = self.ensureSafeObject(expression);\n\t self.assign(intoId, expression);\n\t }, function() {\n\t self.assign(intoId, 'undefined');\n\t });\n\t recursionFn(intoId);\n\t });\n\t }\n\t break;\n\t case AST.AssignmentExpression:\n\t right = this.nextId();\n\t left = {};\n\t if (!isAssignable(ast.left)) {\n\t throw $parseMinErr('lval', 'Trying to assign a value to a non l-value');\n\t }\n\t this.recurse(ast.left, undefined, left, function() {\n\t self.if_(self.notNull(left.context), function() {\n\t self.recurse(ast.right, right);\n\t self.addEnsureSafeObject(self.member(left.context, left.name, left.computed));\n\t self.addEnsureSafeAssignContext(left.context);\n\t expression = self.member(left.context, left.name, left.computed) + ast.operator + right;\n\t self.assign(intoId, expression);\n\t recursionFn(intoId || expression);\n\t });\n\t }, 1);\n\t break;\n\t case AST.ArrayExpression:\n\t args = [];\n\t forEach(ast.elements, function(expr) {\n\t self.recurse(expr, self.nextId(), undefined, function(argument) {\n\t args.push(argument);\n\t });\n\t });\n\t expression = '[' + args.join(',') + ']';\n\t this.assign(intoId, expression);\n\t recursionFn(expression);\n\t break;\n\t case AST.ObjectExpression:\n\t args = [];\n\t computed = false;\n\t forEach(ast.properties, function(property) {\n\t if (property.computed) {\n\t computed = true;\n\t }\n\t });\n\t if (computed) {\n\t intoId = intoId || this.nextId();\n\t this.assign(intoId, '{}');\n\t forEach(ast.properties, function(property) {\n\t if (property.computed) {\n\t left = self.nextId();\n\t self.recurse(property.key, left);\n\t } else {\n\t left = property.key.type === AST.Identifier ?\n\t property.key.name :\n\t ('' + property.key.value);\n\t }\n\t right = self.nextId();\n\t self.recurse(property.value, right);\n\t self.assign(self.member(intoId, left, property.computed), right);\n\t });\n\t } else {\n\t forEach(ast.properties, function(property) {\n\t self.recurse(property.value, ast.constant ? undefined : self.nextId(), undefined, function(expr) {\n\t args.push(self.escape(\n\t property.key.type === AST.Identifier ? property.key.name :\n\t ('' + property.key.value)) +\n\t ':' + expr);\n\t });\n\t });\n\t expression = '{' + args.join(',') + '}';\n\t this.assign(intoId, expression);\n\t }\n\t recursionFn(intoId || expression);\n\t break;\n\t case AST.ThisExpression:\n\t this.assign(intoId, 's');\n\t recursionFn('s');\n\t break;\n\t case AST.LocalsExpression:\n\t this.assign(intoId, 'l');\n\t recursionFn('l');\n\t break;\n\t case AST.NGValueParameter:\n\t this.assign(intoId, 'v');\n\t recursionFn('v');\n\t break;\n\t }\n\t },\n\t\n\t getHasOwnProperty: function(element, property) {\n\t var key = element + '.' + property;\n\t var own = this.current().own;\n\t if (!own.hasOwnProperty(key)) {\n\t own[key] = this.nextId(false, element + '&&(' + this.escape(property) + ' in ' + element + ')');\n\t }\n\t return own[key];\n\t },\n\t\n\t assign: function(id, value) {\n\t if (!id) return;\n\t this.current().body.push(id, '=', value, ';');\n\t return id;\n\t },\n\t\n\t filter: function(filterName) {\n\t if (!this.state.filters.hasOwnProperty(filterName)) {\n\t this.state.filters[filterName] = this.nextId(true);\n\t }\n\t return this.state.filters[filterName];\n\t },\n\t\n\t ifDefined: function(id, defaultValue) {\n\t return 'ifDefined(' + id + ',' + this.escape(defaultValue) + ')';\n\t },\n\t\n\t plus: function(left, right) {\n\t return 'plus(' + left + ',' + right + ')';\n\t },\n\t\n\t return_: function(id) {\n\t this.current().body.push('return ', id, ';');\n\t },\n\t\n\t if_: function(test, alternate, consequent) {\n\t if (test === true) {\n\t alternate();\n\t } else {\n\t var body = this.current().body;\n\t body.push('if(', test, '){');\n\t alternate();\n\t body.push('}');\n\t if (consequent) {\n\t body.push('else{');\n\t consequent();\n\t body.push('}');\n\t }\n\t }\n\t },\n\t\n\t not: function(expression) {\n\t return '!(' + expression + ')';\n\t },\n\t\n\t notNull: function(expression) {\n\t return expression + '!=null';\n\t },\n\t\n\t nonComputedMember: function(left, right) {\n\t var SAFE_IDENTIFIER = /[$_a-zA-Z][$_a-zA-Z0-9]*/;\n\t var UNSAFE_CHARACTERS = /[^$_a-zA-Z0-9]/g;\n\t if (SAFE_IDENTIFIER.test(right)) {\n\t return left + '.' + right;\n\t } else {\n\t return left + '[\"' + right.replace(UNSAFE_CHARACTERS, this.stringEscapeFn) + '\"]';\n\t }\n\t },\n\t\n\t computedMember: function(left, right) {\n\t return left + '[' + right + ']';\n\t },\n\t\n\t member: function(left, right, computed) {\n\t if (computed) return this.computedMember(left, right);\n\t return this.nonComputedMember(left, right);\n\t },\n\t\n\t addEnsureSafeObject: function(item) {\n\t this.current().body.push(this.ensureSafeObject(item), ';');\n\t },\n\t\n\t addEnsureSafeMemberName: function(item) {\n\t this.current().body.push(this.ensureSafeMemberName(item), ';');\n\t },\n\t\n\t addEnsureSafeFunction: function(item) {\n\t this.current().body.push(this.ensureSafeFunction(item), ';');\n\t },\n\t\n\t addEnsureSafeAssignContext: function(item) {\n\t this.current().body.push(this.ensureSafeAssignContext(item), ';');\n\t },\n\t\n\t ensureSafeObject: function(item) {\n\t return 'ensureSafeObject(' + item + ',text)';\n\t },\n\t\n\t ensureSafeMemberName: function(item) {\n\t return 'ensureSafeMemberName(' + item + ',text)';\n\t },\n\t\n\t ensureSafeFunction: function(item) {\n\t return 'ensureSafeFunction(' + item + ',text)';\n\t },\n\t\n\t getStringValue: function(item) {\n\t this.assign(item, 'getStringValue(' + item + ')');\n\t },\n\t\n\t ensureSafeAssignContext: function(item) {\n\t return 'ensureSafeAssignContext(' + item + ',text)';\n\t },\n\t\n\t lazyRecurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) {\n\t var self = this;\n\t return function() {\n\t self.recurse(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck);\n\t };\n\t },\n\t\n\t lazyAssign: function(id, value) {\n\t var self = this;\n\t return function() {\n\t self.assign(id, value);\n\t };\n\t },\n\t\n\t stringEscapeRegex: /[^ a-zA-Z0-9]/g,\n\t\n\t stringEscapeFn: function(c) {\n\t return '\\\\u' + ('0000' + c.charCodeAt(0).toString(16)).slice(-4);\n\t },\n\t\n\t escape: function(value) {\n\t if (isString(value)) return \"'\" + value.replace(this.stringEscapeRegex, this.stringEscapeFn) + \"'\";\n\t if (isNumber(value)) return value.toString();\n\t if (value === true) return 'true';\n\t if (value === false) return 'false';\n\t if (value === null) return 'null';\n\t if (typeof value === 'undefined') return 'undefined';\n\t\n\t throw $parseMinErr('esc', 'IMPOSSIBLE');\n\t },\n\t\n\t nextId: function(skip, init) {\n\t var id = 'v' + (this.state.nextId++);\n\t if (!skip) {\n\t this.current().vars.push(id + (init ? '=' + init : ''));\n\t }\n\t return id;\n\t },\n\t\n\t current: function() {\n\t return this.state[this.state.computing];\n\t }\n\t};\n\t\n\t\n\tfunction ASTInterpreter(astBuilder, $filter) {\n\t this.astBuilder = astBuilder;\n\t this.$filter = $filter;\n\t}\n\t\n\tASTInterpreter.prototype = {\n\t compile: function(expression, expensiveChecks) {\n\t var self = this;\n\t var ast = this.astBuilder.ast(expression);\n\t this.expression = expression;\n\t this.expensiveChecks = expensiveChecks;\n\t findConstantAndWatchExpressions(ast, self.$filter);\n\t var assignable;\n\t var assign;\n\t if ((assignable = assignableAST(ast))) {\n\t assign = this.recurse(assignable);\n\t }\n\t var toWatch = getInputs(ast.body);\n\t var inputs;\n\t if (toWatch) {\n\t inputs = [];\n\t forEach(toWatch, function(watch, key) {\n\t var input = self.recurse(watch);\n\t watch.input = input;\n\t inputs.push(input);\n\t watch.watchId = key;\n\t });\n\t }\n\t var expressions = [];\n\t forEach(ast.body, function(expression) {\n\t expressions.push(self.recurse(expression.expression));\n\t });\n\t var fn = ast.body.length === 0 ? noop :\n\t ast.body.length === 1 ? expressions[0] :\n\t function(scope, locals) {\n\t var lastValue;\n\t forEach(expressions, function(exp) {\n\t lastValue = exp(scope, locals);\n\t });\n\t return lastValue;\n\t };\n\t if (assign) {\n\t fn.assign = function(scope, value, locals) {\n\t return assign(scope, locals, value);\n\t };\n\t }\n\t if (inputs) {\n\t fn.inputs = inputs;\n\t }\n\t fn.literal = isLiteral(ast);\n\t fn.constant = isConstant(ast);\n\t return fn;\n\t },\n\t\n\t recurse: function(ast, context, create) {\n\t var left, right, self = this, args, expression;\n\t if (ast.input) {\n\t return this.inputs(ast.input, ast.watchId);\n\t }\n\t switch (ast.type) {\n\t case AST.Literal:\n\t return this.value(ast.value, context);\n\t case AST.UnaryExpression:\n\t right = this.recurse(ast.argument);\n\t return this['unary' + ast.operator](right, context);\n\t case AST.BinaryExpression:\n\t left = this.recurse(ast.left);\n\t right = this.recurse(ast.right);\n\t return this['binary' + ast.operator](left, right, context);\n\t case AST.LogicalExpression:\n\t left = this.recurse(ast.left);\n\t right = this.recurse(ast.right);\n\t return this['binary' + ast.operator](left, right, context);\n\t case AST.ConditionalExpression:\n\t return this['ternary?:'](\n\t this.recurse(ast.test),\n\t this.recurse(ast.alternate),\n\t this.recurse(ast.consequent),\n\t context\n\t );\n\t case AST.Identifier:\n\t ensureSafeMemberName(ast.name, self.expression);\n\t return self.identifier(ast.name,\n\t self.expensiveChecks || isPossiblyDangerousMemberName(ast.name),\n\t context, create, self.expression);\n\t case AST.MemberExpression:\n\t left = this.recurse(ast.object, false, !!create);\n\t if (!ast.computed) {\n\t ensureSafeMemberName(ast.property.name, self.expression);\n\t right = ast.property.name;\n\t }\n\t if (ast.computed) right = this.recurse(ast.property);\n\t return ast.computed ?\n\t this.computedMember(left, right, context, create, self.expression) :\n\t this.nonComputedMember(left, right, self.expensiveChecks, context, create, self.expression);\n\t case AST.CallExpression:\n\t args = [];\n\t forEach(ast.arguments, function(expr) {\n\t args.push(self.recurse(expr));\n\t });\n\t if (ast.filter) right = this.$filter(ast.callee.name);\n\t if (!ast.filter) right = this.recurse(ast.callee, true);\n\t return ast.filter ?\n\t function(scope, locals, assign, inputs) {\n\t var values = [];\n\t for (var i = 0; i < args.length; ++i) {\n\t values.push(args[i](scope, locals, assign, inputs));\n\t }\n\t var value = right.apply(undefined, values, inputs);\n\t return context ? {context: undefined, name: undefined, value: value} : value;\n\t } :\n\t function(scope, locals, assign, inputs) {\n\t var rhs = right(scope, locals, assign, inputs);\n\t var value;\n\t if (rhs.value != null) {\n\t ensureSafeObject(rhs.context, self.expression);\n\t ensureSafeFunction(rhs.value, self.expression);\n\t var values = [];\n\t for (var i = 0; i < args.length; ++i) {\n\t values.push(ensureSafeObject(args[i](scope, locals, assign, inputs), self.expression));\n\t }\n\t value = ensureSafeObject(rhs.value.apply(rhs.context, values), self.expression);\n\t }\n\t return context ? {value: value} : value;\n\t };\n\t case AST.AssignmentExpression:\n\t left = this.recurse(ast.left, true, 1);\n\t right = this.recurse(ast.right);\n\t return function(scope, locals, assign, inputs) {\n\t var lhs = left(scope, locals, assign, inputs);\n\t var rhs = right(scope, locals, assign, inputs);\n\t ensureSafeObject(lhs.value, self.expression);\n\t ensureSafeAssignContext(lhs.context);\n\t lhs.context[lhs.name] = rhs;\n\t return context ? {value: rhs} : rhs;\n\t };\n\t case AST.ArrayExpression:\n\t args = [];\n\t forEach(ast.elements, function(expr) {\n\t args.push(self.recurse(expr));\n\t });\n\t return function(scope, locals, assign, inputs) {\n\t var value = [];\n\t for (var i = 0; i < args.length; ++i) {\n\t value.push(args[i](scope, locals, assign, inputs));\n\t }\n\t return context ? {value: value} : value;\n\t };\n\t case AST.ObjectExpression:\n\t args = [];\n\t forEach(ast.properties, function(property) {\n\t if (property.computed) {\n\t args.push({key: self.recurse(property.key),\n\t computed: true,\n\t value: self.recurse(property.value)\n\t });\n\t } else {\n\t args.push({key: property.key.type === AST.Identifier ?\n\t property.key.name :\n\t ('' + property.key.value),\n\t computed: false,\n\t value: self.recurse(property.value)\n\t });\n\t }\n\t });\n\t return function(scope, locals, assign, inputs) {\n\t var value = {};\n\t for (var i = 0; i < args.length; ++i) {\n\t if (args[i].computed) {\n\t value[args[i].key(scope, locals, assign, inputs)] = args[i].value(scope, locals, assign, inputs);\n\t } else {\n\t value[args[i].key] = args[i].value(scope, locals, assign, inputs);\n\t }\n\t }\n\t return context ? {value: value} : value;\n\t };\n\t case AST.ThisExpression:\n\t return function(scope) {\n\t return context ? {value: scope} : scope;\n\t };\n\t case AST.LocalsExpression:\n\t return function(scope, locals) {\n\t return context ? {value: locals} : locals;\n\t };\n\t case AST.NGValueParameter:\n\t return function(scope, locals, assign) {\n\t return context ? {value: assign} : assign;\n\t };\n\t }\n\t },\n\t\n\t 'unary+': function(argument, context) {\n\t return function(scope, locals, assign, inputs) {\n\t var arg = argument(scope, locals, assign, inputs);\n\t if (isDefined(arg)) {\n\t arg = +arg;\n\t } else {\n\t arg = 0;\n\t }\n\t return context ? {value: arg} : arg;\n\t };\n\t },\n\t 'unary-': function(argument, context) {\n\t return function(scope, locals, assign, inputs) {\n\t var arg = argument(scope, locals, assign, inputs);\n\t if (isDefined(arg)) {\n\t arg = -arg;\n\t } else {\n\t arg = 0;\n\t }\n\t return context ? {value: arg} : arg;\n\t };\n\t },\n\t 'unary!': function(argument, context) {\n\t return function(scope, locals, assign, inputs) {\n\t var arg = !argument(scope, locals, assign, inputs);\n\t return context ? {value: arg} : arg;\n\t };\n\t },\n\t 'binary+': function(left, right, context) {\n\t return function(scope, locals, assign, inputs) {\n\t var lhs = left(scope, locals, assign, inputs);\n\t var rhs = right(scope, locals, assign, inputs);\n\t var arg = plusFn(lhs, rhs);\n\t return context ? {value: arg} : arg;\n\t };\n\t },\n\t 'binary-': function(left, right, context) {\n\t return function(scope, locals, assign, inputs) {\n\t var lhs = left(scope, locals, assign, inputs);\n\t var rhs = right(scope, locals, assign, inputs);\n\t var arg = (isDefined(lhs) ? lhs : 0) - (isDefined(rhs) ? rhs : 0);\n\t return context ? {value: arg} : arg;\n\t };\n\t },\n\t 'binary*': function(left, right, context) {\n\t return function(scope, locals, assign, inputs) {\n\t var arg = left(scope, locals, assign, inputs) * right(scope, locals, assign, inputs);\n\t return context ? {value: arg} : arg;\n\t };\n\t },\n\t 'binary/': function(left, right, context) {\n\t return function(scope, locals, assign, inputs) {\n\t var arg = left(scope, locals, assign, inputs) / right(scope, locals, assign, inputs);\n\t return context ? {value: arg} : arg;\n\t };\n\t },\n\t 'binary%': function(left, right, context) {\n\t return function(scope, locals, assign, inputs) {\n\t var arg = left(scope, locals, assign, inputs) % right(scope, locals, assign, inputs);\n\t return context ? {value: arg} : arg;\n\t };\n\t },\n\t 'binary===': function(left, right, context) {\n\t return function(scope, locals, assign, inputs) {\n\t var arg = left(scope, locals, assign, inputs) === right(scope, locals, assign, inputs);\n\t return context ? {value: arg} : arg;\n\t };\n\t },\n\t 'binary!==': function(left, right, context) {\n\t return function(scope, locals, assign, inputs) {\n\t var arg = left(scope, locals, assign, inputs) !== right(scope, locals, assign, inputs);\n\t return context ? {value: arg} : arg;\n\t };\n\t },\n\t 'binary==': function(left, right, context) {\n\t return function(scope, locals, assign, inputs) {\n\t var arg = left(scope, locals, assign, inputs) == right(scope, locals, assign, inputs);\n\t return context ? {value: arg} : arg;\n\t };\n\t },\n\t 'binary!=': function(left, right, context) {\n\t return function(scope, locals, assign, inputs) {\n\t var arg = left(scope, locals, assign, inputs) != right(scope, locals, assign, inputs);\n\t return context ? {value: arg} : arg;\n\t };\n\t },\n\t 'binary<': function(left, right, context) {\n\t return function(scope, locals, assign, inputs) {\n\t var arg = left(scope, locals, assign, inputs) < right(scope, locals, assign, inputs);\n\t return context ? {value: arg} : arg;\n\t };\n\t },\n\t 'binary>': function(left, right, context) {\n\t return function(scope, locals, assign, inputs) {\n\t var arg = left(scope, locals, assign, inputs) > right(scope, locals, assign, inputs);\n\t return context ? {value: arg} : arg;\n\t };\n\t },\n\t 'binary<=': function(left, right, context) {\n\t return function(scope, locals, assign, inputs) {\n\t var arg = left(scope, locals, assign, inputs) <= right(scope, locals, assign, inputs);\n\t return context ? {value: arg} : arg;\n\t };\n\t },\n\t 'binary>=': function(left, right, context) {\n\t return function(scope, locals, assign, inputs) {\n\t var arg = left(scope, locals, assign, inputs) >= right(scope, locals, assign, inputs);\n\t return context ? {value: arg} : arg;\n\t };\n\t },\n\t 'binary&&': function(left, right, context) {\n\t return function(scope, locals, assign, inputs) {\n\t var arg = left(scope, locals, assign, inputs) && right(scope, locals, assign, inputs);\n\t return context ? {value: arg} : arg;\n\t };\n\t },\n\t 'binary||': function(left, right, context) {\n\t return function(scope, locals, assign, inputs) {\n\t var arg = left(scope, locals, assign, inputs) || right(scope, locals, assign, inputs);\n\t return context ? {value: arg} : arg;\n\t };\n\t },\n\t 'ternary?:': function(test, alternate, consequent, context) {\n\t return function(scope, locals, assign, inputs) {\n\t var arg = test(scope, locals, assign, inputs) ? alternate(scope, locals, assign, inputs) : consequent(scope, locals, assign, inputs);\n\t return context ? {value: arg} : arg;\n\t };\n\t },\n\t value: function(value, context) {\n\t return function() { return context ? {context: undefined, name: undefined, value: value} : value; };\n\t },\n\t identifier: function(name, expensiveChecks, context, create, expression) {\n\t return function(scope, locals, assign, inputs) {\n\t var base = locals && (name in locals) ? locals : scope;\n\t if (create && create !== 1 && base && !(base[name])) {\n\t base[name] = {};\n\t }\n\t var value = base ? base[name] : undefined;\n\t if (expensiveChecks) {\n\t ensureSafeObject(value, expression);\n\t }\n\t if (context) {\n\t return {context: base, name: name, value: value};\n\t } else {\n\t return value;\n\t }\n\t };\n\t },\n\t computedMember: function(left, right, context, create, expression) {\n\t return function(scope, locals, assign, inputs) {\n\t var lhs = left(scope, locals, assign, inputs);\n\t var rhs;\n\t var value;\n\t if (lhs != null) {\n\t rhs = right(scope, locals, assign, inputs);\n\t rhs = getStringValue(rhs);\n\t ensureSafeMemberName(rhs, expression);\n\t if (create && create !== 1) {\n\t ensureSafeAssignContext(lhs);\n\t if (lhs && !(lhs[rhs])) {\n\t lhs[rhs] = {};\n\t }\n\t }\n\t value = lhs[rhs];\n\t ensureSafeObject(value, expression);\n\t }\n\t if (context) {\n\t return {context: lhs, name: rhs, value: value};\n\t } else {\n\t return value;\n\t }\n\t };\n\t },\n\t nonComputedMember: function(left, right, expensiveChecks, context, create, expression) {\n\t return function(scope, locals, assign, inputs) {\n\t var lhs = left(scope, locals, assign, inputs);\n\t if (create && create !== 1) {\n\t ensureSafeAssignContext(lhs);\n\t if (lhs && !(lhs[right])) {\n\t lhs[right] = {};\n\t }\n\t }\n\t var value = lhs != null ? lhs[right] : undefined;\n\t if (expensiveChecks || isPossiblyDangerousMemberName(right)) {\n\t ensureSafeObject(value, expression);\n\t }\n\t if (context) {\n\t return {context: lhs, name: right, value: value};\n\t } else {\n\t return value;\n\t }\n\t };\n\t },\n\t inputs: function(input, watchId) {\n\t return function(scope, value, locals, inputs) {\n\t if (inputs) return inputs[watchId];\n\t return input(scope, value, locals);\n\t };\n\t }\n\t};\n\t\n\t/**\n\t * @constructor\n\t */\n\tvar Parser = function(lexer, $filter, options) {\n\t this.lexer = lexer;\n\t this.$filter = $filter;\n\t this.options = options;\n\t this.ast = new AST(lexer, options);\n\t this.astCompiler = options.csp ? new ASTInterpreter(this.ast, $filter) :\n\t new ASTCompiler(this.ast, $filter);\n\t};\n\t\n\tParser.prototype = {\n\t constructor: Parser,\n\t\n\t parse: function(text) {\n\t return this.astCompiler.compile(text, this.options.expensiveChecks);\n\t }\n\t};\n\t\n\tfunction isPossiblyDangerousMemberName(name) {\n\t return name == 'constructor';\n\t}\n\t\n\tvar objectValueOf = Object.prototype.valueOf;\n\t\n\tfunction getValueOf(value) {\n\t return isFunction(value.valueOf) ? value.valueOf() : objectValueOf.call(value);\n\t}\n\t\n\t///////////////////////////////////\n\t\n\t/**\n\t * @ngdoc service\n\t * @name $parse\n\t * @kind function\n\t *\n\t * @description\n\t *\n\t * Converts Angular {@link guide/expression expression} into a function.\n\t *\n\t * ```js\n\t * var getter = $parse('user.name');\n\t * var setter = getter.assign;\n\t * var context = {user:{name:'angular'}};\n\t * var locals = {user:{name:'local'}};\n\t *\n\t * expect(getter(context)).toEqual('angular');\n\t * setter(context, 'newValue');\n\t * expect(context.user.name).toEqual('newValue');\n\t * expect(getter(context, locals)).toEqual('local');\n\t * ```\n\t *\n\t *\n\t * @param {string} expression String expression to compile.\n\t * @returns {function(context, locals)} a function which represents the compiled expression:\n\t *\n\t * * `context` – `{object}` – an object against which any expressions embedded in the strings\n\t * are evaluated against (typically a scope object).\n\t * * `locals` – `{object=}` – local variables context object, useful for overriding values in\n\t * `context`.\n\t *\n\t * The returned function also has the following properties:\n\t * * `literal` – `{boolean}` – whether the expression's top-level node is a JavaScript\n\t * literal.\n\t * * `constant` – `{boolean}` – whether the expression is made entirely of JavaScript\n\t * constant literals.\n\t * * `assign` – `{?function(context, value)}` – if the expression is assignable, this will be\n\t * set to a function to change its value on the given context.\n\t *\n\t */\n\t\n\t\n\t/**\n\t * @ngdoc provider\n\t * @name $parseProvider\n\t *\n\t * @description\n\t * `$parseProvider` can be used for configuring the default behavior of the {@link ng.$parse $parse}\n\t * service.\n\t */\n\tfunction $ParseProvider() {\n\t var cacheDefault = createMap();\n\t var cacheExpensive = createMap();\n\t var literals = {\n\t 'true': true,\n\t 'false': false,\n\t 'null': null,\n\t 'undefined': undefined\n\t };\n\t var identStart, identContinue;\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $parseProvider#addLiteral\n\t * @description\n\t *\n\t * Configure $parse service to add literal values that will be present as literal at expressions.\n\t *\n\t * @param {string} literalName Token for the literal value. The literal name value must be a valid literal name.\n\t * @param {*} literalValue Value for this literal. All literal values must be primitives or `undefined`.\n\t *\n\t **/\n\t this.addLiteral = function(literalName, literalValue) {\n\t literals[literalName] = literalValue;\n\t };\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $parseProvider#setIdentifierFns\n\t * @description\n\t *\n\t * Allows defining the set of characters that are allowed in Angular expressions. The function\n\t * `identifierStart` will get called to know if a given character is a valid character to be the\n\t * first character for an identifier. The function `identifierContinue` will get called to know if\n\t * a given character is a valid character to be a follow-up identifier character. The functions\n\t * `identifierStart` and `identifierContinue` will receive as arguments the single character to be\n\t * identifier and the character code point. These arguments will be `string` and `numeric`. Keep in\n\t * mind that the `string` parameter can be two characters long depending on the character\n\t * representation. It is expected for the function to return `true` or `false`, whether that\n\t * character is allowed or not.\n\t *\n\t * Since this function will be called extensivelly, keep the implementation of these functions fast,\n\t * as the performance of these functions have a direct impact on the expressions parsing speed.\n\t *\n\t * @param {function=} identifierStart The function that will decide whether the given character is\n\t * a valid identifier start character.\n\t * @param {function=} identifierContinue The function that will decide whether the given character is\n\t * a valid identifier continue character.\n\t */\n\t this.setIdentifierFns = function(identifierStart, identifierContinue) {\n\t identStart = identifierStart;\n\t identContinue = identifierContinue;\n\t return this;\n\t };\n\t\n\t this.$get = ['$filter', function($filter) {\n\t var noUnsafeEval = csp().noUnsafeEval;\n\t var $parseOptions = {\n\t csp: noUnsafeEval,\n\t expensiveChecks: false,\n\t literals: copy(literals),\n\t isIdentifierStart: isFunction(identStart) && identStart,\n\t isIdentifierContinue: isFunction(identContinue) && identContinue\n\t },\n\t $parseOptionsExpensive = {\n\t csp: noUnsafeEval,\n\t expensiveChecks: true,\n\t literals: copy(literals),\n\t isIdentifierStart: isFunction(identStart) && identStart,\n\t isIdentifierContinue: isFunction(identContinue) && identContinue\n\t };\n\t var runningChecksEnabled = false;\n\t\n\t $parse.$$runningExpensiveChecks = function() {\n\t return runningChecksEnabled;\n\t };\n\t\n\t return $parse;\n\t\n\t function $parse(exp, interceptorFn, expensiveChecks) {\n\t var parsedExpression, oneTime, cacheKey;\n\t\n\t expensiveChecks = expensiveChecks || runningChecksEnabled;\n\t\n\t switch (typeof exp) {\n\t case 'string':\n\t exp = exp.trim();\n\t cacheKey = exp;\n\t\n\t var cache = (expensiveChecks ? cacheExpensive : cacheDefault);\n\t parsedExpression = cache[cacheKey];\n\t\n\t if (!parsedExpression) {\n\t if (exp.charAt(0) === ':' && exp.charAt(1) === ':') {\n\t oneTime = true;\n\t exp = exp.substring(2);\n\t }\n\t var parseOptions = expensiveChecks ? $parseOptionsExpensive : $parseOptions;\n\t var lexer = new Lexer(parseOptions);\n\t var parser = new Parser(lexer, $filter, parseOptions);\n\t parsedExpression = parser.parse(exp);\n\t if (parsedExpression.constant) {\n\t parsedExpression.$$watchDelegate = constantWatchDelegate;\n\t } else if (oneTime) {\n\t parsedExpression.$$watchDelegate = parsedExpression.literal ?\n\t oneTimeLiteralWatchDelegate : oneTimeWatchDelegate;\n\t } else if (parsedExpression.inputs) {\n\t parsedExpression.$$watchDelegate = inputsWatchDelegate;\n\t }\n\t if (expensiveChecks) {\n\t parsedExpression = expensiveChecksInterceptor(parsedExpression);\n\t }\n\t cache[cacheKey] = parsedExpression;\n\t }\n\t return addInterceptor(parsedExpression, interceptorFn);\n\t\n\t case 'function':\n\t return addInterceptor(exp, interceptorFn);\n\t\n\t default:\n\t return addInterceptor(noop, interceptorFn);\n\t }\n\t }\n\t\n\t function expensiveChecksInterceptor(fn) {\n\t if (!fn) return fn;\n\t expensiveCheckFn.$$watchDelegate = fn.$$watchDelegate;\n\t expensiveCheckFn.assign = expensiveChecksInterceptor(fn.assign);\n\t expensiveCheckFn.constant = fn.constant;\n\t expensiveCheckFn.literal = fn.literal;\n\t for (var i = 0; fn.inputs && i < fn.inputs.length; ++i) {\n\t fn.inputs[i] = expensiveChecksInterceptor(fn.inputs[i]);\n\t }\n\t expensiveCheckFn.inputs = fn.inputs;\n\t\n\t return expensiveCheckFn;\n\t\n\t function expensiveCheckFn(scope, locals, assign, inputs) {\n\t var expensiveCheckOldValue = runningChecksEnabled;\n\t runningChecksEnabled = true;\n\t try {\n\t return fn(scope, locals, assign, inputs);\n\t } finally {\n\t runningChecksEnabled = expensiveCheckOldValue;\n\t }\n\t }\n\t }\n\t\n\t function expressionInputDirtyCheck(newValue, oldValueOfValue) {\n\t\n\t if (newValue == null || oldValueOfValue == null) { // null/undefined\n\t return newValue === oldValueOfValue;\n\t }\n\t\n\t if (typeof newValue === 'object') {\n\t\n\t // attempt to convert the value to a primitive type\n\t // TODO(docs): add a note to docs that by implementing valueOf even objects and arrays can\n\t // be cheaply dirty-checked\n\t newValue = getValueOf(newValue);\n\t\n\t if (typeof newValue === 'object') {\n\t // objects/arrays are not supported - deep-watching them would be too expensive\n\t return false;\n\t }\n\t\n\t // fall-through to the primitive equality check\n\t }\n\t\n\t //Primitive or NaN\n\t return newValue === oldValueOfValue || (newValue !== newValue && oldValueOfValue !== oldValueOfValue);\n\t }\n\t\n\t function inputsWatchDelegate(scope, listener, objectEquality, parsedExpression, prettyPrintExpression) {\n\t var inputExpressions = parsedExpression.inputs;\n\t var lastResult;\n\t\n\t if (inputExpressions.length === 1) {\n\t var oldInputValueOf = expressionInputDirtyCheck; // init to something unique so that equals check fails\n\t inputExpressions = inputExpressions[0];\n\t return scope.$watch(function expressionInputWatch(scope) {\n\t var newInputValue = inputExpressions(scope);\n\t if (!expressionInputDirtyCheck(newInputValue, oldInputValueOf)) {\n\t lastResult = parsedExpression(scope, undefined, undefined, [newInputValue]);\n\t oldInputValueOf = newInputValue && getValueOf(newInputValue);\n\t }\n\t return lastResult;\n\t }, listener, objectEquality, prettyPrintExpression);\n\t }\n\t\n\t var oldInputValueOfValues = [];\n\t var oldInputValues = [];\n\t for (var i = 0, ii = inputExpressions.length; i < ii; i++) {\n\t oldInputValueOfValues[i] = expressionInputDirtyCheck; // init to something unique so that equals check fails\n\t oldInputValues[i] = null;\n\t }\n\t\n\t return scope.$watch(function expressionInputsWatch(scope) {\n\t var changed = false;\n\t\n\t for (var i = 0, ii = inputExpressions.length; i < ii; i++) {\n\t var newInputValue = inputExpressions[i](scope);\n\t if (changed || (changed = !expressionInputDirtyCheck(newInputValue, oldInputValueOfValues[i]))) {\n\t oldInputValues[i] = newInputValue;\n\t oldInputValueOfValues[i] = newInputValue && getValueOf(newInputValue);\n\t }\n\t }\n\t\n\t if (changed) {\n\t lastResult = parsedExpression(scope, undefined, undefined, oldInputValues);\n\t }\n\t\n\t return lastResult;\n\t }, listener, objectEquality, prettyPrintExpression);\n\t }\n\t\n\t function oneTimeWatchDelegate(scope, listener, objectEquality, parsedExpression) {\n\t var unwatch, lastValue;\n\t return unwatch = scope.$watch(function oneTimeWatch(scope) {\n\t return parsedExpression(scope);\n\t }, function oneTimeListener(value, old, scope) {\n\t lastValue = value;\n\t if (isFunction(listener)) {\n\t listener.apply(this, arguments);\n\t }\n\t if (isDefined(value)) {\n\t scope.$$postDigest(function() {\n\t if (isDefined(lastValue)) {\n\t unwatch();\n\t }\n\t });\n\t }\n\t }, objectEquality);\n\t }\n\t\n\t function oneTimeLiteralWatchDelegate(scope, listener, objectEquality, parsedExpression) {\n\t var unwatch, lastValue;\n\t return unwatch = scope.$watch(function oneTimeWatch(scope) {\n\t return parsedExpression(scope);\n\t }, function oneTimeListener(value, old, scope) {\n\t lastValue = value;\n\t if (isFunction(listener)) {\n\t listener.call(this, value, old, scope);\n\t }\n\t if (isAllDefined(value)) {\n\t scope.$$postDigest(function() {\n\t if (isAllDefined(lastValue)) unwatch();\n\t });\n\t }\n\t }, objectEquality);\n\t\n\t function isAllDefined(value) {\n\t var allDefined = true;\n\t forEach(value, function(val) {\n\t if (!isDefined(val)) allDefined = false;\n\t });\n\t return allDefined;\n\t }\n\t }\n\t\n\t function constantWatchDelegate(scope, listener, objectEquality, parsedExpression) {\n\t var unwatch;\n\t return unwatch = scope.$watch(function constantWatch(scope) {\n\t unwatch();\n\t return parsedExpression(scope);\n\t }, listener, objectEquality);\n\t }\n\t\n\t function addInterceptor(parsedExpression, interceptorFn) {\n\t if (!interceptorFn) return parsedExpression;\n\t var watchDelegate = parsedExpression.$$watchDelegate;\n\t var useInputs = false;\n\t\n\t var regularWatch =\n\t watchDelegate !== oneTimeLiteralWatchDelegate &&\n\t watchDelegate !== oneTimeWatchDelegate;\n\t\n\t var fn = regularWatch ? function regularInterceptedExpression(scope, locals, assign, inputs) {\n\t var value = useInputs && inputs ? inputs[0] : parsedExpression(scope, locals, assign, inputs);\n\t return interceptorFn(value, scope, locals);\n\t } : function oneTimeInterceptedExpression(scope, locals, assign, inputs) {\n\t var value = parsedExpression(scope, locals, assign, inputs);\n\t var result = interceptorFn(value, scope, locals);\n\t // we only return the interceptor's result if the\n\t // initial value is defined (for bind-once)\n\t return isDefined(value) ? result : value;\n\t };\n\t\n\t // Propagate $$watchDelegates other then inputsWatchDelegate\n\t if (parsedExpression.$$watchDelegate &&\n\t parsedExpression.$$watchDelegate !== inputsWatchDelegate) {\n\t fn.$$watchDelegate = parsedExpression.$$watchDelegate;\n\t } else if (!interceptorFn.$stateful) {\n\t // If there is an interceptor, but no watchDelegate then treat the interceptor like\n\t // we treat filters - it is assumed to be a pure function unless flagged with $stateful\n\t fn.$$watchDelegate = inputsWatchDelegate;\n\t useInputs = !parsedExpression.inputs;\n\t fn.inputs = parsedExpression.inputs ? parsedExpression.inputs : [parsedExpression];\n\t }\n\t\n\t return fn;\n\t }\n\t }];\n\t}\n\t\n\t/**\n\t * @ngdoc service\n\t * @name $q\n\t * @requires $rootScope\n\t *\n\t * @description\n\t * A service that helps you run functions asynchronously, and use their return values (or exceptions)\n\t * when they are done processing.\n\t *\n\t * This is an implementation of promises/deferred objects inspired by\n\t * [Kris Kowal's Q](https://github.com/kriskowal/q).\n\t *\n\t * $q can be used in two fashions --- one which is more similar to Kris Kowal's Q or jQuery's Deferred\n\t * implementations, and the other which resembles ES6 (ES2015) promises to some degree.\n\t *\n\t * # $q constructor\n\t *\n\t * The streamlined ES6 style promise is essentially just using $q as a constructor which takes a `resolver`\n\t * function as the first argument. This is similar to the native Promise implementation from ES6,\n\t * see [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).\n\t *\n\t * While the constructor-style use is supported, not all of the supporting methods from ES6 promises are\n\t * available yet.\n\t *\n\t * It can be used like so:\n\t *\n\t * ```js\n\t * // for the purpose of this example let's assume that variables `$q` and `okToGreet`\n\t * // are available in the current lexical scope (they could have been injected or passed in).\n\t *\n\t * function asyncGreet(name) {\n\t * // perform some asynchronous operation, resolve or reject the promise when appropriate.\n\t * return $q(function(resolve, reject) {\n\t * setTimeout(function() {\n\t * if (okToGreet(name)) {\n\t * resolve('Hello, ' + name + '!');\n\t * } else {\n\t * reject('Greeting ' + name + ' is not allowed.');\n\t * }\n\t * }, 1000);\n\t * });\n\t * }\n\t *\n\t * var promise = asyncGreet('Robin Hood');\n\t * promise.then(function(greeting) {\n\t * alert('Success: ' + greeting);\n\t * }, function(reason) {\n\t * alert('Failed: ' + reason);\n\t * });\n\t * ```\n\t *\n\t * Note: progress/notify callbacks are not currently supported via the ES6-style interface.\n\t *\n\t * Note: unlike ES6 behavior, an exception thrown in the constructor function will NOT implicitly reject the promise.\n\t *\n\t * However, the more traditional CommonJS-style usage is still available, and documented below.\n\t *\n\t * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n\t * interface for interacting with an object that represents the result of an action that is\n\t * performed asynchronously, and may or may not be finished at any given point in time.\n\t *\n\t * From the perspective of dealing with error handling, deferred and promise APIs are to\n\t * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n\t *\n\t * ```js\n\t * // for the purpose of this example let's assume that variables `$q` and `okToGreet`\n\t * // are available in the current lexical scope (they could have been injected or passed in).\n\t *\n\t * function asyncGreet(name) {\n\t * var deferred = $q.defer();\n\t *\n\t * setTimeout(function() {\n\t * deferred.notify('About to greet ' + name + '.');\n\t *\n\t * if (okToGreet(name)) {\n\t * deferred.resolve('Hello, ' + name + '!');\n\t * } else {\n\t * deferred.reject('Greeting ' + name + ' is not allowed.');\n\t * }\n\t * }, 1000);\n\t *\n\t * return deferred.promise;\n\t * }\n\t *\n\t * var promise = asyncGreet('Robin Hood');\n\t * promise.then(function(greeting) {\n\t * alert('Success: ' + greeting);\n\t * }, function(reason) {\n\t * alert('Failed: ' + reason);\n\t * }, function(update) {\n\t * alert('Got notification: ' + update);\n\t * });\n\t * ```\n\t *\n\t * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n\t * comes in the way of guarantees that promise and deferred APIs make, see\n\t * https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md.\n\t *\n\t * Additionally the promise api allows for composition that is very hard to do with the\n\t * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n\t * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n\t * section on serial or parallel joining of promises.\n\t *\n\t * # The Deferred API\n\t *\n\t * A new instance of deferred is constructed by calling `$q.defer()`.\n\t *\n\t * The purpose of the deferred object is to expose the associated Promise instance as well as APIs\n\t * that can be used for signaling the successful or unsuccessful completion, as well as the status\n\t * of the task.\n\t *\n\t * **Methods**\n\t *\n\t * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n\t * constructed via `$q.reject`, the promise will be rejected instead.\n\t * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n\t * resolving it with a rejection constructed via `$q.reject`.\n\t * - `notify(value)` - provides updates on the status of the promise's execution. This may be called\n\t * multiple times before the promise is either resolved or rejected.\n\t *\n\t * **Properties**\n\t *\n\t * - promise – `{Promise}` – promise object associated with this deferred.\n\t *\n\t *\n\t * # The Promise API\n\t *\n\t * A new promise instance is created when a deferred instance is created and can be retrieved by\n\t * calling `deferred.promise`.\n\t *\n\t * The purpose of the promise object is to allow for interested parties to get access to the result\n\t * of the deferred task when it completes.\n\t *\n\t * **Methods**\n\t *\n\t * - `then(successCallback, [errorCallback], [notifyCallback])` – regardless of when the promise was or\n\t * will be resolved or rejected, `then` calls one of the success or error callbacks asynchronously\n\t * as soon as the result is available. The callbacks are called with a single argument: the result\n\t * or rejection reason. Additionally, the notify callback may be called zero or more times to\n\t * provide a progress indication, before the promise is resolved or rejected.\n\t *\n\t * This method *returns a new promise* which is resolved or rejected via the return value of the\n\t * `successCallback`, `errorCallback` (unless that value is a promise, in which case it is resolved\n\t * with the value which is resolved in that promise using\n\t * [promise chaining](http://www.html5rocks.com/en/tutorials/es6/promises/#toc-promises-queues)).\n\t * It also notifies via the return value of the `notifyCallback` method. The promise cannot be\n\t * resolved or rejected from the notifyCallback method. The errorCallback and notifyCallback\n\t * arguments are optional.\n\t *\n\t * - `catch(errorCallback)` – shorthand for `promise.then(null, errorCallback)`\n\t *\n\t * - `finally(callback, notifyCallback)` – allows you to observe either the fulfillment or rejection of a promise,\n\t * but to do so without modifying the final value. This is useful to release resources or do some\n\t * clean-up that needs to be done whether the promise was rejected or resolved. See the [full\n\t * specification](https://github.com/kriskowal/q/wiki/API-Reference#promisefinallycallback) for\n\t * more information.\n\t *\n\t * # Chaining promises\n\t *\n\t * Because calling the `then` method of a promise returns a new derived promise, it is easily\n\t * possible to create a chain of promises:\n\t *\n\t * ```js\n\t * promiseB = promiseA.then(function(result) {\n\t * return result + 1;\n\t * });\n\t *\n\t * // promiseB will be resolved immediately after promiseA is resolved and its value\n\t * // will be the result of promiseA incremented by 1\n\t * ```\n\t *\n\t * It is possible to create chains of any length and since a promise can be resolved with another\n\t * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n\t * the promises at any point in the chain. This makes it possible to implement powerful APIs like\n\t * $http's response interceptors.\n\t *\n\t *\n\t * # Differences between Kris Kowal's Q and $q\n\t *\n\t * There are two main differences:\n\t *\n\t * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n\t * mechanism in angular, which means faster propagation of resolution or rejection into your\n\t * models and avoiding unnecessary browser repaints, which would result in flickering UI.\n\t * - Q has many more features than $q, but that comes at a cost of bytes. $q is tiny, but contains\n\t * all the important functionality needed for common async tasks.\n\t *\n\t * # Testing\n\t *\n\t * ```js\n\t * it('should simulate promise', inject(function($q, $rootScope) {\n\t * var deferred = $q.defer();\n\t * var promise = deferred.promise;\n\t * var resolvedValue;\n\t *\n\t * promise.then(function(value) { resolvedValue = value; });\n\t * expect(resolvedValue).toBeUndefined();\n\t *\n\t * // Simulate resolving of promise\n\t * deferred.resolve(123);\n\t * // Note that the 'then' function does not get called synchronously.\n\t * // This is because we want the promise API to always be async, whether or not\n\t * // it got called synchronously or asynchronously.\n\t * expect(resolvedValue).toBeUndefined();\n\t *\n\t * // Propagate promise resolution to 'then' functions using $apply().\n\t * $rootScope.$apply();\n\t * expect(resolvedValue).toEqual(123);\n\t * }));\n\t * ```\n\t *\n\t * @param {function(function, function)} resolver Function which is responsible for resolving or\n\t * rejecting the newly created promise. The first parameter is a function which resolves the\n\t * promise, the second parameter is a function which rejects the promise.\n\t *\n\t * @returns {Promise} The newly created promise.\n\t */\n\tfunction $QProvider() {\n\t\n\t this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n\t return qFactory(function(callback) {\n\t $rootScope.$evalAsync(callback);\n\t }, $exceptionHandler);\n\t }];\n\t}\n\t\n\tfunction $$QProvider() {\n\t this.$get = ['$browser', '$exceptionHandler', function($browser, $exceptionHandler) {\n\t return qFactory(function(callback) {\n\t $browser.defer(callback);\n\t }, $exceptionHandler);\n\t }];\n\t}\n\t\n\t/**\n\t * Constructs a promise manager.\n\t *\n\t * @param {function(function)} nextTick Function for executing functions in the next turn.\n\t * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n\t * debugging purposes.\n\t * @returns {object} Promise manager.\n\t */\n\tfunction qFactory(nextTick, exceptionHandler) {\n\t var $qMinErr = minErr('$q', TypeError);\n\t\n\t /**\n\t * @ngdoc method\n\t * @name ng.$q#defer\n\t * @kind function\n\t *\n\t * @description\n\t * Creates a `Deferred` object which represents a task which will finish in the future.\n\t *\n\t * @returns {Deferred} Returns a new instance of deferred.\n\t */\n\t var defer = function() {\n\t var d = new Deferred();\n\t //Necessary to support unbound execution :/\n\t d.resolve = simpleBind(d, d.resolve);\n\t d.reject = simpleBind(d, d.reject);\n\t d.notify = simpleBind(d, d.notify);\n\t return d;\n\t };\n\t\n\t function Promise() {\n\t this.$$state = { status: 0 };\n\t }\n\t\n\t extend(Promise.prototype, {\n\t then: function(onFulfilled, onRejected, progressBack) {\n\t if (isUndefined(onFulfilled) && isUndefined(onRejected) && isUndefined(progressBack)) {\n\t return this;\n\t }\n\t var result = new Deferred();\n\t\n\t this.$$state.pending = this.$$state.pending || [];\n\t this.$$state.pending.push([result, onFulfilled, onRejected, progressBack]);\n\t if (this.$$state.status > 0) scheduleProcessQueue(this.$$state);\n\t\n\t return result.promise;\n\t },\n\t\n\t \"catch\": function(callback) {\n\t return this.then(null, callback);\n\t },\n\t\n\t \"finally\": function(callback, progressBack) {\n\t return this.then(function(value) {\n\t return handleCallback(value, true, callback);\n\t }, function(error) {\n\t return handleCallback(error, false, callback);\n\t }, progressBack);\n\t }\n\t });\n\t\n\t //Faster, more basic than angular.bind http://jsperf.com/angular-bind-vs-custom-vs-native\n\t function simpleBind(context, fn) {\n\t return function(value) {\n\t fn.call(context, value);\n\t };\n\t }\n\t\n\t function processQueue(state) {\n\t var fn, deferred, pending;\n\t\n\t pending = state.pending;\n\t state.processScheduled = false;\n\t state.pending = undefined;\n\t for (var i = 0, ii = pending.length; i < ii; ++i) {\n\t deferred = pending[i][0];\n\t fn = pending[i][state.status];\n\t try {\n\t if (isFunction(fn)) {\n\t deferred.resolve(fn(state.value));\n\t } else if (state.status === 1) {\n\t deferred.resolve(state.value);\n\t } else {\n\t deferred.reject(state.value);\n\t }\n\t } catch (e) {\n\t deferred.reject(e);\n\t exceptionHandler(e);\n\t }\n\t }\n\t }\n\t\n\t function scheduleProcessQueue(state) {\n\t if (state.processScheduled || !state.pending) return;\n\t state.processScheduled = true;\n\t nextTick(function() { processQueue(state); });\n\t }\n\t\n\t function Deferred() {\n\t this.promise = new Promise();\n\t }\n\t\n\t extend(Deferred.prototype, {\n\t resolve: function(val) {\n\t if (this.promise.$$state.status) return;\n\t if (val === this.promise) {\n\t this.$$reject($qMinErr(\n\t 'qcycle',\n\t \"Expected promise to be resolved with value other than itself '{0}'\",\n\t val));\n\t } else {\n\t this.$$resolve(val);\n\t }\n\t\n\t },\n\t\n\t $$resolve: function(val) {\n\t var then;\n\t var that = this;\n\t var done = false;\n\t try {\n\t if ((isObject(val) || isFunction(val))) then = val && val.then;\n\t if (isFunction(then)) {\n\t this.promise.$$state.status = -1;\n\t then.call(val, resolvePromise, rejectPromise, simpleBind(this, this.notify));\n\t } else {\n\t this.promise.$$state.value = val;\n\t this.promise.$$state.status = 1;\n\t scheduleProcessQueue(this.promise.$$state);\n\t }\n\t } catch (e) {\n\t rejectPromise(e);\n\t exceptionHandler(e);\n\t }\n\t\n\t function resolvePromise(val) {\n\t if (done) return;\n\t done = true;\n\t that.$$resolve(val);\n\t }\n\t function rejectPromise(val) {\n\t if (done) return;\n\t done = true;\n\t that.$$reject(val);\n\t }\n\t },\n\t\n\t reject: function(reason) {\n\t if (this.promise.$$state.status) return;\n\t this.$$reject(reason);\n\t },\n\t\n\t $$reject: function(reason) {\n\t this.promise.$$state.value = reason;\n\t this.promise.$$state.status = 2;\n\t scheduleProcessQueue(this.promise.$$state);\n\t },\n\t\n\t notify: function(progress) {\n\t var callbacks = this.promise.$$state.pending;\n\t\n\t if ((this.promise.$$state.status <= 0) && callbacks && callbacks.length) {\n\t nextTick(function() {\n\t var callback, result;\n\t for (var i = 0, ii = callbacks.length; i < ii; i++) {\n\t result = callbacks[i][0];\n\t callback = callbacks[i][3];\n\t try {\n\t result.notify(isFunction(callback) ? callback(progress) : progress);\n\t } catch (e) {\n\t exceptionHandler(e);\n\t }\n\t }\n\t });\n\t }\n\t }\n\t });\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $q#reject\n\t * @kind function\n\t *\n\t * @description\n\t * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n\t * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n\t * a promise chain, you don't need to worry about it.\n\t *\n\t * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n\t * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n\t * a promise error callback and you want to forward the error to the promise derived from the\n\t * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n\t * `reject`.\n\t *\n\t * ```js\n\t * promiseB = promiseA.then(function(result) {\n\t * // success: do something and resolve promiseB\n\t * // with the old or a new result\n\t * return result;\n\t * }, function(reason) {\n\t * // error: handle the error if possible and\n\t * // resolve promiseB with newPromiseOrValue,\n\t * // otherwise forward the rejection to promiseB\n\t * if (canHandle(reason)) {\n\t * // handle the error and recover\n\t * return newPromiseOrValue;\n\t * }\n\t * return $q.reject(reason);\n\t * });\n\t * ```\n\t *\n\t * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n\t * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n\t */\n\t var reject = function(reason) {\n\t var result = new Deferred();\n\t result.reject(reason);\n\t return result.promise;\n\t };\n\t\n\t var makePromise = function makePromise(value, resolved) {\n\t var result = new Deferred();\n\t if (resolved) {\n\t result.resolve(value);\n\t } else {\n\t result.reject(value);\n\t }\n\t return result.promise;\n\t };\n\t\n\t var handleCallback = function handleCallback(value, isResolved, callback) {\n\t var callbackOutput = null;\n\t try {\n\t if (isFunction(callback)) callbackOutput = callback();\n\t } catch (e) {\n\t return makePromise(e, false);\n\t }\n\t if (isPromiseLike(callbackOutput)) {\n\t return callbackOutput.then(function() {\n\t return makePromise(value, isResolved);\n\t }, function(error) {\n\t return makePromise(error, false);\n\t });\n\t } else {\n\t return makePromise(value, isResolved);\n\t }\n\t };\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $q#when\n\t * @kind function\n\t *\n\t * @description\n\t * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n\t * This is useful when you are dealing with an object that might or might not be a promise, or if\n\t * the promise comes from a source that can't be trusted.\n\t *\n\t * @param {*} value Value or a promise\n\t * @param {Function=} successCallback\n\t * @param {Function=} errorCallback\n\t * @param {Function=} progressCallback\n\t * @returns {Promise} Returns a promise of the passed value or promise\n\t */\n\t\n\t\n\t var when = function(value, callback, errback, progressBack) {\n\t var result = new Deferred();\n\t result.resolve(value);\n\t return result.promise.then(callback, errback, progressBack);\n\t };\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $q#resolve\n\t * @kind function\n\t *\n\t * @description\n\t * Alias of {@link ng.$q#when when} to maintain naming consistency with ES6.\n\t *\n\t * @param {*} value Value or a promise\n\t * @param {Function=} successCallback\n\t * @param {Function=} errorCallback\n\t * @param {Function=} progressCallback\n\t * @returns {Promise} Returns a promise of the passed value or promise\n\t */\n\t var resolve = when;\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $q#all\n\t * @kind function\n\t *\n\t * @description\n\t * Combines multiple promises into a single promise that is resolved when all of the input\n\t * promises are resolved.\n\t *\n\t * @param {Array.|Object.} promises An array or hash of promises.\n\t * @returns {Promise} Returns a single promise that will be resolved with an array/hash of values,\n\t * each value corresponding to the promise at the same index/key in the `promises` array/hash.\n\t * If any of the promises is resolved with a rejection, this resulting promise will be rejected\n\t * with the same rejection value.\n\t */\n\t\n\t function all(promises) {\n\t var deferred = new Deferred(),\n\t counter = 0,\n\t results = isArray(promises) ? [] : {};\n\t\n\t forEach(promises, function(promise, key) {\n\t counter++;\n\t when(promise).then(function(value) {\n\t if (results.hasOwnProperty(key)) return;\n\t results[key] = value;\n\t if (!(--counter)) deferred.resolve(results);\n\t }, function(reason) {\n\t if (results.hasOwnProperty(key)) return;\n\t deferred.reject(reason);\n\t });\n\t });\n\t\n\t if (counter === 0) {\n\t deferred.resolve(results);\n\t }\n\t\n\t return deferred.promise;\n\t }\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $q#race\n\t * @kind function\n\t *\n\t * @description\n\t * Returns a promise that resolves or rejects as soon as one of those promises\n\t * resolves or rejects, with the value or reason from that promise.\n\t *\n\t * @param {Array.|Object.} promises An array or hash of promises.\n\t * @returns {Promise} a promise that resolves or rejects as soon as one of the `promises`\n\t * resolves or rejects, with the value or reason from that promise.\n\t */\n\t\n\t function race(promises) {\n\t var deferred = defer();\n\t\n\t forEach(promises, function(promise) {\n\t when(promise).then(deferred.resolve, deferred.reject);\n\t });\n\t\n\t return deferred.promise;\n\t }\n\t\n\t var $Q = function Q(resolver) {\n\t if (!isFunction(resolver)) {\n\t throw $qMinErr('norslvr', \"Expected resolverFn, got '{0}'\", resolver);\n\t }\n\t\n\t var deferred = new Deferred();\n\t\n\t function resolveFn(value) {\n\t deferred.resolve(value);\n\t }\n\t\n\t function rejectFn(reason) {\n\t deferred.reject(reason);\n\t }\n\t\n\t resolver(resolveFn, rejectFn);\n\t\n\t return deferred.promise;\n\t };\n\t\n\t // Let's make the instanceof operator work for promises, so that\n\t // `new $q(fn) instanceof $q` would evaluate to true.\n\t $Q.prototype = Promise.prototype;\n\t\n\t $Q.defer = defer;\n\t $Q.reject = reject;\n\t $Q.when = when;\n\t $Q.resolve = resolve;\n\t $Q.all = all;\n\t $Q.race = race;\n\t\n\t return $Q;\n\t}\n\t\n\tfunction $$RAFProvider() { //rAF\n\t this.$get = ['$window', '$timeout', function($window, $timeout) {\n\t var requestAnimationFrame = $window.requestAnimationFrame ||\n\t $window.webkitRequestAnimationFrame;\n\t\n\t var cancelAnimationFrame = $window.cancelAnimationFrame ||\n\t $window.webkitCancelAnimationFrame ||\n\t $window.webkitCancelRequestAnimationFrame;\n\t\n\t var rafSupported = !!requestAnimationFrame;\n\t var raf = rafSupported\n\t ? function(fn) {\n\t var id = requestAnimationFrame(fn);\n\t return function() {\n\t cancelAnimationFrame(id);\n\t };\n\t }\n\t : function(fn) {\n\t var timer = $timeout(fn, 16.66, false); // 1000 / 60 = 16.666\n\t return function() {\n\t $timeout.cancel(timer);\n\t };\n\t };\n\t\n\t raf.supported = rafSupported;\n\t\n\t return raf;\n\t }];\n\t}\n\t\n\t/**\n\t * DESIGN NOTES\n\t *\n\t * The design decisions behind the scope are heavily favored for speed and memory consumption.\n\t *\n\t * The typical use of scope is to watch the expressions, which most of the time return the same\n\t * value as last time so we optimize the operation.\n\t *\n\t * Closures construction is expensive in terms of speed as well as memory:\n\t * - No closures, instead use prototypical inheritance for API\n\t * - Internal state needs to be stored on scope directly, which means that private state is\n\t * exposed as $$____ properties\n\t *\n\t * Loop operations are optimized by using while(count--) { ... }\n\t * - This means that in order to keep the same order of execution as addition we have to add\n\t * items to the array at the beginning (unshift) instead of at the end (push)\n\t *\n\t * Child scopes are created and removed often\n\t * - Using an array would be slow since inserts in the middle are expensive; so we use linked lists\n\t *\n\t * There are fewer watches than observers. This is why you don't want the observer to be implemented\n\t * in the same way as watch. Watch requires return of the initialization function which is expensive\n\t * to construct.\n\t */\n\t\n\t\n\t/**\n\t * @ngdoc provider\n\t * @name $rootScopeProvider\n\t * @description\n\t *\n\t * Provider for the $rootScope service.\n\t */\n\t\n\t/**\n\t * @ngdoc method\n\t * @name $rootScopeProvider#digestTtl\n\t * @description\n\t *\n\t * Sets the number of `$digest` iterations the scope should attempt to execute before giving up and\n\t * assuming that the model is unstable.\n\t *\n\t * The current default is 10 iterations.\n\t *\n\t * In complex applications it's possible that the dependencies between `$watch`s will result in\n\t * several digest iterations. However if an application needs more than the default 10 digest\n\t * iterations for its model to stabilize then you should investigate what is causing the model to\n\t * continuously change during the digest.\n\t *\n\t * Increasing the TTL could have performance implications, so you should not change it without\n\t * proper justification.\n\t *\n\t * @param {number} limit The number of digest iterations.\n\t */\n\t\n\t\n\t/**\n\t * @ngdoc service\n\t * @name $rootScope\n\t * @description\n\t *\n\t * Every application has a single root {@link ng.$rootScope.Scope scope}.\n\t * All other scopes are descendant scopes of the root scope. Scopes provide separation\n\t * between the model and the view, via a mechanism for watching the model for changes.\n\t * They also provide event emission/broadcast and subscription facility. See the\n\t * {@link guide/scope developer guide on scopes}.\n\t */\n\tfunction $RootScopeProvider() {\n\t var TTL = 10;\n\t var $rootScopeMinErr = minErr('$rootScope');\n\t var lastDirtyWatch = null;\n\t var applyAsyncId = null;\n\t\n\t this.digestTtl = function(value) {\n\t if (arguments.length) {\n\t TTL = value;\n\t }\n\t return TTL;\n\t };\n\t\n\t function createChildScopeClass(parent) {\n\t function ChildScope() {\n\t this.$$watchers = this.$$nextSibling =\n\t this.$$childHead = this.$$childTail = null;\n\t this.$$listeners = {};\n\t this.$$listenerCount = {};\n\t this.$$watchersCount = 0;\n\t this.$id = nextUid();\n\t this.$$ChildScope = null;\n\t }\n\t ChildScope.prototype = parent;\n\t return ChildScope;\n\t }\n\t\n\t this.$get = ['$exceptionHandler', '$parse', '$browser',\n\t function($exceptionHandler, $parse, $browser) {\n\t\n\t function destroyChildScope($event) {\n\t $event.currentScope.$$destroyed = true;\n\t }\n\t\n\t function cleanUpScope($scope) {\n\t\n\t if (msie === 9) {\n\t // There is a memory leak in IE9 if all child scopes are not disconnected\n\t // completely when a scope is destroyed. So this code will recurse up through\n\t // all this scopes children\n\t //\n\t // See issue https://github.com/angular/angular.js/issues/10706\n\t $scope.$$childHead && cleanUpScope($scope.$$childHead);\n\t $scope.$$nextSibling && cleanUpScope($scope.$$nextSibling);\n\t }\n\t\n\t // The code below works around IE9 and V8's memory leaks\n\t //\n\t // See:\n\t // - https://code.google.com/p/v8/issues/detail?id=2073#c26\n\t // - https://github.com/angular/angular.js/issues/6794#issuecomment-38648909\n\t // - https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n\t\n\t $scope.$parent = $scope.$$nextSibling = $scope.$$prevSibling = $scope.$$childHead =\n\t $scope.$$childTail = $scope.$root = $scope.$$watchers = null;\n\t }\n\t\n\t /**\n\t * @ngdoc type\n\t * @name $rootScope.Scope\n\t *\n\t * @description\n\t * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n\t * {@link auto.$injector $injector}. Child scopes are created using the\n\t * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n\t * compiled HTML template is executed.) See also the {@link guide/scope Scopes guide} for\n\t * an in-depth introduction and usage examples.\n\t *\n\t *\n\t * # Inheritance\n\t * A scope can inherit from a parent scope, as in this example:\n\t * ```js\n\t var parent = $rootScope;\n\t var child = parent.$new();\n\t\n\t parent.salutation = \"Hello\";\n\t expect(child.salutation).toEqual('Hello');\n\t\n\t child.salutation = \"Welcome\";\n\t expect(child.salutation).toEqual('Welcome');\n\t expect(parent.salutation).toEqual('Hello');\n\t * ```\n\t *\n\t * When interacting with `Scope` in tests, additional helper methods are available on the\n\t * instances of `Scope` type. See {@link ngMock.$rootScope.Scope ngMock Scope} for additional\n\t * details.\n\t *\n\t *\n\t * @param {Object.=} providers Map of service factory which need to be\n\t * provided for the current scope. Defaults to {@link ng}.\n\t * @param {Object.=} instanceCache Provides pre-instantiated services which should\n\t * append/override services provided by `providers`. This is handy\n\t * when unit-testing and having the need to override a default\n\t * service.\n\t * @returns {Object} Newly created scope.\n\t *\n\t */\n\t function Scope() {\n\t this.$id = nextUid();\n\t this.$$phase = this.$parent = this.$$watchers =\n\t this.$$nextSibling = this.$$prevSibling =\n\t this.$$childHead = this.$$childTail = null;\n\t this.$root = this;\n\t this.$$destroyed = false;\n\t this.$$listeners = {};\n\t this.$$listenerCount = {};\n\t this.$$watchersCount = 0;\n\t this.$$isolateBindings = null;\n\t }\n\t\n\t /**\n\t * @ngdoc property\n\t * @name $rootScope.Scope#$id\n\t *\n\t * @description\n\t * Unique scope ID (monotonically increasing) useful for debugging.\n\t */\n\t\n\t /**\n\t * @ngdoc property\n\t * @name $rootScope.Scope#$parent\n\t *\n\t * @description\n\t * Reference to the parent scope.\n\t */\n\t\n\t /**\n\t * @ngdoc property\n\t * @name $rootScope.Scope#$root\n\t *\n\t * @description\n\t * Reference to the root scope.\n\t */\n\t\n\t Scope.prototype = {\n\t constructor: Scope,\n\t /**\n\t * @ngdoc method\n\t * @name $rootScope.Scope#$new\n\t * @kind function\n\t *\n\t * @description\n\t * Creates a new child {@link ng.$rootScope.Scope scope}.\n\t *\n\t * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} event.\n\t * The scope can be removed from the scope hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n\t *\n\t * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is\n\t * desired for the scope and its child scopes to be permanently detached from the parent and\n\t * thus stop participating in model change detection and listener notification by invoking.\n\t *\n\t * @param {boolean} isolate If true, then the scope does not prototypically inherit from the\n\t * parent scope. The scope is isolated, as it can not see parent scope properties.\n\t * When creating widgets, it is useful for the widget to not accidentally read parent\n\t * state.\n\t *\n\t * @param {Scope} [parent=this] The {@link ng.$rootScope.Scope `Scope`} that will be the `$parent`\n\t * of the newly created scope. Defaults to `this` scope if not provided.\n\t * This is used when creating a transclude scope to correctly place it\n\t * in the scope hierarchy while maintaining the correct prototypical\n\t * inheritance.\n\t *\n\t * @returns {Object} The newly created child scope.\n\t *\n\t */\n\t $new: function(isolate, parent) {\n\t var child;\n\t\n\t parent = parent || this;\n\t\n\t if (isolate) {\n\t child = new Scope();\n\t child.$root = this.$root;\n\t } else {\n\t // Only create a child scope class if somebody asks for one,\n\t // but cache it to allow the VM to optimize lookups.\n\t if (!this.$$ChildScope) {\n\t this.$$ChildScope = createChildScopeClass(this);\n\t }\n\t child = new this.$$ChildScope();\n\t }\n\t child.$parent = parent;\n\t child.$$prevSibling = parent.$$childTail;\n\t if (parent.$$childHead) {\n\t parent.$$childTail.$$nextSibling = child;\n\t parent.$$childTail = child;\n\t } else {\n\t parent.$$childHead = parent.$$childTail = child;\n\t }\n\t\n\t // When the new scope is not isolated or we inherit from `this`, and\n\t // the parent scope is destroyed, the property `$$destroyed` is inherited\n\t // prototypically. In all other cases, this property needs to be set\n\t // when the parent scope is destroyed.\n\t // The listener needs to be added after the parent is set\n\t if (isolate || parent != this) child.$on('$destroy', destroyChildScope);\n\t\n\t return child;\n\t },\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $rootScope.Scope#$watch\n\t * @kind function\n\t *\n\t * @description\n\t * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n\t *\n\t * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest\n\t * $digest()} and should return the value that will be watched. (`watchExpression` should not change\n\t * its value when executed multiple times with the same input because it may be executed multiple\n\t * times by {@link ng.$rootScope.Scope#$digest $digest()}. That is, `watchExpression` should be\n\t * [idempotent](http://en.wikipedia.org/wiki/Idempotence).\n\t * - The `listener` is called only when the value from the current `watchExpression` and the\n\t * previous call to `watchExpression` are not equal (with the exception of the initial run,\n\t * see below). Inequality is determined according to reference inequality,\n\t * [strict comparison](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators)\n\t * via the `!==` Javascript operator, unless `objectEquality == true`\n\t * (see next point)\n\t * - When `objectEquality == true`, inequality of the `watchExpression` is determined\n\t * according to the {@link angular.equals} function. To save the value of the object for\n\t * later comparison, the {@link angular.copy} function is used. This therefore means that\n\t * watching complex objects will have adverse memory and performance implications.\n\t * - The watch `listener` may change the model, which may trigger other `listener`s to fire.\n\t * This is achieved by rerunning the watchers until no changes are detected. The rerun\n\t * iteration limit is 10 to prevent an infinite loop deadlock.\n\t *\n\t *\n\t * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n\t * you can register a `watchExpression` function with no `listener`. (Be prepared for\n\t * multiple calls to your `watchExpression` because it will execute multiple times in a\n\t * single {@link ng.$rootScope.Scope#$digest $digest} cycle if a change is detected.)\n\t *\n\t * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n\t * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n\t * watcher. In rare cases, this is undesirable because the listener is called when the result\n\t * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n\t * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n\t * listener was called due to initialization.\n\t *\n\t *\n\t *\n\t * # Example\n\t * ```js\n\t // let's assume that scope was dependency injected as the $rootScope\n\t var scope = $rootScope;\n\t scope.name = 'misko';\n\t scope.counter = 0;\n\t\n\t expect(scope.counter).toEqual(0);\n\t scope.$watch('name', function(newValue, oldValue) {\n\t scope.counter = scope.counter + 1;\n\t });\n\t expect(scope.counter).toEqual(0);\n\t\n\t scope.$digest();\n\t // the listener is always called during the first $digest loop after it was registered\n\t expect(scope.counter).toEqual(1);\n\t\n\t scope.$digest();\n\t // but now it will not be called unless the value changes\n\t expect(scope.counter).toEqual(1);\n\t\n\t scope.name = 'adam';\n\t scope.$digest();\n\t expect(scope.counter).toEqual(2);\n\t\n\t\n\t\n\t // Using a function as a watchExpression\n\t var food;\n\t scope.foodCounter = 0;\n\t expect(scope.foodCounter).toEqual(0);\n\t scope.$watch(\n\t // This function returns the value being watched. It is called for each turn of the $digest loop\n\t function() { return food; },\n\t // This is the change listener, called when the value returned from the above function changes\n\t function(newValue, oldValue) {\n\t if ( newValue !== oldValue ) {\n\t // Only increment the counter if the value changed\n\t scope.foodCounter = scope.foodCounter + 1;\n\t }\n\t }\n\t );\n\t // No digest has been run so the counter will be zero\n\t expect(scope.foodCounter).toEqual(0);\n\t\n\t // Run the digest but since food has not changed count will still be zero\n\t scope.$digest();\n\t expect(scope.foodCounter).toEqual(0);\n\t\n\t // Update food and run digest. Now the counter will increment\n\t food = 'cheeseburger';\n\t scope.$digest();\n\t expect(scope.foodCounter).toEqual(1);\n\t\n\t * ```\n\t *\n\t *\n\t *\n\t * @param {(function()|string)} watchExpression Expression that is evaluated on each\n\t * {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers\n\t * a call to the `listener`.\n\t *\n\t * - `string`: Evaluated as {@link guide/expression expression}\n\t * - `function(scope)`: called with current `scope` as a parameter.\n\t * @param {function(newVal, oldVal, scope)} listener Callback called whenever the value\n\t * of `watchExpression` changes.\n\t *\n\t * - `newVal` contains the current value of the `watchExpression`\n\t * - `oldVal` contains the previous value of the `watchExpression`\n\t * - `scope` refers to the current scope\n\t * @param {boolean=} [objectEquality=false] Compare for object equality using {@link angular.equals} instead of\n\t * comparing for reference equality.\n\t * @returns {function()} Returns a deregistration function for this listener.\n\t */\n\t $watch: function(watchExp, listener, objectEquality, prettyPrintExpression) {\n\t var get = $parse(watchExp);\n\t\n\t if (get.$$watchDelegate) {\n\t return get.$$watchDelegate(this, listener, objectEquality, get, watchExp);\n\t }\n\t var scope = this,\n\t array = scope.$$watchers,\n\t watcher = {\n\t fn: listener,\n\t last: initWatchVal,\n\t get: get,\n\t exp: prettyPrintExpression || watchExp,\n\t eq: !!objectEquality\n\t };\n\t\n\t lastDirtyWatch = null;\n\t\n\t if (!isFunction(listener)) {\n\t watcher.fn = noop;\n\t }\n\t\n\t if (!array) {\n\t array = scope.$$watchers = [];\n\t }\n\t // we use unshift since we use a while loop in $digest for speed.\n\t // the while loop reads in reverse order.\n\t array.unshift(watcher);\n\t incrementWatchersCount(this, 1);\n\t\n\t return function deregisterWatch() {\n\t if (arrayRemove(array, watcher) >= 0) {\n\t incrementWatchersCount(scope, -1);\n\t }\n\t lastDirtyWatch = null;\n\t };\n\t },\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $rootScope.Scope#$watchGroup\n\t * @kind function\n\t *\n\t * @description\n\t * A variant of {@link ng.$rootScope.Scope#$watch $watch()} where it watches an array of `watchExpressions`.\n\t * If any one expression in the collection changes the `listener` is executed.\n\t *\n\t * - The items in the `watchExpressions` array are observed via standard $watch operation and are examined on every\n\t * call to $digest() to see if any items changes.\n\t * - The `listener` is called whenever any expression in the `watchExpressions` array changes.\n\t *\n\t * @param {Array.} watchExpressions Array of expressions that will be individually\n\t * watched using {@link ng.$rootScope.Scope#$watch $watch()}\n\t *\n\t * @param {function(newValues, oldValues, scope)} listener Callback called whenever the return value of any\n\t * expression in `watchExpressions` changes\n\t * The `newValues` array contains the current values of the `watchExpressions`, with the indexes matching\n\t * those of `watchExpression`\n\t * and the `oldValues` array contains the previous values of the `watchExpressions`, with the indexes matching\n\t * those of `watchExpression`\n\t * The `scope` refers to the current scope.\n\t * @returns {function()} Returns a de-registration function for all listeners.\n\t */\n\t $watchGroup: function(watchExpressions, listener) {\n\t var oldValues = new Array(watchExpressions.length);\n\t var newValues = new Array(watchExpressions.length);\n\t var deregisterFns = [];\n\t var self = this;\n\t var changeReactionScheduled = false;\n\t var firstRun = true;\n\t\n\t if (!watchExpressions.length) {\n\t // No expressions means we call the listener ASAP\n\t var shouldCall = true;\n\t self.$evalAsync(function() {\n\t if (shouldCall) listener(newValues, newValues, self);\n\t });\n\t return function deregisterWatchGroup() {\n\t shouldCall = false;\n\t };\n\t }\n\t\n\t if (watchExpressions.length === 1) {\n\t // Special case size of one\n\t return this.$watch(watchExpressions[0], function watchGroupAction(value, oldValue, scope) {\n\t newValues[0] = value;\n\t oldValues[0] = oldValue;\n\t listener(newValues, (value === oldValue) ? newValues : oldValues, scope);\n\t });\n\t }\n\t\n\t forEach(watchExpressions, function(expr, i) {\n\t var unwatchFn = self.$watch(expr, function watchGroupSubAction(value, oldValue) {\n\t newValues[i] = value;\n\t oldValues[i] = oldValue;\n\t if (!changeReactionScheduled) {\n\t changeReactionScheduled = true;\n\t self.$evalAsync(watchGroupAction);\n\t }\n\t });\n\t deregisterFns.push(unwatchFn);\n\t });\n\t\n\t function watchGroupAction() {\n\t changeReactionScheduled = false;\n\t\n\t if (firstRun) {\n\t firstRun = false;\n\t listener(newValues, newValues, self);\n\t } else {\n\t listener(newValues, oldValues, self);\n\t }\n\t }\n\t\n\t return function deregisterWatchGroup() {\n\t while (deregisterFns.length) {\n\t deregisterFns.shift()();\n\t }\n\t };\n\t },\n\t\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $rootScope.Scope#$watchCollection\n\t * @kind function\n\t *\n\t * @description\n\t * Shallow watches the properties of an object and fires whenever any of the properties change\n\t * (for arrays, this implies watching the array items; for object maps, this implies watching\n\t * the properties). If a change is detected, the `listener` callback is fired.\n\t *\n\t * - The `obj` collection is observed via standard $watch operation and is examined on every\n\t * call to $digest() to see if any items have been added, removed, or moved.\n\t * - The `listener` is called whenever anything within the `obj` has changed. Examples include\n\t * adding, removing, and moving items belonging to an object or array.\n\t *\n\t *\n\t * # Example\n\t * ```js\n\t $scope.names = ['igor', 'matias', 'misko', 'james'];\n\t $scope.dataCount = 4;\n\t\n\t $scope.$watchCollection('names', function(newNames, oldNames) {\n\t $scope.dataCount = newNames.length;\n\t });\n\t\n\t expect($scope.dataCount).toEqual(4);\n\t $scope.$digest();\n\t\n\t //still at 4 ... no changes\n\t expect($scope.dataCount).toEqual(4);\n\t\n\t $scope.names.pop();\n\t $scope.$digest();\n\t\n\t //now there's been a change\n\t expect($scope.dataCount).toEqual(3);\n\t * ```\n\t *\n\t *\n\t * @param {string|function(scope)} obj Evaluated as {@link guide/expression expression}. The\n\t * expression value should evaluate to an object or an array which is observed on each\n\t * {@link ng.$rootScope.Scope#$digest $digest} cycle. Any shallow change within the\n\t * collection will trigger a call to the `listener`.\n\t *\n\t * @param {function(newCollection, oldCollection, scope)} listener a callback function called\n\t * when a change is detected.\n\t * - The `newCollection` object is the newly modified data obtained from the `obj` expression\n\t * - The `oldCollection` object is a copy of the former collection data.\n\t * Due to performance considerations, the`oldCollection` value is computed only if the\n\t * `listener` function declares two or more arguments.\n\t * - The `scope` argument refers to the current scope.\n\t *\n\t * @returns {function()} Returns a de-registration function for this listener. When the\n\t * de-registration function is executed, the internal watch operation is terminated.\n\t */\n\t $watchCollection: function(obj, listener) {\n\t $watchCollectionInterceptor.$stateful = true;\n\t\n\t var self = this;\n\t // the current value, updated on each dirty-check run\n\t var newValue;\n\t // a shallow copy of the newValue from the last dirty-check run,\n\t // updated to match newValue during dirty-check run\n\t var oldValue;\n\t // a shallow copy of the newValue from when the last change happened\n\t var veryOldValue;\n\t // only track veryOldValue if the listener is asking for it\n\t var trackVeryOldValue = (listener.length > 1);\n\t var changeDetected = 0;\n\t var changeDetector = $parse(obj, $watchCollectionInterceptor);\n\t var internalArray = [];\n\t var internalObject = {};\n\t var initRun = true;\n\t var oldLength = 0;\n\t\n\t function $watchCollectionInterceptor(_value) {\n\t newValue = _value;\n\t var newLength, key, bothNaN, newItem, oldItem;\n\t\n\t // If the new value is undefined, then return undefined as the watch may be a one-time watch\n\t if (isUndefined(newValue)) return;\n\t\n\t if (!isObject(newValue)) { // if primitive\n\t if (oldValue !== newValue) {\n\t oldValue = newValue;\n\t changeDetected++;\n\t }\n\t } else if (isArrayLike(newValue)) {\n\t if (oldValue !== internalArray) {\n\t // we are transitioning from something which was not an array into array.\n\t oldValue = internalArray;\n\t oldLength = oldValue.length = 0;\n\t changeDetected++;\n\t }\n\t\n\t newLength = newValue.length;\n\t\n\t if (oldLength !== newLength) {\n\t // if lengths do not match we need to trigger change notification\n\t changeDetected++;\n\t oldValue.length = oldLength = newLength;\n\t }\n\t // copy the items to oldValue and look for changes.\n\t for (var i = 0; i < newLength; i++) {\n\t oldItem = oldValue[i];\n\t newItem = newValue[i];\n\t\n\t bothNaN = (oldItem !== oldItem) && (newItem !== newItem);\n\t if (!bothNaN && (oldItem !== newItem)) {\n\t changeDetected++;\n\t oldValue[i] = newItem;\n\t }\n\t }\n\t } else {\n\t if (oldValue !== internalObject) {\n\t // we are transitioning from something which was not an object into object.\n\t oldValue = internalObject = {};\n\t oldLength = 0;\n\t changeDetected++;\n\t }\n\t // copy the items to oldValue and look for changes.\n\t newLength = 0;\n\t for (key in newValue) {\n\t if (hasOwnProperty.call(newValue, key)) {\n\t newLength++;\n\t newItem = newValue[key];\n\t oldItem = oldValue[key];\n\t\n\t if (key in oldValue) {\n\t bothNaN = (oldItem !== oldItem) && (newItem !== newItem);\n\t if (!bothNaN && (oldItem !== newItem)) {\n\t changeDetected++;\n\t oldValue[key] = newItem;\n\t }\n\t } else {\n\t oldLength++;\n\t oldValue[key] = newItem;\n\t changeDetected++;\n\t }\n\t }\n\t }\n\t if (oldLength > newLength) {\n\t // we used to have more keys, need to find them and destroy them.\n\t changeDetected++;\n\t for (key in oldValue) {\n\t if (!hasOwnProperty.call(newValue, key)) {\n\t oldLength--;\n\t delete oldValue[key];\n\t }\n\t }\n\t }\n\t }\n\t return changeDetected;\n\t }\n\t\n\t function $watchCollectionAction() {\n\t if (initRun) {\n\t initRun = false;\n\t listener(newValue, newValue, self);\n\t } else {\n\t listener(newValue, veryOldValue, self);\n\t }\n\t\n\t // make a copy for the next time a collection is changed\n\t if (trackVeryOldValue) {\n\t if (!isObject(newValue)) {\n\t //primitive\n\t veryOldValue = newValue;\n\t } else if (isArrayLike(newValue)) {\n\t veryOldValue = new Array(newValue.length);\n\t for (var i = 0; i < newValue.length; i++) {\n\t veryOldValue[i] = newValue[i];\n\t }\n\t } else { // if object\n\t veryOldValue = {};\n\t for (var key in newValue) {\n\t if (hasOwnProperty.call(newValue, key)) {\n\t veryOldValue[key] = newValue[key];\n\t }\n\t }\n\t }\n\t }\n\t }\n\t\n\t return this.$watch(changeDetector, $watchCollectionAction);\n\t },\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $rootScope.Scope#$digest\n\t * @kind function\n\t *\n\t * @description\n\t * Processes all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and\n\t * its children. Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change\n\t * the model, the `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers}\n\t * until no more listeners are firing. This means that it is possible to get into an infinite\n\t * loop. This function will throw `'Maximum iteration limit exceeded.'` if the number of\n\t * iterations exceeds 10.\n\t *\n\t * Usually, you don't call `$digest()` directly in\n\t * {@link ng.directive:ngController controllers} or in\n\t * {@link ng.$compileProvider#directive directives}.\n\t * Instead, you should call {@link ng.$rootScope.Scope#$apply $apply()} (typically from within\n\t * a {@link ng.$compileProvider#directive directive}), which will force a `$digest()`.\n\t *\n\t * If you want to be notified whenever `$digest()` is called,\n\t * you can register a `watchExpression` function with\n\t * {@link ng.$rootScope.Scope#$watch $watch()} with no `listener`.\n\t *\n\t * In unit tests, you may need to call `$digest()` to simulate the scope life cycle.\n\t *\n\t * # Example\n\t * ```js\n\t var scope = ...;\n\t scope.name = 'misko';\n\t scope.counter = 0;\n\t\n\t expect(scope.counter).toEqual(0);\n\t scope.$watch('name', function(newValue, oldValue) {\n\t scope.counter = scope.counter + 1;\n\t });\n\t expect(scope.counter).toEqual(0);\n\t\n\t scope.$digest();\n\t // the listener is always called during the first $digest loop after it was registered\n\t expect(scope.counter).toEqual(1);\n\t\n\t scope.$digest();\n\t // but now it will not be called unless the value changes\n\t expect(scope.counter).toEqual(1);\n\t\n\t scope.name = 'adam';\n\t scope.$digest();\n\t expect(scope.counter).toEqual(2);\n\t * ```\n\t *\n\t */\n\t $digest: function() {\n\t var watch, value, last, fn, get,\n\t watchers,\n\t length,\n\t dirty, ttl = TTL,\n\t next, current, target = this,\n\t watchLog = [],\n\t logIdx, asyncTask;\n\t\n\t beginPhase('$digest');\n\t // Check for changes to browser url that happened in sync before the call to $digest\n\t $browser.$$checkUrlChange();\n\t\n\t if (this === $rootScope && applyAsyncId !== null) {\n\t // If this is the root scope, and $applyAsync has scheduled a deferred $apply(), then\n\t // cancel the scheduled $apply and flush the queue of expressions to be evaluated.\n\t $browser.defer.cancel(applyAsyncId);\n\t flushApplyAsync();\n\t }\n\t\n\t lastDirtyWatch = null;\n\t\n\t do { // \"while dirty\" loop\n\t dirty = false;\n\t current = target;\n\t\n\t // It's safe for asyncQueuePosition to be a local variable here because this loop can't\n\t // be reentered recursively. Calling $digest from a function passed to $applyAsync would\n\t // lead to a '$digest already in progress' error.\n\t for (var asyncQueuePosition = 0; asyncQueuePosition < asyncQueue.length; asyncQueuePosition++) {\n\t try {\n\t asyncTask = asyncQueue[asyncQueuePosition];\n\t asyncTask.scope.$eval(asyncTask.expression, asyncTask.locals);\n\t } catch (e) {\n\t $exceptionHandler(e);\n\t }\n\t lastDirtyWatch = null;\n\t }\n\t asyncQueue.length = 0;\n\t\n\t traverseScopesLoop:\n\t do { // \"traverse the scopes\" loop\n\t if ((watchers = current.$$watchers)) {\n\t // process our watches\n\t length = watchers.length;\n\t while (length--) {\n\t try {\n\t watch = watchers[length];\n\t // Most common watches are on primitives, in which case we can short\n\t // circuit it with === operator, only when === fails do we use .equals\n\t if (watch) {\n\t get = watch.get;\n\t if ((value = get(current)) !== (last = watch.last) &&\n\t !(watch.eq\n\t ? equals(value, last)\n\t : (typeof value === 'number' && typeof last === 'number'\n\t && isNaN(value) && isNaN(last)))) {\n\t dirty = true;\n\t lastDirtyWatch = watch;\n\t watch.last = watch.eq ? copy(value, null) : value;\n\t fn = watch.fn;\n\t fn(value, ((last === initWatchVal) ? value : last), current);\n\t if (ttl < 5) {\n\t logIdx = 4 - ttl;\n\t if (!watchLog[logIdx]) watchLog[logIdx] = [];\n\t watchLog[logIdx].push({\n\t msg: isFunction(watch.exp) ? 'fn: ' + (watch.exp.name || watch.exp.toString()) : watch.exp,\n\t newVal: value,\n\t oldVal: last\n\t });\n\t }\n\t } else if (watch === lastDirtyWatch) {\n\t // If the most recently dirty watcher is now clean, short circuit since the remaining watchers\n\t // have already been tested.\n\t dirty = false;\n\t break traverseScopesLoop;\n\t }\n\t }\n\t } catch (e) {\n\t $exceptionHandler(e);\n\t }\n\t }\n\t }\n\t\n\t // Insanity Warning: scope depth-first traversal\n\t // yes, this code is a bit crazy, but it works and we have tests to prove it!\n\t // this piece should be kept in sync with the traversal in $broadcast\n\t if (!(next = ((current.$$watchersCount && current.$$childHead) ||\n\t (current !== target && current.$$nextSibling)))) {\n\t while (current !== target && !(next = current.$$nextSibling)) {\n\t current = current.$parent;\n\t }\n\t }\n\t } while ((current = next));\n\t\n\t // `break traverseScopesLoop;` takes us to here\n\t\n\t if ((dirty || asyncQueue.length) && !(ttl--)) {\n\t clearPhase();\n\t throw $rootScopeMinErr('infdig',\n\t '{0} $digest() iterations reached. Aborting!\\n' +\n\t 'Watchers fired in the last 5 iterations: {1}',\n\t TTL, watchLog);\n\t }\n\t\n\t } while (dirty || asyncQueue.length);\n\t\n\t clearPhase();\n\t\n\t // postDigestQueuePosition isn't local here because this loop can be reentered recursively.\n\t while (postDigestQueuePosition < postDigestQueue.length) {\n\t try {\n\t postDigestQueue[postDigestQueuePosition++]();\n\t } catch (e) {\n\t $exceptionHandler(e);\n\t }\n\t }\n\t postDigestQueue.length = postDigestQueuePosition = 0;\n\t },\n\t\n\t\n\t /**\n\t * @ngdoc event\n\t * @name $rootScope.Scope#$destroy\n\t * @eventType broadcast on scope being destroyed\n\t *\n\t * @description\n\t * Broadcasted when a scope and its children are being destroyed.\n\t *\n\t * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to\n\t * clean up DOM bindings before an element is removed from the DOM.\n\t */\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $rootScope.Scope#$destroy\n\t * @kind function\n\t *\n\t * @description\n\t * Removes the current scope (and all of its children) from the parent scope. Removal implies\n\t * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n\t * propagate to the current scope and its children. Removal also implies that the current\n\t * scope is eligible for garbage collection.\n\t *\n\t * The `$destroy()` is usually used by directives such as\n\t * {@link ng.directive:ngRepeat ngRepeat} for managing the\n\t * unrolling of the loop.\n\t *\n\t * Just before a scope is destroyed, a `$destroy` event is broadcasted on this scope.\n\t * Application code can register a `$destroy` event handler that will give it a chance to\n\t * perform any necessary cleanup.\n\t *\n\t * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to\n\t * clean up DOM bindings before an element is removed from the DOM.\n\t */\n\t $destroy: function() {\n\t // We can't destroy a scope that has been already destroyed.\n\t if (this.$$destroyed) return;\n\t var parent = this.$parent;\n\t\n\t this.$broadcast('$destroy');\n\t this.$$destroyed = true;\n\t\n\t if (this === $rootScope) {\n\t //Remove handlers attached to window when $rootScope is removed\n\t $browser.$$applicationDestroyed();\n\t }\n\t\n\t incrementWatchersCount(this, -this.$$watchersCount);\n\t for (var eventName in this.$$listenerCount) {\n\t decrementListenerCount(this, this.$$listenerCount[eventName], eventName);\n\t }\n\t\n\t // sever all the references to parent scopes (after this cleanup, the current scope should\n\t // not be retained by any of our references and should be eligible for garbage collection)\n\t if (parent && parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n\t if (parent && parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n\t if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n\t if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\t\n\t // Disable listeners, watchers and apply/digest methods\n\t this.$destroy = this.$digest = this.$apply = this.$evalAsync = this.$applyAsync = noop;\n\t this.$on = this.$watch = this.$watchGroup = function() { return noop; };\n\t this.$$listeners = {};\n\t\n\t // Disconnect the next sibling to prevent `cleanUpScope` destroying those too\n\t this.$$nextSibling = null;\n\t cleanUpScope(this);\n\t },\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $rootScope.Scope#$eval\n\t * @kind function\n\t *\n\t * @description\n\t * Executes the `expression` on the current scope and returns the result. Any exceptions in\n\t * the expression are propagated (uncaught). This is useful when evaluating Angular\n\t * expressions.\n\t *\n\t * # Example\n\t * ```js\n\t var scope = ng.$rootScope.Scope();\n\t scope.a = 1;\n\t scope.b = 2;\n\t\n\t expect(scope.$eval('a+b')).toEqual(3);\n\t expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n\t * ```\n\t *\n\t * @param {(string|function())=} expression An angular expression to be executed.\n\t *\n\t * - `string`: execute using the rules as defined in {@link guide/expression expression}.\n\t * - `function(scope)`: execute the function with the current `scope` parameter.\n\t *\n\t * @param {(object)=} locals Local variables object, useful for overriding values in scope.\n\t * @returns {*} The result of evaluating the expression.\n\t */\n\t $eval: function(expr, locals) {\n\t return $parse(expr)(this, locals);\n\t },\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $rootScope.Scope#$evalAsync\n\t * @kind function\n\t *\n\t * @description\n\t * Executes the expression on the current scope at a later point in time.\n\t *\n\t * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only\n\t * that:\n\t *\n\t * - it will execute after the function that scheduled the evaluation (preferably before DOM\n\t * rendering).\n\t * - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n\t * `expression` execution.\n\t *\n\t * Any exceptions from the execution of the expression are forwarded to the\n\t * {@link ng.$exceptionHandler $exceptionHandler} service.\n\t *\n\t * __Note:__ if this function is called outside of a `$digest` cycle, a new `$digest` cycle\n\t * will be scheduled. However, it is encouraged to always call code that changes the model\n\t * from within an `$apply` call. That includes code evaluated via `$evalAsync`.\n\t *\n\t * @param {(string|function())=} expression An angular expression to be executed.\n\t *\n\t * - `string`: execute using the rules as defined in {@link guide/expression expression}.\n\t * - `function(scope)`: execute the function with the current `scope` parameter.\n\t *\n\t * @param {(object)=} locals Local variables object, useful for overriding values in scope.\n\t */\n\t $evalAsync: function(expr, locals) {\n\t // if we are outside of an $digest loop and this is the first time we are scheduling async\n\t // task also schedule async auto-flush\n\t if (!$rootScope.$$phase && !asyncQueue.length) {\n\t $browser.defer(function() {\n\t if (asyncQueue.length) {\n\t $rootScope.$digest();\n\t }\n\t });\n\t }\n\t\n\t asyncQueue.push({scope: this, expression: $parse(expr), locals: locals});\n\t },\n\t\n\t $$postDigest: function(fn) {\n\t postDigestQueue.push(fn);\n\t },\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $rootScope.Scope#$apply\n\t * @kind function\n\t *\n\t * @description\n\t * `$apply()` is used to execute an expression in angular from outside of the angular\n\t * framework. (For example from browser DOM events, setTimeout, XHR or third party libraries).\n\t * Because we are calling into the angular framework we need to perform proper scope life\n\t * cycle of {@link ng.$exceptionHandler exception handling},\n\t * {@link ng.$rootScope.Scope#$digest executing watches}.\n\t *\n\t * ## Life cycle\n\t *\n\t * # Pseudo-Code of `$apply()`\n\t * ```js\n\t function $apply(expr) {\n\t try {\n\t return $eval(expr);\n\t } catch (e) {\n\t $exceptionHandler(e);\n\t } finally {\n\t $root.$digest();\n\t }\n\t }\n\t * ```\n\t *\n\t *\n\t * Scope's `$apply()` method transitions through the following stages:\n\t *\n\t * 1. The {@link guide/expression expression} is executed using the\n\t * {@link ng.$rootScope.Scope#$eval $eval()} method.\n\t * 2. Any exceptions from the execution of the expression are forwarded to the\n\t * {@link ng.$exceptionHandler $exceptionHandler} service.\n\t * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the\n\t * expression was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n\t *\n\t *\n\t * @param {(string|function())=} exp An angular expression to be executed.\n\t *\n\t * - `string`: execute using the rules as defined in {@link guide/expression expression}.\n\t * - `function(scope)`: execute the function with current `scope` parameter.\n\t *\n\t * @returns {*} The result of evaluating the expression.\n\t */\n\t $apply: function(expr) {\n\t try {\n\t beginPhase('$apply');\n\t try {\n\t return this.$eval(expr);\n\t } finally {\n\t clearPhase();\n\t }\n\t } catch (e) {\n\t $exceptionHandler(e);\n\t } finally {\n\t try {\n\t $rootScope.$digest();\n\t } catch (e) {\n\t $exceptionHandler(e);\n\t throw e;\n\t }\n\t }\n\t },\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $rootScope.Scope#$applyAsync\n\t * @kind function\n\t *\n\t * @description\n\t * Schedule the invocation of $apply to occur at a later time. The actual time difference\n\t * varies across browsers, but is typically around ~10 milliseconds.\n\t *\n\t * This can be used to queue up multiple expressions which need to be evaluated in the same\n\t * digest.\n\t *\n\t * @param {(string|function())=} exp An angular expression to be executed.\n\t *\n\t * - `string`: execute using the rules as defined in {@link guide/expression expression}.\n\t * - `function(scope)`: execute the function with current `scope` parameter.\n\t */\n\t $applyAsync: function(expr) {\n\t var scope = this;\n\t expr && applyAsyncQueue.push($applyAsyncExpression);\n\t expr = $parse(expr);\n\t scheduleApplyAsync();\n\t\n\t function $applyAsyncExpression() {\n\t scope.$eval(expr);\n\t }\n\t },\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $rootScope.Scope#$on\n\t * @kind function\n\t *\n\t * @description\n\t * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for\n\t * discussion of event life cycle.\n\t *\n\t * The event listener function format is: `function(event, args...)`. The `event` object\n\t * passed into the listener has the following attributes:\n\t *\n\t * - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or\n\t * `$broadcast`-ed.\n\t * - `currentScope` - `{Scope}`: the scope that is currently handling the event. Once the\n\t * event propagates through the scope hierarchy, this property is set to null.\n\t * - `name` - `{string}`: name of the event.\n\t * - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel\n\t * further event propagation (available only for events that were `$emit`-ed).\n\t * - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag\n\t * to true.\n\t * - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n\t *\n\t * @param {string} name Event name to listen on.\n\t * @param {function(event, ...args)} listener Function to call when the event is emitted.\n\t * @returns {function()} Returns a deregistration function for this listener.\n\t */\n\t $on: function(name, listener) {\n\t var namedListeners = this.$$listeners[name];\n\t if (!namedListeners) {\n\t this.$$listeners[name] = namedListeners = [];\n\t }\n\t namedListeners.push(listener);\n\t\n\t var current = this;\n\t do {\n\t if (!current.$$listenerCount[name]) {\n\t current.$$listenerCount[name] = 0;\n\t }\n\t current.$$listenerCount[name]++;\n\t } while ((current = current.$parent));\n\t\n\t var self = this;\n\t return function() {\n\t var indexOfListener = namedListeners.indexOf(listener);\n\t if (indexOfListener !== -1) {\n\t namedListeners[indexOfListener] = null;\n\t decrementListenerCount(self, 1, name);\n\t }\n\t };\n\t },\n\t\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $rootScope.Scope#$emit\n\t * @kind function\n\t *\n\t * @description\n\t * Dispatches an event `name` upwards through the scope hierarchy notifying the\n\t * registered {@link ng.$rootScope.Scope#$on} listeners.\n\t *\n\t * The event life cycle starts at the scope on which `$emit` was called. All\n\t * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get\n\t * notified. Afterwards, the event traverses upwards toward the root scope and calls all\n\t * registered listeners along the way. The event will stop propagating if one of the listeners\n\t * cancels it.\n\t *\n\t * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n\t * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n\t *\n\t * @param {string} name Event name to emit.\n\t * @param {...*} args Optional one or more arguments which will be passed onto the event listeners.\n\t * @return {Object} Event object (see {@link ng.$rootScope.Scope#$on}).\n\t */\n\t $emit: function(name, args) {\n\t var empty = [],\n\t namedListeners,\n\t scope = this,\n\t stopPropagation = false,\n\t event = {\n\t name: name,\n\t targetScope: scope,\n\t stopPropagation: function() {stopPropagation = true;},\n\t preventDefault: function() {\n\t event.defaultPrevented = true;\n\t },\n\t defaultPrevented: false\n\t },\n\t listenerArgs = concat([event], arguments, 1),\n\t i, length;\n\t\n\t do {\n\t namedListeners = scope.$$listeners[name] || empty;\n\t event.currentScope = scope;\n\t for (i = 0, length = namedListeners.length; i < length; i++) {\n\t\n\t // if listeners were deregistered, defragment the array\n\t if (!namedListeners[i]) {\n\t namedListeners.splice(i, 1);\n\t i--;\n\t length--;\n\t continue;\n\t }\n\t try {\n\t //allow all listeners attached to the current scope to run\n\t namedListeners[i].apply(null, listenerArgs);\n\t } catch (e) {\n\t $exceptionHandler(e);\n\t }\n\t }\n\t //if any listener on the current scope stops propagation, prevent bubbling\n\t if (stopPropagation) {\n\t event.currentScope = null;\n\t return event;\n\t }\n\t //traverse upwards\n\t scope = scope.$parent;\n\t } while (scope);\n\t\n\t event.currentScope = null;\n\t\n\t return event;\n\t },\n\t\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $rootScope.Scope#$broadcast\n\t * @kind function\n\t *\n\t * @description\n\t * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n\t * registered {@link ng.$rootScope.Scope#$on} listeners.\n\t *\n\t * The event life cycle starts at the scope on which `$broadcast` was called. All\n\t * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get\n\t * notified. Afterwards, the event propagates to all direct and indirect scopes of the current\n\t * scope and calls all registered listeners along the way. The event cannot be canceled.\n\t *\n\t * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n\t * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n\t *\n\t * @param {string} name Event name to broadcast.\n\t * @param {...*} args Optional one or more arguments which will be passed onto the event listeners.\n\t * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n\t */\n\t $broadcast: function(name, args) {\n\t var target = this,\n\t current = target,\n\t next = target,\n\t event = {\n\t name: name,\n\t targetScope: target,\n\t preventDefault: function() {\n\t event.defaultPrevented = true;\n\t },\n\t defaultPrevented: false\n\t };\n\t\n\t if (!target.$$listenerCount[name]) return event;\n\t\n\t var listenerArgs = concat([event], arguments, 1),\n\t listeners, i, length;\n\t\n\t //down while you can, then up and next sibling or up and next sibling until back at root\n\t while ((current = next)) {\n\t event.currentScope = current;\n\t listeners = current.$$listeners[name] || [];\n\t for (i = 0, length = listeners.length; i < length; i++) {\n\t // if listeners were deregistered, defragment the array\n\t if (!listeners[i]) {\n\t listeners.splice(i, 1);\n\t i--;\n\t length--;\n\t continue;\n\t }\n\t\n\t try {\n\t listeners[i].apply(null, listenerArgs);\n\t } catch (e) {\n\t $exceptionHandler(e);\n\t }\n\t }\n\t\n\t // Insanity Warning: scope depth-first traversal\n\t // yes, this code is a bit crazy, but it works and we have tests to prove it!\n\t // this piece should be kept in sync with the traversal in $digest\n\t // (though it differs due to having the extra check for $$listenerCount)\n\t if (!(next = ((current.$$listenerCount[name] && current.$$childHead) ||\n\t (current !== target && current.$$nextSibling)))) {\n\t while (current !== target && !(next = current.$$nextSibling)) {\n\t current = current.$parent;\n\t }\n\t }\n\t }\n\t\n\t event.currentScope = null;\n\t return event;\n\t }\n\t };\n\t\n\t var $rootScope = new Scope();\n\t\n\t //The internal queues. Expose them on the $rootScope for debugging/testing purposes.\n\t var asyncQueue = $rootScope.$$asyncQueue = [];\n\t var postDigestQueue = $rootScope.$$postDigestQueue = [];\n\t var applyAsyncQueue = $rootScope.$$applyAsyncQueue = [];\n\t\n\t var postDigestQueuePosition = 0;\n\t\n\t return $rootScope;\n\t\n\t\n\t function beginPhase(phase) {\n\t if ($rootScope.$$phase) {\n\t throw $rootScopeMinErr('inprog', '{0} already in progress', $rootScope.$$phase);\n\t }\n\t\n\t $rootScope.$$phase = phase;\n\t }\n\t\n\t function clearPhase() {\n\t $rootScope.$$phase = null;\n\t }\n\t\n\t function incrementWatchersCount(current, count) {\n\t do {\n\t current.$$watchersCount += count;\n\t } while ((current = current.$parent));\n\t }\n\t\n\t function decrementListenerCount(current, count, name) {\n\t do {\n\t current.$$listenerCount[name] -= count;\n\t\n\t if (current.$$listenerCount[name] === 0) {\n\t delete current.$$listenerCount[name];\n\t }\n\t } while ((current = current.$parent));\n\t }\n\t\n\t /**\n\t * function used as an initial value for watchers.\n\t * because it's unique we can easily tell it apart from other values\n\t */\n\t function initWatchVal() {}\n\t\n\t function flushApplyAsync() {\n\t while (applyAsyncQueue.length) {\n\t try {\n\t applyAsyncQueue.shift()();\n\t } catch (e) {\n\t $exceptionHandler(e);\n\t }\n\t }\n\t applyAsyncId = null;\n\t }\n\t\n\t function scheduleApplyAsync() {\n\t if (applyAsyncId === null) {\n\t applyAsyncId = $browser.defer(function() {\n\t $rootScope.$apply(flushApplyAsync);\n\t });\n\t }\n\t }\n\t }];\n\t}\n\t\n\t/**\n\t * @ngdoc service\n\t * @name $rootElement\n\t *\n\t * @description\n\t * The root element of Angular application. This is either the element where {@link\n\t * ng.directive:ngApp ngApp} was declared or the element passed into\n\t * {@link angular.bootstrap}. The element represents the root element of application. It is also the\n\t * location where the application's {@link auto.$injector $injector} service gets\n\t * published, and can be retrieved using `$rootElement.injector()`.\n\t */\n\t\n\t\n\t// the implementation is in angular.bootstrap\n\t\n\t/**\n\t * @description\n\t * Private service to sanitize uris for links and images. Used by $compile and $sanitize.\n\t */\n\tfunction $$SanitizeUriProvider() {\n\t var aHrefSanitizationWhitelist = /^\\s*(https?|ftp|mailto|tel|file):/,\n\t imgSrcSanitizationWhitelist = /^\\s*((https?|ftp|file|blob):|data:image\\/)/;\n\t\n\t /**\n\t * @description\n\t * Retrieves or overrides the default regular expression that is used for whitelisting of safe\n\t * urls during a[href] sanitization.\n\t *\n\t * The sanitization is a security measure aimed at prevent XSS attacks via html links.\n\t *\n\t * Any url about to be assigned to a[href] via data-binding is first normalized and turned into\n\t * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist`\n\t * regular expression. If a match is found, the original url is written into the dom. Otherwise,\n\t * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.\n\t *\n\t * @param {RegExp=} regexp New regexp to whitelist urls with.\n\t * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for\n\t * chaining otherwise.\n\t */\n\t this.aHrefSanitizationWhitelist = function(regexp) {\n\t if (isDefined(regexp)) {\n\t aHrefSanitizationWhitelist = regexp;\n\t return this;\n\t }\n\t return aHrefSanitizationWhitelist;\n\t };\n\t\n\t\n\t /**\n\t * @description\n\t * Retrieves or overrides the default regular expression that is used for whitelisting of safe\n\t * urls during img[src] sanitization.\n\t *\n\t * The sanitization is a security measure aimed at prevent XSS attacks via html links.\n\t *\n\t * Any url about to be assigned to img[src] via data-binding is first normalized and turned into\n\t * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist`\n\t * regular expression. If a match is found, the original url is written into the dom. Otherwise,\n\t * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.\n\t *\n\t * @param {RegExp=} regexp New regexp to whitelist urls with.\n\t * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for\n\t * chaining otherwise.\n\t */\n\t this.imgSrcSanitizationWhitelist = function(regexp) {\n\t if (isDefined(regexp)) {\n\t imgSrcSanitizationWhitelist = regexp;\n\t return this;\n\t }\n\t return imgSrcSanitizationWhitelist;\n\t };\n\t\n\t this.$get = function() {\n\t return function sanitizeUri(uri, isImage) {\n\t var regex = isImage ? imgSrcSanitizationWhitelist : aHrefSanitizationWhitelist;\n\t var normalizedVal;\n\t normalizedVal = urlResolve(uri).href;\n\t if (normalizedVal !== '' && !normalizedVal.match(regex)) {\n\t return 'unsafe:' + normalizedVal;\n\t }\n\t return uri;\n\t };\n\t };\n\t}\n\t\n\t/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n\t * Any commits to this file should be reviewed with security in mind. *\n\t * Changes to this file can potentially create security vulnerabilities. *\n\t * An approval from 2 Core members with history of modifying *\n\t * this file is required. *\n\t * *\n\t * Does the change somehow allow for arbitrary javascript to be executed? *\n\t * Or allows for someone to change the prototype of built-in objects? *\n\t * Or gives undesired access to variables likes document or window? *\n\t * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */\n\t\n\tvar $sceMinErr = minErr('$sce');\n\t\n\tvar SCE_CONTEXTS = {\n\t HTML: 'html',\n\t CSS: 'css',\n\t URL: 'url',\n\t // RESOURCE_URL is a subtype of URL used in contexts where a privileged resource is sourced from a\n\t // url. (e.g. ng-include, script src, templateUrl)\n\t RESOURCE_URL: 'resourceUrl',\n\t JS: 'js'\n\t};\n\t\n\t// Helper functions follow.\n\t\n\tfunction adjustMatcher(matcher) {\n\t if (matcher === 'self') {\n\t return matcher;\n\t } else if (isString(matcher)) {\n\t // Strings match exactly except for 2 wildcards - '*' and '**'.\n\t // '*' matches any character except those from the set ':/.?&'.\n\t // '**' matches any character (like .* in a RegExp).\n\t // More than 2 *'s raises an error as it's ill defined.\n\t if (matcher.indexOf('***') > -1) {\n\t throw $sceMinErr('iwcard',\n\t 'Illegal sequence *** in string matcher. String: {0}', matcher);\n\t }\n\t matcher = escapeForRegexp(matcher).\n\t replace('\\\\*\\\\*', '.*').\n\t replace('\\\\*', '[^:/.?&;]*');\n\t return new RegExp('^' + matcher + '$');\n\t } else if (isRegExp(matcher)) {\n\t // The only other type of matcher allowed is a Regexp.\n\t // Match entire URL / disallow partial matches.\n\t // Flags are reset (i.e. no global, ignoreCase or multiline)\n\t return new RegExp('^' + matcher.source + '$');\n\t } else {\n\t throw $sceMinErr('imatcher',\n\t 'Matchers may only be \"self\", string patterns or RegExp objects');\n\t }\n\t}\n\t\n\t\n\tfunction adjustMatchers(matchers) {\n\t var adjustedMatchers = [];\n\t if (isDefined(matchers)) {\n\t forEach(matchers, function(matcher) {\n\t adjustedMatchers.push(adjustMatcher(matcher));\n\t });\n\t }\n\t return adjustedMatchers;\n\t}\n\t\n\t\n\t/**\n\t * @ngdoc service\n\t * @name $sceDelegate\n\t * @kind function\n\t *\n\t * @description\n\t *\n\t * `$sceDelegate` is a service that is used by the `$sce` service to provide {@link ng.$sce Strict\n\t * Contextual Escaping (SCE)} services to AngularJS.\n\t *\n\t * Typically, you would configure or override the {@link ng.$sceDelegate $sceDelegate} instead of\n\t * the `$sce` service to customize the way Strict Contextual Escaping works in AngularJS. This is\n\t * because, while the `$sce` provides numerous shorthand methods, etc., you really only need to\n\t * override 3 core functions (`trustAs`, `getTrusted` and `valueOf`) to replace the way things\n\t * work because `$sce` delegates to `$sceDelegate` for these operations.\n\t *\n\t * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} to configure this service.\n\t *\n\t * The default instance of `$sceDelegate` should work out of the box with little pain. While you\n\t * can override it completely to change the behavior of `$sce`, the common case would\n\t * involve configuring the {@link ng.$sceDelegateProvider $sceDelegateProvider} instead by setting\n\t * your own whitelists and blacklists for trusting URLs used for loading AngularJS resources such as\n\t * templates. Refer {@link ng.$sceDelegateProvider#resourceUrlWhitelist\n\t * $sceDelegateProvider.resourceUrlWhitelist} and {@link\n\t * ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist}\n\t */\n\t\n\t/**\n\t * @ngdoc provider\n\t * @name $sceDelegateProvider\n\t * @description\n\t *\n\t * The `$sceDelegateProvider` provider allows developers to configure the {@link ng.$sceDelegate\n\t * $sceDelegate} service. This allows one to get/set the whitelists and blacklists used to ensure\n\t * that the URLs used for sourcing Angular templates are safe. Refer {@link\n\t * ng.$sceDelegateProvider#resourceUrlWhitelist $sceDelegateProvider.resourceUrlWhitelist} and\n\t * {@link ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist}\n\t *\n\t * For the general details about this service in Angular, read the main page for {@link ng.$sce\n\t * Strict Contextual Escaping (SCE)}.\n\t *\n\t * **Example**: Consider the following case. \n\t *\n\t * - your app is hosted at url `http://myapp.example.com/`\n\t * - but some of your templates are hosted on other domains you control such as\n\t * `http://srv01.assets.example.com/`,  `http://srv02.assets.example.com/`, etc.\n\t * - and you have an open redirect at `http://myapp.example.com/clickThru?...`.\n\t *\n\t * Here is what a secure configuration for this scenario might look like:\n\t *\n\t * ```\n\t * angular.module('myApp', []).config(function($sceDelegateProvider) {\n\t * $sceDelegateProvider.resourceUrlWhitelist([\n\t * // Allow same origin resource loads.\n\t * 'self',\n\t * // Allow loading from our assets domain. Notice the difference between * and **.\n\t * 'http://srv*.assets.example.com/**'\n\t * ]);\n\t *\n\t * // The blacklist overrides the whitelist so the open redirect here is blocked.\n\t * $sceDelegateProvider.resourceUrlBlacklist([\n\t * 'http://myapp.example.com/clickThru**'\n\t * ]);\n\t * });\n\t * ```\n\t */\n\t\n\tfunction $SceDelegateProvider() {\n\t this.SCE_CONTEXTS = SCE_CONTEXTS;\n\t\n\t // Resource URLs can also be trusted by policy.\n\t var resourceUrlWhitelist = ['self'],\n\t resourceUrlBlacklist = [];\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $sceDelegateProvider#resourceUrlWhitelist\n\t * @kind function\n\t *\n\t * @param {Array=} whitelist When provided, replaces the resourceUrlWhitelist with the value\n\t * provided. This must be an array or null. A snapshot of this array is used so further\n\t * changes to the array are ignored.\n\t *\n\t * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items\n\t * allowed in this array.\n\t *\n\t *
\n\t * **Note:** an empty whitelist array will block all URLs!\n\t *
\n\t *\n\t * @return {Array} the currently set whitelist array.\n\t *\n\t * The **default value** when no whitelist has been explicitly set is `['self']` allowing only\n\t * same origin resource requests.\n\t *\n\t * @description\n\t * Sets/Gets the whitelist of trusted resource URLs.\n\t */\n\t this.resourceUrlWhitelist = function(value) {\n\t if (arguments.length) {\n\t resourceUrlWhitelist = adjustMatchers(value);\n\t }\n\t return resourceUrlWhitelist;\n\t };\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $sceDelegateProvider#resourceUrlBlacklist\n\t * @kind function\n\t *\n\t * @param {Array=} blacklist When provided, replaces the resourceUrlBlacklist with the value\n\t * provided. This must be an array or null. A snapshot of this array is used so further\n\t * changes to the array are ignored.\n\t *\n\t * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items\n\t * allowed in this array.\n\t *\n\t * The typical usage for the blacklist is to **block\n\t * [open redirects](http://cwe.mitre.org/data/definitions/601.html)** served by your domain as\n\t * these would otherwise be trusted but actually return content from the redirected domain.\n\t *\n\t * Finally, **the blacklist overrides the whitelist** and has the final say.\n\t *\n\t * @return {Array} the currently set blacklist array.\n\t *\n\t * The **default value** when no whitelist has been explicitly set is the empty array (i.e. there\n\t * is no blacklist.)\n\t *\n\t * @description\n\t * Sets/Gets the blacklist of trusted resource URLs.\n\t */\n\t\n\t this.resourceUrlBlacklist = function(value) {\n\t if (arguments.length) {\n\t resourceUrlBlacklist = adjustMatchers(value);\n\t }\n\t return resourceUrlBlacklist;\n\t };\n\t\n\t this.$get = ['$injector', function($injector) {\n\t\n\t var htmlSanitizer = function htmlSanitizer(html) {\n\t throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.');\n\t };\n\t\n\t if ($injector.has('$sanitize')) {\n\t htmlSanitizer = $injector.get('$sanitize');\n\t }\n\t\n\t\n\t function matchUrl(matcher, parsedUrl) {\n\t if (matcher === 'self') {\n\t return urlIsSameOrigin(parsedUrl);\n\t } else {\n\t // definitely a regex. See adjustMatchers()\n\t return !!matcher.exec(parsedUrl.href);\n\t }\n\t }\n\t\n\t function isResourceUrlAllowedByPolicy(url) {\n\t var parsedUrl = urlResolve(url.toString());\n\t var i, n, allowed = false;\n\t // Ensure that at least one item from the whitelist allows this url.\n\t for (i = 0, n = resourceUrlWhitelist.length; i < n; i++) {\n\t if (matchUrl(resourceUrlWhitelist[i], parsedUrl)) {\n\t allowed = true;\n\t break;\n\t }\n\t }\n\t if (allowed) {\n\t // Ensure that no item from the blacklist blocked this url.\n\t for (i = 0, n = resourceUrlBlacklist.length; i < n; i++) {\n\t if (matchUrl(resourceUrlBlacklist[i], parsedUrl)) {\n\t allowed = false;\n\t break;\n\t }\n\t }\n\t }\n\t return allowed;\n\t }\n\t\n\t function generateHolderType(Base) {\n\t var holderType = function TrustedValueHolderType(trustedValue) {\n\t this.$$unwrapTrustedValue = function() {\n\t return trustedValue;\n\t };\n\t };\n\t if (Base) {\n\t holderType.prototype = new Base();\n\t }\n\t holderType.prototype.valueOf = function sceValueOf() {\n\t return this.$$unwrapTrustedValue();\n\t };\n\t holderType.prototype.toString = function sceToString() {\n\t return this.$$unwrapTrustedValue().toString();\n\t };\n\t return holderType;\n\t }\n\t\n\t var trustedValueHolderBase = generateHolderType(),\n\t byType = {};\n\t\n\t byType[SCE_CONTEXTS.HTML] = generateHolderType(trustedValueHolderBase);\n\t byType[SCE_CONTEXTS.CSS] = generateHolderType(trustedValueHolderBase);\n\t byType[SCE_CONTEXTS.URL] = generateHolderType(trustedValueHolderBase);\n\t byType[SCE_CONTEXTS.JS] = generateHolderType(trustedValueHolderBase);\n\t byType[SCE_CONTEXTS.RESOURCE_URL] = generateHolderType(byType[SCE_CONTEXTS.URL]);\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $sceDelegate#trustAs\n\t *\n\t * @description\n\t * Returns an object that is trusted by angular for use in specified strict\n\t * contextual escaping contexts (such as ng-bind-html, ng-include, any src\n\t * attribute interpolation, any dom event binding attribute interpolation\n\t * such as for onclick, etc.) that uses the provided value.\n\t * See {@link ng.$sce $sce} for enabling strict contextual escaping.\n\t *\n\t * @param {string} type The kind of context in which this value is safe for use. e.g. url,\n\t * resourceUrl, html, js and css.\n\t * @param {*} value The value that that should be considered trusted/safe.\n\t * @returns {*} A value that can be used to stand in for the provided `value` in places\n\t * where Angular expects a $sce.trustAs() return value.\n\t */\n\t function trustAs(type, trustedValue) {\n\t var Constructor = (byType.hasOwnProperty(type) ? byType[type] : null);\n\t if (!Constructor) {\n\t throw $sceMinErr('icontext',\n\t 'Attempted to trust a value in invalid context. Context: {0}; Value: {1}',\n\t type, trustedValue);\n\t }\n\t if (trustedValue === null || isUndefined(trustedValue) || trustedValue === '') {\n\t return trustedValue;\n\t }\n\t // All the current contexts in SCE_CONTEXTS happen to be strings. In order to avoid trusting\n\t // mutable objects, we ensure here that the value passed in is actually a string.\n\t if (typeof trustedValue !== 'string') {\n\t throw $sceMinErr('itype',\n\t 'Attempted to trust a non-string value in a content requiring a string: Context: {0}',\n\t type);\n\t }\n\t return new Constructor(trustedValue);\n\t }\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $sceDelegate#valueOf\n\t *\n\t * @description\n\t * If the passed parameter had been returned by a prior call to {@link ng.$sceDelegate#trustAs\n\t * `$sceDelegate.trustAs`}, returns the value that had been passed to {@link\n\t * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}.\n\t *\n\t * If the passed parameter is not a value that had been returned by {@link\n\t * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}, returns it as-is.\n\t *\n\t * @param {*} value The result of a prior {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}\n\t * call or anything else.\n\t * @returns {*} The `value` that was originally provided to {@link ng.$sceDelegate#trustAs\n\t * `$sceDelegate.trustAs`} if `value` is the result of such a call. Otherwise, returns\n\t * `value` unchanged.\n\t */\n\t function valueOf(maybeTrusted) {\n\t if (maybeTrusted instanceof trustedValueHolderBase) {\n\t return maybeTrusted.$$unwrapTrustedValue();\n\t } else {\n\t return maybeTrusted;\n\t }\n\t }\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $sceDelegate#getTrusted\n\t *\n\t * @description\n\t * Takes the result of a {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`} call and\n\t * returns the originally supplied value if the queried context type is a supertype of the\n\t * created type. If this condition isn't satisfied, throws an exception.\n\t *\n\t *
\n\t * Disabling auto-escaping is extremely dangerous, it usually creates a Cross Site Scripting\n\t * (XSS) vulnerability in your application.\n\t *
\n\t *\n\t * @param {string} type The kind of context in which this value is to be used.\n\t * @param {*} maybeTrusted The result of a prior {@link ng.$sceDelegate#trustAs\n\t * `$sceDelegate.trustAs`} call.\n\t * @returns {*} The value the was originally provided to {@link ng.$sceDelegate#trustAs\n\t * `$sceDelegate.trustAs`} if valid in this context. Otherwise, throws an exception.\n\t */\n\t function getTrusted(type, maybeTrusted) {\n\t if (maybeTrusted === null || isUndefined(maybeTrusted) || maybeTrusted === '') {\n\t return maybeTrusted;\n\t }\n\t var constructor = (byType.hasOwnProperty(type) ? byType[type] : null);\n\t if (constructor && maybeTrusted instanceof constructor) {\n\t return maybeTrusted.$$unwrapTrustedValue();\n\t }\n\t // If we get here, then we may only take one of two actions.\n\t // 1. sanitize the value for the requested type, or\n\t // 2. throw an exception.\n\t if (type === SCE_CONTEXTS.RESOURCE_URL) {\n\t if (isResourceUrlAllowedByPolicy(maybeTrusted)) {\n\t return maybeTrusted;\n\t } else {\n\t throw $sceMinErr('insecurl',\n\t 'Blocked loading resource from url not allowed by $sceDelegate policy. URL: {0}',\n\t maybeTrusted.toString());\n\t }\n\t } else if (type === SCE_CONTEXTS.HTML) {\n\t return htmlSanitizer(maybeTrusted);\n\t }\n\t throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.');\n\t }\n\t\n\t return { trustAs: trustAs,\n\t getTrusted: getTrusted,\n\t valueOf: valueOf };\n\t }];\n\t}\n\t\n\t\n\t/**\n\t * @ngdoc provider\n\t * @name $sceProvider\n\t * @description\n\t *\n\t * The $sceProvider provider allows developers to configure the {@link ng.$sce $sce} service.\n\t * - enable/disable Strict Contextual Escaping (SCE) in a module\n\t * - override the default implementation with a custom delegate\n\t *\n\t * Read more about {@link ng.$sce Strict Contextual Escaping (SCE)}.\n\t */\n\t\n\t/* jshint maxlen: false*/\n\t\n\t/**\n\t * @ngdoc service\n\t * @name $sce\n\t * @kind function\n\t *\n\t * @description\n\t *\n\t * `$sce` is a service that provides Strict Contextual Escaping services to AngularJS.\n\t *\n\t * # Strict Contextual Escaping\n\t *\n\t * Strict Contextual Escaping (SCE) is a mode in which AngularJS requires bindings in certain\n\t * contexts to result in a value that is marked as safe to use for that context. One example of\n\t * such a context is binding arbitrary html controlled by the user via `ng-bind-html`. We refer\n\t * to these contexts as privileged or SCE contexts.\n\t *\n\t * As of version 1.2, Angular ships with SCE enabled by default.\n\t *\n\t * Note: When enabled (the default), IE<11 in quirks mode is not supported. In this mode, IE<11 allow\n\t * one to execute arbitrary javascript by the use of the expression() syntax. Refer\n\t * to learn more about them.\n\t * You can ensure your document is in standards mode and not quirks mode by adding ``\n\t * to the top of your HTML document.\n\t *\n\t * SCE assists in writing code in a way that (a) is secure by default and (b) makes auditing for\n\t * security vulnerabilities such as XSS, clickjacking, etc. a lot easier.\n\t *\n\t * Here's an example of a binding in a privileged context:\n\t *\n\t * ```\n\t * \n\t *
\n\t * ```\n\t *\n\t * Notice that `ng-bind-html` is bound to `userHtml` controlled by the user. With SCE\n\t * disabled, this application allows the user to render arbitrary HTML into the DIV.\n\t * In a more realistic example, one may be rendering user comments, blog articles, etc. via\n\t * bindings. (HTML is just one example of a context where rendering user controlled input creates\n\t * security vulnerabilities.)\n\t *\n\t * For the case of HTML, you might use a library, either on the client side, or on the server side,\n\t * to sanitize unsafe HTML before binding to the value and rendering it in the document.\n\t *\n\t * How would you ensure that every place that used these types of bindings was bound to a value that\n\t * was sanitized by your library (or returned as safe for rendering by your server?) How can you\n\t * ensure that you didn't accidentally delete the line that sanitized the value, or renamed some\n\t * properties/fields and forgot to update the binding to the sanitized value?\n\t *\n\t * To be secure by default, you want to ensure that any such bindings are disallowed unless you can\n\t * determine that something explicitly says it's safe to use a value for binding in that\n\t * context. You can then audit your code (a simple grep would do) to ensure that this is only done\n\t * for those values that you can easily tell are safe - because they were received from your server,\n\t * sanitized by your library, etc. You can organize your codebase to help with this - perhaps\n\t * allowing only the files in a specific directory to do this. Ensuring that the internal API\n\t * exposed by that code doesn't markup arbitrary values as safe then becomes a more manageable task.\n\t *\n\t * In the case of AngularJS' SCE service, one uses {@link ng.$sce#trustAs $sce.trustAs}\n\t * (and shorthand methods such as {@link ng.$sce#trustAsHtml $sce.trustAsHtml}, etc.) to\n\t * obtain values that will be accepted by SCE / privileged contexts.\n\t *\n\t *\n\t * ## How does it work?\n\t *\n\t * In privileged contexts, directives and code will bind to the result of {@link ng.$sce#getTrusted\n\t * $sce.getTrusted(context, value)} rather than to the value directly. Directives use {@link\n\t * ng.$sce#parseAs $sce.parseAs} rather than `$parse` to watch attribute bindings, which performs the\n\t * {@link ng.$sce#getTrusted $sce.getTrusted} behind the scenes on non-constant literals.\n\t *\n\t * As an example, {@link ng.directive:ngBindHtml ngBindHtml} uses {@link\n\t * ng.$sce#parseAsHtml $sce.parseAsHtml(binding expression)}. Here's the actual code (slightly\n\t * simplified):\n\t *\n\t * ```\n\t * var ngBindHtmlDirective = ['$sce', function($sce) {\n\t * return function(scope, element, attr) {\n\t * scope.$watch($sce.parseAsHtml(attr.ngBindHtml), function(value) {\n\t * element.html(value || '');\n\t * });\n\t * };\n\t * }];\n\t * ```\n\t *\n\t * ## Impact on loading templates\n\t *\n\t * This applies both to the {@link ng.directive:ngInclude `ng-include`} directive as well as\n\t * `templateUrl`'s specified by {@link guide/directive directives}.\n\t *\n\t * By default, Angular only loads templates from the same domain and protocol as the application\n\t * document. This is done by calling {@link ng.$sce#getTrustedResourceUrl\n\t * $sce.getTrustedResourceUrl} on the template URL. To load templates from other domains and/or\n\t * protocols, you may either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist\n\t * them} or {@link ng.$sce#trustAsResourceUrl wrap it} into a trusted value.\n\t *\n\t * *Please note*:\n\t * The browser's\n\t * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest)\n\t * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/)\n\t * policy apply in addition to this and may further restrict whether the template is successfully\n\t * loaded. This means that without the right CORS policy, loading templates from a different domain\n\t * won't work on all browsers. Also, loading templates from `file://` URL does not work on some\n\t * browsers.\n\t *\n\t * ## This feels like too much overhead\n\t *\n\t * It's important to remember that SCE only applies to interpolation expressions.\n\t *\n\t * If your expressions are constant literals, they're automatically trusted and you don't need to\n\t * call `$sce.trustAs` on them (remember to include the `ngSanitize` module) (e.g.\n\t * `
implicitly trusted'\">
`) just works.\n\t *\n\t * Additionally, `a[href]` and `img[src]` automatically sanitize their URLs and do not pass them\n\t * through {@link ng.$sce#getTrusted $sce.getTrusted}. SCE doesn't play a role here.\n\t *\n\t * The included {@link ng.$sceDelegate $sceDelegate} comes with sane defaults to allow you to load\n\t * templates in `ng-include` from your application's domain without having to even know about SCE.\n\t * It blocks loading templates from other domains or loading templates over http from an https\n\t * served document. You can change these by setting your own custom {@link\n\t * ng.$sceDelegateProvider#resourceUrlWhitelist whitelists} and {@link\n\t * ng.$sceDelegateProvider#resourceUrlBlacklist blacklists} for matching such URLs.\n\t *\n\t * This significantly reduces the overhead. It is far easier to pay the small overhead and have an\n\t * application that's secure and can be audited to verify that with much more ease than bolting\n\t * security onto an application later.\n\t *\n\t * \n\t * ## What trusted context types are supported?\n\t *\n\t * | Context | Notes |\n\t * |---------------------|----------------|\n\t * | `$sce.HTML` | For HTML that's safe to source into the application. The {@link ng.directive:ngBindHtml ngBindHtml} directive uses this context for bindings. If an unsafe value is encountered and the {@link ngSanitize $sanitize} module is present this will sanitize the value instead of throwing an error. |\n\t * | `$sce.CSS` | For CSS that's safe to source into the application. Currently unused. Feel free to use it in your own directives. |\n\t * | `$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\t * | `$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\t *\n\t * ## Format of items in {@link ng.$sceDelegateProvider#resourceUrlWhitelist resourceUrlWhitelist}/{@link ng.$sceDelegateProvider#resourceUrlBlacklist Blacklist}
\n\t *\n\t * Each element in these arrays must be one of the following:\n\t *\n\t * - **'self'**\n\t * - The special **string**, `'self'`, can be used to match against all URLs of the **same\n\t * domain** as the application document using the **same protocol**.\n\t * - **String** (except the special value `'self'`)\n\t * - The string is matched against the full *normalized / absolute URL* of the resource\n\t * being tested (substring matches are not good enough.)\n\t * - There are exactly **two wildcard sequences** - `*` and `**`. All other characters\n\t * match themselves.\n\t * - `*`: matches zero or more occurrences of any character other than one of the following 6\n\t * characters: '`:`', '`/`', '`.`', '`?`', '`&`' and '`;`'. It's a useful wildcard for use\n\t * in a whitelist.\n\t * - `**`: matches zero or more occurrences of *any* character. As such, it's not\n\t * appropriate for use in a scheme, domain, etc. as it would match too much. (e.g.\n\t * http://**.example.com/ would match http://evil.com/?ignore=.example.com/ and that might\n\t * not have been the intention.) Its usage at the very end of the path is ok. (e.g.\n\t * http://foo.example.com/templates/**).\n\t * - **RegExp** (*see caveat below*)\n\t * - *Caveat*: While regular expressions are powerful and offer great flexibility, their syntax\n\t * (and all the inevitable escaping) makes them *harder to maintain*. It's easy to\n\t * accidentally introduce a bug when one updates a complex expression (imho, all regexes should\n\t * have good test coverage). For instance, the use of `.` in the regex is correct only in a\n\t * small number of cases. A `.` character in the regex used when matching the scheme or a\n\t * subdomain could be matched against a `:` or literal `.` that was likely not intended. It\n\t * is highly recommended to use the string patterns and only fall back to regular expressions\n\t * as a last resort.\n\t * - The regular expression must be an instance of RegExp (i.e. not a string.) It is\n\t * matched against the **entire** *normalized / absolute URL* of the resource being tested\n\t * (even when the RegExp did not have the `^` and `$` codes.) In addition, any flags\n\t * present on the RegExp (such as multiline, global, ignoreCase) are ignored.\n\t * - If you are generating your JavaScript from some other templating engine (not\n\t * recommended, e.g. in issue [#4006](https://github.com/angular/angular.js/issues/4006)),\n\t * remember to escape your regular expression (and be aware that you might need more than\n\t * one level of escaping depending on your templating engine and the way you interpolated\n\t * the value.) Do make use of your platform's escaping mechanism as it might be good\n\t * enough before coding your own. E.g. Ruby has\n\t * [Regexp.escape(str)](http://www.ruby-doc.org/core-2.0.0/Regexp.html#method-c-escape)\n\t * and Python has [re.escape](http://docs.python.org/library/re.html#re.escape).\n\t * Javascript lacks a similar built in function for escaping. Take a look at Google\n\t * Closure library's [goog.string.regExpEscape(s)](\n\t * http://docs.closure-library.googlecode.com/git/closure_goog_string_string.js.source.html#line962).\n\t *\n\t * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} for an example.\n\t *\n\t * ## Show me an example using SCE.\n\t *\n\t * \n\t * \n\t *
\n\t *

\n\t * User comments
\n\t * By default, HTML that isn't explicitly trusted (e.g. Alice's comment) is sanitized when\n\t * $sanitize is available. If $sanitize isn't available, this results in an error instead of an\n\t * exploit.\n\t *
\n\t *
\n\t * {{userComment.name}}:\n\t * \n\t *
\n\t *
\n\t *
\n\t *
\n\t *
\n\t *\n\t * \n\t * angular.module('mySceApp', ['ngSanitize'])\n\t * .controller('AppController', ['$http', '$templateCache', '$sce',\n\t * function($http, $templateCache, $sce) {\n\t * var self = this;\n\t * $http.get(\"test_data.json\", {cache: $templateCache}).success(function(userComments) {\n\t * self.userComments = userComments;\n\t * });\n\t * self.explicitlyTrustedHtml = $sce.trustAsHtml(\n\t * 'Hover over this text.');\n\t * }]);\n\t * \n\t *\n\t * \n\t * [\n\t * { \"name\": \"Alice\",\n\t * \"htmlComment\":\n\t * \"Is anyone reading this?\"\n\t * },\n\t * { \"name\": \"Bob\",\n\t * \"htmlComment\": \"Yes! Am I the only other one?\"\n\t * }\n\t * ]\n\t * \n\t *\n\t * \n\t * describe('SCE doc demo', function() {\n\t * it('should sanitize untrusted values', function() {\n\t * expect(element.all(by.css('.htmlComment')).first().getInnerHtml())\n\t * .toBe('Is anyone reading this?');\n\t * });\n\t *\n\t * it('should NOT sanitize explicitly trusted values', function() {\n\t * expect(element(by.id('explicitlyTrustedHtml')).getInnerHtml()).toBe(\n\t * 'Hover over this text.');\n\t * });\n\t * });\n\t * \n\t *
\n\t *\n\t *\n\t *\n\t * ## Can I disable SCE completely?\n\t *\n\t * Yes, you can. However, this is strongly discouraged. SCE gives you a lot of security benefits\n\t * for little coding overhead. It will be much harder to take an SCE disabled application and\n\t * either secure it on your own or enable SCE at a later stage. It might make sense to disable SCE\n\t * for cases where you have a lot of existing code that was written before SCE was introduced and\n\t * you're migrating them a module at a time.\n\t *\n\t * That said, here's how you can completely disable SCE:\n\t *\n\t * ```\n\t * angular.module('myAppWithSceDisabledmyApp', []).config(function($sceProvider) {\n\t * // Completely disable SCE. For demonstration purposes only!\n\t * // Do not use in new projects.\n\t * $sceProvider.enabled(false);\n\t * });\n\t * ```\n\t *\n\t */\n\t/* jshint maxlen: 100 */\n\t\n\tfunction $SceProvider() {\n\t var enabled = true;\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $sceProvider#enabled\n\t * @kind function\n\t *\n\t * @param {boolean=} value If provided, then enables/disables SCE.\n\t * @return {boolean} true if SCE is enabled, false otherwise.\n\t *\n\t * @description\n\t * Enables/disables SCE and returns the current value.\n\t */\n\t this.enabled = function(value) {\n\t if (arguments.length) {\n\t enabled = !!value;\n\t }\n\t return enabled;\n\t };\n\t\n\t\n\t /* Design notes on the default implementation for SCE.\n\t *\n\t * The API contract for the SCE delegate\n\t * -------------------------------------\n\t * The SCE delegate object must provide the following 3 methods:\n\t *\n\t * - trustAs(contextEnum, value)\n\t * This method is used to tell the SCE service that the provided value is OK to use in the\n\t * contexts specified by contextEnum. It must return an object that will be accepted by\n\t * getTrusted() for a compatible contextEnum and return this value.\n\t *\n\t * - valueOf(value)\n\t * For values that were not produced by trustAs(), return them as is. For values that were\n\t * produced by trustAs(), return the corresponding input value to trustAs. Basically, if\n\t * trustAs is wrapping the given values into some type, this operation unwraps it when given\n\t * such a value.\n\t *\n\t * - getTrusted(contextEnum, value)\n\t * This function should return the a value that is safe to use in the context specified by\n\t * contextEnum or throw and exception otherwise.\n\t *\n\t * NOTE: This contract deliberately does NOT state that values returned by trustAs() must be\n\t * opaque or wrapped in some holder object. That happens to be an implementation detail. For\n\t * instance, an implementation could maintain a registry of all trusted objects by context. In\n\t * such a case, trustAs() would return the same object that was passed in. getTrusted() would\n\t * return the same object passed in if it was found in the registry under a compatible context or\n\t * throw an exception otherwise. An implementation might only wrap values some of the time based\n\t * on some criteria. getTrusted() might return a value and not throw an exception for special\n\t * constants or objects even if not wrapped. All such implementations fulfill this contract.\n\t *\n\t *\n\t * A note on the inheritance model for SCE contexts\n\t * ------------------------------------------------\n\t * I've used inheritance and made RESOURCE_URL wrapped types a subtype of URL wrapped types. This\n\t * is purely an implementation details.\n\t *\n\t * The contract is simply this:\n\t *\n\t * getTrusted($sce.RESOURCE_URL, value) succeeding implies that getTrusted($sce.URL, value)\n\t * will also succeed.\n\t *\n\t * Inheritance happens to capture this in a natural way. In some future, we\n\t * may not use inheritance anymore. That is OK because no code outside of\n\t * sce.js and sceSpecs.js would need to be aware of this detail.\n\t */\n\t\n\t this.$get = ['$parse', '$sceDelegate', function(\n\t $parse, $sceDelegate) {\n\t // Prereq: Ensure that we're not running in IE<11 quirks mode. In that mode, IE < 11 allow\n\t // the \"expression(javascript expression)\" syntax which is insecure.\n\t if (enabled && msie < 8) {\n\t throw $sceMinErr('iequirks',\n\t 'Strict Contextual Escaping does not support Internet Explorer version < 11 in quirks ' +\n\t 'mode. You can fix this by adding the text to the top of your HTML ' +\n\t 'document. See http://docs.angularjs.org/api/ng.$sce for more information.');\n\t }\n\t\n\t var sce = shallowCopy(SCE_CONTEXTS);\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $sce#isEnabled\n\t * @kind function\n\t *\n\t * @return {Boolean} true if SCE is enabled, false otherwise. If you want to set the value, you\n\t * have to do it at module config time on {@link ng.$sceProvider $sceProvider}.\n\t *\n\t * @description\n\t * Returns a boolean indicating if SCE is enabled.\n\t */\n\t sce.isEnabled = function() {\n\t return enabled;\n\t };\n\t sce.trustAs = $sceDelegate.trustAs;\n\t sce.getTrusted = $sceDelegate.getTrusted;\n\t sce.valueOf = $sceDelegate.valueOf;\n\t\n\t if (!enabled) {\n\t sce.trustAs = sce.getTrusted = function(type, value) { return value; };\n\t sce.valueOf = identity;\n\t }\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $sce#parseAs\n\t *\n\t * @description\n\t * Converts Angular {@link guide/expression expression} into a function. This is like {@link\n\t * ng.$parse $parse} and is identical when the expression is a literal constant. Otherwise, it\n\t * wraps the expression in a call to {@link ng.$sce#getTrusted $sce.getTrusted(*type*,\n\t * *result*)}\n\t *\n\t * @param {string} type The kind of SCE context in which this result will be used.\n\t * @param {string} expression String expression to compile.\n\t * @returns {function(context, locals)} a function which represents the compiled expression:\n\t *\n\t * * `context` – `{object}` – an object against which any expressions embedded in the strings\n\t * are evaluated against (typically a scope object).\n\t * * `locals` – `{object=}` – local variables context object, useful for overriding values in\n\t * `context`.\n\t */\n\t sce.parseAs = function sceParseAs(type, expr) {\n\t var parsed = $parse(expr);\n\t if (parsed.literal && parsed.constant) {\n\t return parsed;\n\t } else {\n\t return $parse(expr, function(value) {\n\t return sce.getTrusted(type, value);\n\t });\n\t }\n\t };\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $sce#trustAs\n\t *\n\t * @description\n\t * Delegates to {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}. As such,\n\t * returns an object that is trusted by angular for use in specified strict contextual\n\t * escaping contexts (such as ng-bind-html, ng-include, any src attribute\n\t * interpolation, any dom event binding attribute interpolation such as for onclick, etc.)\n\t * that uses the provided value. See * {@link ng.$sce $sce} for enabling strict contextual\n\t * escaping.\n\t *\n\t * @param {string} type The kind of context in which this value is safe for use. e.g. url,\n\t * resourceUrl, html, js and css.\n\t * @param {*} value The value that that should be considered trusted/safe.\n\t * @returns {*} A value that can be used to stand in for the provided `value` in places\n\t * where Angular expects a $sce.trustAs() return value.\n\t */\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $sce#trustAsHtml\n\t *\n\t * @description\n\t * Shorthand method. `$sce.trustAsHtml(value)` →\n\t * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.HTML, value)`}\n\t *\n\t * @param {*} value The value to trustAs.\n\t * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedHtml\n\t * $sce.getTrustedHtml(value)} to obtain the original value. (privileged directives\n\t * only accept expressions that are either literal constants or are the\n\t * return value of {@link ng.$sce#trustAs $sce.trustAs}.)\n\t */\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $sce#trustAsUrl\n\t *\n\t * @description\n\t * Shorthand method. `$sce.trustAsUrl(value)` →\n\t * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.URL, value)`}\n\t *\n\t * @param {*} value The value to trustAs.\n\t * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedUrl\n\t * $sce.getTrustedUrl(value)} to obtain the original value. (privileged directives\n\t * only accept expressions that are either literal constants or are the\n\t * return value of {@link ng.$sce#trustAs $sce.trustAs}.)\n\t */\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $sce#trustAsResourceUrl\n\t *\n\t * @description\n\t * Shorthand method. `$sce.trustAsResourceUrl(value)` →\n\t * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.RESOURCE_URL, value)`}\n\t *\n\t * @param {*} value The value to trustAs.\n\t * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedResourceUrl\n\t * $sce.getTrustedResourceUrl(value)} to obtain the original value. (privileged directives\n\t * only accept expressions that are either literal constants or are the return\n\t * value of {@link ng.$sce#trustAs $sce.trustAs}.)\n\t */\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $sce#trustAsJs\n\t *\n\t * @description\n\t * Shorthand method. `$sce.trustAsJs(value)` →\n\t * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.JS, value)`}\n\t *\n\t * @param {*} value The value to trustAs.\n\t * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedJs\n\t * $sce.getTrustedJs(value)} to obtain the original value. (privileged directives\n\t * only accept expressions that are either literal constants or are the\n\t * return value of {@link ng.$sce#trustAs $sce.trustAs}.)\n\t */\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $sce#getTrusted\n\t *\n\t * @description\n\t * Delegates to {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted`}. As such,\n\t * takes the result of a {@link ng.$sce#trustAs `$sce.trustAs`}() call and returns the\n\t * originally supplied value if the queried context type is a supertype of the created type.\n\t * If this condition isn't satisfied, throws an exception.\n\t *\n\t * @param {string} type The kind of context in which this value is to be used.\n\t * @param {*} maybeTrusted The result of a prior {@link ng.$sce#trustAs `$sce.trustAs`}\n\t * call.\n\t * @returns {*} The value the was originally provided to\n\t * {@link ng.$sce#trustAs `$sce.trustAs`} if valid in this context.\n\t * Otherwise, throws an exception.\n\t */\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $sce#getTrustedHtml\n\t *\n\t * @description\n\t * Shorthand method. `$sce.getTrustedHtml(value)` →\n\t * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.HTML, value)`}\n\t *\n\t * @param {*} value The value to pass to `$sce.getTrusted`.\n\t * @returns {*} The return value of `$sce.getTrusted($sce.HTML, value)`\n\t */\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $sce#getTrustedCss\n\t *\n\t * @description\n\t * Shorthand method. `$sce.getTrustedCss(value)` →\n\t * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.CSS, value)`}\n\t *\n\t * @param {*} value The value to pass to `$sce.getTrusted`.\n\t * @returns {*} The return value of `$sce.getTrusted($sce.CSS, value)`\n\t */\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $sce#getTrustedUrl\n\t *\n\t * @description\n\t * Shorthand method. `$sce.getTrustedUrl(value)` →\n\t * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.URL, value)`}\n\t *\n\t * @param {*} value The value to pass to `$sce.getTrusted`.\n\t * @returns {*} The return value of `$sce.getTrusted($sce.URL, value)`\n\t */\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $sce#getTrustedResourceUrl\n\t *\n\t * @description\n\t * Shorthand method. `$sce.getTrustedResourceUrl(value)` →\n\t * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.RESOURCE_URL, value)`}\n\t *\n\t * @param {*} value The value to pass to `$sceDelegate.getTrusted`.\n\t * @returns {*} The return value of `$sce.getTrusted($sce.RESOURCE_URL, value)`\n\t */\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $sce#getTrustedJs\n\t *\n\t * @description\n\t * Shorthand method. `$sce.getTrustedJs(value)` →\n\t * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.JS, value)`}\n\t *\n\t * @param {*} value The value to pass to `$sce.getTrusted`.\n\t * @returns {*} The return value of `$sce.getTrusted($sce.JS, value)`\n\t */\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $sce#parseAsHtml\n\t *\n\t * @description\n\t * Shorthand method. `$sce.parseAsHtml(expression string)` →\n\t * {@link ng.$sce#parseAs `$sce.parseAs($sce.HTML, value)`}\n\t *\n\t * @param {string} expression String expression to compile.\n\t * @returns {function(context, locals)} a function which represents the compiled expression:\n\t *\n\t * * `context` – `{object}` – an object against which any expressions embedded in the strings\n\t * are evaluated against (typically a scope object).\n\t * * `locals` – `{object=}` – local variables context object, useful for overriding values in\n\t * `context`.\n\t */\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $sce#parseAsCss\n\t *\n\t * @description\n\t * Shorthand method. `$sce.parseAsCss(value)` →\n\t * {@link ng.$sce#parseAs `$sce.parseAs($sce.CSS, value)`}\n\t *\n\t * @param {string} expression String expression to compile.\n\t * @returns {function(context, locals)} a function which represents the compiled expression:\n\t *\n\t * * `context` – `{object}` – an object against which any expressions embedded in the strings\n\t * are evaluated against (typically a scope object).\n\t * * `locals` – `{object=}` – local variables context object, useful for overriding values in\n\t * `context`.\n\t */\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $sce#parseAsUrl\n\t *\n\t * @description\n\t * Shorthand method. `$sce.parseAsUrl(value)` →\n\t * {@link ng.$sce#parseAs `$sce.parseAs($sce.URL, value)`}\n\t *\n\t * @param {string} expression String expression to compile.\n\t * @returns {function(context, locals)} a function which represents the compiled expression:\n\t *\n\t * * `context` – `{object}` – an object against which any expressions embedded in the strings\n\t * are evaluated against (typically a scope object).\n\t * * `locals` – `{object=}` – local variables context object, useful for overriding values in\n\t * `context`.\n\t */\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $sce#parseAsResourceUrl\n\t *\n\t * @description\n\t * Shorthand method. `$sce.parseAsResourceUrl(value)` →\n\t * {@link ng.$sce#parseAs `$sce.parseAs($sce.RESOURCE_URL, value)`}\n\t *\n\t * @param {string} expression String expression to compile.\n\t * @returns {function(context, locals)} a function which represents the compiled expression:\n\t *\n\t * * `context` – `{object}` – an object against which any expressions embedded in the strings\n\t * are evaluated against (typically a scope object).\n\t * * `locals` – `{object=}` – local variables context object, useful for overriding values in\n\t * `context`.\n\t */\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $sce#parseAsJs\n\t *\n\t * @description\n\t * Shorthand method. `$sce.parseAsJs(value)` →\n\t * {@link ng.$sce#parseAs `$sce.parseAs($sce.JS, value)`}\n\t *\n\t * @param {string} expression String expression to compile.\n\t * @returns {function(context, locals)} a function which represents the compiled expression:\n\t *\n\t * * `context` – `{object}` – an object against which any expressions embedded in the strings\n\t * are evaluated against (typically a scope object).\n\t * * `locals` – `{object=}` – local variables context object, useful for overriding values in\n\t * `context`.\n\t */\n\t\n\t // Shorthand delegations.\n\t var parse = sce.parseAs,\n\t getTrusted = sce.getTrusted,\n\t trustAs = sce.trustAs;\n\t\n\t forEach(SCE_CONTEXTS, function(enumValue, name) {\n\t var lName = lowercase(name);\n\t sce[camelCase(\"parse_as_\" + lName)] = function(expr) {\n\t return parse(enumValue, expr);\n\t };\n\t sce[camelCase(\"get_trusted_\" + lName)] = function(value) {\n\t return getTrusted(enumValue, value);\n\t };\n\t sce[camelCase(\"trust_as_\" + lName)] = function(value) {\n\t return trustAs(enumValue, value);\n\t };\n\t });\n\t\n\t return sce;\n\t }];\n\t}\n\t\n\t/**\n\t * !!! This is an undocumented \"private\" service !!!\n\t *\n\t * @name $sniffer\n\t * @requires $window\n\t * @requires $document\n\t *\n\t * @property {boolean} history Does the browser support html5 history api ?\n\t * @property {boolean} transitions Does the browser support CSS transition events ?\n\t * @property {boolean} animations Does the browser support CSS animation events ?\n\t *\n\t * @description\n\t * This is very simple implementation of testing browser's features.\n\t */\n\tfunction $SnifferProvider() {\n\t this.$get = ['$window', '$document', function($window, $document) {\n\t var eventSupport = {},\n\t // Chrome Packaged Apps are not allowed to access `history.pushState`. They can be detected by\n\t // the presence of `chrome.app.runtime` (see https://developer.chrome.com/apps/api_index)\n\t isChromePackagedApp = $window.chrome && $window.chrome.app && $window.chrome.app.runtime,\n\t hasHistoryPushState = !isChromePackagedApp && $window.history && $window.history.pushState,\n\t android =\n\t toInt((/android (\\d+)/.exec(lowercase(($window.navigator || {}).userAgent)) || [])[1]),\n\t boxee = /Boxee/i.test(($window.navigator || {}).userAgent),\n\t document = $document[0] || {},\n\t vendorPrefix,\n\t vendorRegex = /^(Moz|webkit|ms)(?=[A-Z])/,\n\t bodyStyle = document.body && document.body.style,\n\t transitions = false,\n\t animations = false,\n\t match;\n\t\n\t if (bodyStyle) {\n\t for (var prop in bodyStyle) {\n\t if (match = vendorRegex.exec(prop)) {\n\t vendorPrefix = match[0];\n\t vendorPrefix = vendorPrefix[0].toUpperCase() + vendorPrefix.substr(1);\n\t break;\n\t }\n\t }\n\t\n\t if (!vendorPrefix) {\n\t vendorPrefix = ('WebkitOpacity' in bodyStyle) && 'webkit';\n\t }\n\t\n\t transitions = !!(('transition' in bodyStyle) || (vendorPrefix + 'Transition' in bodyStyle));\n\t animations = !!(('animation' in bodyStyle) || (vendorPrefix + 'Animation' in bodyStyle));\n\t\n\t if (android && (!transitions || !animations)) {\n\t transitions = isString(bodyStyle.webkitTransition);\n\t animations = isString(bodyStyle.webkitAnimation);\n\t }\n\t }\n\t\n\t\n\t return {\n\t // Android has history.pushState, but it does not update location correctly\n\t // so let's not use the history API at all.\n\t // http://code.google.com/p/android/issues/detail?id=17471\n\t // https://github.com/angular/angular.js/issues/904\n\t\n\t // older webkit browser (533.9) on Boxee box has exactly the same problem as Android has\n\t // so let's not use the history API also\n\t // We are purposefully using `!(android < 4)` to cover the case when `android` is undefined\n\t // jshint -W018\n\t history: !!(hasHistoryPushState && !(android < 4) && !boxee),\n\t // jshint +W018\n\t hasEvent: function(event) {\n\t // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n\t // it. In particular the event is not fired when backspace or delete key are pressed or\n\t // when cut operation is performed.\n\t // IE10+ implements 'input' event but it erroneously fires under various situations,\n\t // e.g. when placeholder changes, or a form is focused.\n\t if (event === 'input' && msie <= 11) return false;\n\t\n\t if (isUndefined(eventSupport[event])) {\n\t var divElm = document.createElement('div');\n\t eventSupport[event] = 'on' + event in divElm;\n\t }\n\t\n\t return eventSupport[event];\n\t },\n\t csp: csp(),\n\t vendorPrefix: vendorPrefix,\n\t transitions: transitions,\n\t animations: animations,\n\t android: android\n\t };\n\t }];\n\t}\n\t\n\tvar $templateRequestMinErr = minErr('$compile');\n\t\n\t/**\n\t * @ngdoc provider\n\t * @name $templateRequestProvider\n\t * @description\n\t * Used to configure the options passed to the {@link $http} service when making a template request.\n\t *\n\t * For example, it can be used for specifying the \"Accept\" header that is sent to the server, when\n\t * requesting a template.\n\t */\n\tfunction $TemplateRequestProvider() {\n\t\n\t var httpOptions;\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $templateRequestProvider#httpOptions\n\t * @description\n\t * The options to be passed to the {@link $http} service when making the request.\n\t * You can use this to override options such as the \"Accept\" header for template requests.\n\t *\n\t * The {@link $templateRequest} will set the `cache` and the `transformResponse` properties of the\n\t * options if not overridden here.\n\t *\n\t * @param {string=} value new value for the {@link $http} options.\n\t * @returns {string|self} Returns the {@link $http} options when used as getter and self if used as setter.\n\t */\n\t this.httpOptions = function(val) {\n\t if (val) {\n\t httpOptions = val;\n\t return this;\n\t }\n\t return httpOptions;\n\t };\n\t\n\t /**\n\t * @ngdoc service\n\t * @name $templateRequest\n\t *\n\t * @description\n\t * The `$templateRequest` service runs security checks then downloads the provided template using\n\t * `$http` and, upon success, stores the contents inside of `$templateCache`. If the HTTP request\n\t * fails or the response data of the HTTP request is empty, a `$compile` error will be thrown (the\n\t * exception can be thwarted by setting the 2nd parameter of the function to true). Note that the\n\t * contents of `$templateCache` are trusted, so the call to `$sce.getTrustedUrl(tpl)` is omitted\n\t * when `tpl` is of type string and `$templateCache` has the matching entry.\n\t *\n\t * If you want to pass custom options to the `$http` service, such as setting the Accept header you\n\t * can configure this via {@link $templateRequestProvider#httpOptions}.\n\t *\n\t * @param {string|TrustedResourceUrl} tpl The HTTP request template URL\n\t * @param {boolean=} ignoreRequestError Whether or not to ignore the exception when the request fails or the template is empty\n\t *\n\t * @return {Promise} a promise for the HTTP response data of the given URL.\n\t *\n\t * @property {number} totalPendingRequests total amount of pending template requests being downloaded.\n\t */\n\t this.$get = ['$templateCache', '$http', '$q', '$sce', function($templateCache, $http, $q, $sce) {\n\t\n\t function handleRequestFn(tpl, ignoreRequestError) {\n\t handleRequestFn.totalPendingRequests++;\n\t\n\t // We consider the template cache holds only trusted templates, so\n\t // there's no need to go through whitelisting again for keys that already\n\t // are included in there. This also makes Angular accept any script\n\t // directive, no matter its name. However, we still need to unwrap trusted\n\t // types.\n\t if (!isString(tpl) || isUndefined($templateCache.get(tpl))) {\n\t tpl = $sce.getTrustedResourceUrl(tpl);\n\t }\n\t\n\t var transformResponse = $http.defaults && $http.defaults.transformResponse;\n\t\n\t if (isArray(transformResponse)) {\n\t transformResponse = transformResponse.filter(function(transformer) {\n\t return transformer !== defaultHttpResponseTransform;\n\t });\n\t } else if (transformResponse === defaultHttpResponseTransform) {\n\t transformResponse = null;\n\t }\n\t\n\t return $http.get(tpl, extend({\n\t cache: $templateCache,\n\t transformResponse: transformResponse\n\t }, httpOptions))\n\t ['finally'](function() {\n\t handleRequestFn.totalPendingRequests--;\n\t })\n\t .then(function(response) {\n\t $templateCache.put(tpl, response.data);\n\t return response.data;\n\t }, handleError);\n\t\n\t function handleError(resp) {\n\t if (!ignoreRequestError) {\n\t throw $templateRequestMinErr('tpload', 'Failed to load template: {0} (HTTP status: {1} {2})',\n\t tpl, resp.status, resp.statusText);\n\t }\n\t return $q.reject(resp);\n\t }\n\t }\n\t\n\t handleRequestFn.totalPendingRequests = 0;\n\t\n\t return handleRequestFn;\n\t }];\n\t}\n\t\n\tfunction $$TestabilityProvider() {\n\t this.$get = ['$rootScope', '$browser', '$location',\n\t function($rootScope, $browser, $location) {\n\t\n\t /**\n\t * @name $testability\n\t *\n\t * @description\n\t * The private $$testability service provides a collection of methods for use when debugging\n\t * or by automated test and debugging tools.\n\t */\n\t var testability = {};\n\t\n\t /**\n\t * @name $$testability#findBindings\n\t *\n\t * @description\n\t * Returns an array of elements that are bound (via ng-bind or {{}})\n\t * to expressions matching the input.\n\t *\n\t * @param {Element} element The element root to search from.\n\t * @param {string} expression The binding expression to match.\n\t * @param {boolean} opt_exactMatch If true, only returns exact matches\n\t * for the expression. Filters and whitespace are ignored.\n\t */\n\t testability.findBindings = function(element, expression, opt_exactMatch) {\n\t var bindings = element.getElementsByClassName('ng-binding');\n\t var matches = [];\n\t forEach(bindings, function(binding) {\n\t var dataBinding = angular.element(binding).data('$binding');\n\t if (dataBinding) {\n\t forEach(dataBinding, function(bindingName) {\n\t if (opt_exactMatch) {\n\t var matcher = new RegExp('(^|\\\\s)' + escapeForRegexp(expression) + '(\\\\s|\\\\||$)');\n\t if (matcher.test(bindingName)) {\n\t matches.push(binding);\n\t }\n\t } else {\n\t if (bindingName.indexOf(expression) != -1) {\n\t matches.push(binding);\n\t }\n\t }\n\t });\n\t }\n\t });\n\t return matches;\n\t };\n\t\n\t /**\n\t * @name $$testability#findModels\n\t *\n\t * @description\n\t * Returns an array of elements that are two-way found via ng-model to\n\t * expressions matching the input.\n\t *\n\t * @param {Element} element The element root to search from.\n\t * @param {string} expression The model expression to match.\n\t * @param {boolean} opt_exactMatch If true, only returns exact matches\n\t * for the expression.\n\t */\n\t testability.findModels = function(element, expression, opt_exactMatch) {\n\t var prefixes = ['ng-', 'data-ng-', 'ng\\\\:'];\n\t for (var p = 0; p < prefixes.length; ++p) {\n\t var attributeEquals = opt_exactMatch ? '=' : '*=';\n\t var selector = '[' + prefixes[p] + 'model' + attributeEquals + '\"' + expression + '\"]';\n\t var elements = element.querySelectorAll(selector);\n\t if (elements.length) {\n\t return elements;\n\t }\n\t }\n\t };\n\t\n\t /**\n\t * @name $$testability#getLocation\n\t *\n\t * @description\n\t * Shortcut for getting the location in a browser agnostic way. Returns\n\t * the path, search, and hash. (e.g. /path?a=b#hash)\n\t */\n\t testability.getLocation = function() {\n\t return $location.url();\n\t };\n\t\n\t /**\n\t * @name $$testability#setLocation\n\t *\n\t * @description\n\t * Shortcut for navigating to a location without doing a full page reload.\n\t *\n\t * @param {string} url The location url (path, search and hash,\n\t * e.g. /path?a=b#hash) to go to.\n\t */\n\t testability.setLocation = function(url) {\n\t if (url !== $location.url()) {\n\t $location.url(url);\n\t $rootScope.$digest();\n\t }\n\t };\n\t\n\t /**\n\t * @name $$testability#whenStable\n\t *\n\t * @description\n\t * Calls the callback when $timeout and $http requests are completed.\n\t *\n\t * @param {function} callback\n\t */\n\t testability.whenStable = function(callback) {\n\t $browser.notifyWhenNoOutstandingRequests(callback);\n\t };\n\t\n\t return testability;\n\t }];\n\t}\n\t\n\tfunction $TimeoutProvider() {\n\t this.$get = ['$rootScope', '$browser', '$q', '$$q', '$exceptionHandler',\n\t function($rootScope, $browser, $q, $$q, $exceptionHandler) {\n\t\n\t var deferreds = {};\n\t\n\t\n\t /**\n\t * @ngdoc service\n\t * @name $timeout\n\t *\n\t * @description\n\t * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n\t * block and delegates any exceptions to\n\t * {@link ng.$exceptionHandler $exceptionHandler} service.\n\t *\n\t * The return value of calling `$timeout` is a promise, which will be resolved when\n\t * the delay has passed and the timeout function, if provided, is executed.\n\t *\n\t * To cancel a timeout request, call `$timeout.cancel(promise)`.\n\t *\n\t * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n\t * synchronously flush the queue of deferred functions.\n\t *\n\t * If you only want a promise that will be resolved after some specified delay\n\t * then you can call `$timeout` without the `fn` function.\n\t *\n\t * @param {function()=} fn A function, whose execution should be delayed.\n\t * @param {number=} [delay=0] Delay in milliseconds.\n\t * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise\n\t * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n\t * @param {...*=} Pass additional parameters to the executed function.\n\t * @returns {Promise} Promise that will be resolved when the timeout is reached. The promise\n\t * will be resolved with the return value of the `fn` function.\n\t *\n\t */\n\t function timeout(fn, delay, invokeApply) {\n\t if (!isFunction(fn)) {\n\t invokeApply = delay;\n\t delay = fn;\n\t fn = noop;\n\t }\n\t\n\t var args = sliceArgs(arguments, 3),\n\t skipApply = (isDefined(invokeApply) && !invokeApply),\n\t deferred = (skipApply ? $$q : $q).defer(),\n\t promise = deferred.promise,\n\t timeoutId;\n\t\n\t timeoutId = $browser.defer(function() {\n\t try {\n\t deferred.resolve(fn.apply(null, args));\n\t } catch (e) {\n\t deferred.reject(e);\n\t $exceptionHandler(e);\n\t }\n\t finally {\n\t delete deferreds[promise.$$timeoutId];\n\t }\n\t\n\t if (!skipApply) $rootScope.$apply();\n\t }, delay);\n\t\n\t promise.$$timeoutId = timeoutId;\n\t deferreds[timeoutId] = deferred;\n\t\n\t return promise;\n\t }\n\t\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $timeout#cancel\n\t *\n\t * @description\n\t * Cancels a task associated with the `promise`. As a result of this, the promise will be\n\t * resolved with a rejection.\n\t *\n\t * @param {Promise=} promise Promise returned by the `$timeout` function.\n\t * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n\t * canceled.\n\t */\n\t timeout.cancel = function(promise) {\n\t if (promise && promise.$$timeoutId in deferreds) {\n\t deferreds[promise.$$timeoutId].reject('canceled');\n\t delete deferreds[promise.$$timeoutId];\n\t return $browser.defer.cancel(promise.$$timeoutId);\n\t }\n\t return false;\n\t };\n\t\n\t return timeout;\n\t }];\n\t}\n\t\n\t// NOTE: The usage of window and document instead of $window and $document here is\n\t// deliberate. This service depends on the specific behavior of anchor nodes created by the\n\t// browser (resolving and parsing URLs) that is unlikely to be provided by mock objects and\n\t// cause us to break tests. In addition, when the browser resolves a URL for XHR, it\n\t// doesn't know about mocked locations and resolves URLs to the real document - which is\n\t// exactly the behavior needed here. There is little value is mocking these out for this\n\t// service.\n\tvar urlParsingNode = window.document.createElement(\"a\");\n\tvar originUrl = urlResolve(window.location.href);\n\t\n\t\n\t/**\n\t *\n\t * Implementation Notes for non-IE browsers\n\t * ----------------------------------------\n\t * Assigning a URL to the href property of an anchor DOM node, even one attached to the DOM,\n\t * results both in the normalizing and parsing of the URL. Normalizing means that a relative\n\t * URL will be resolved into an absolute URL in the context of the application document.\n\t * Parsing means that the anchor node's host, hostname, protocol, port, pathname and related\n\t * properties are all populated to reflect the normalized URL. This approach has wide\n\t * compatibility - Safari 1+, Mozilla 1+, Opera 7+,e etc. See\n\t * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html\n\t *\n\t * Implementation Notes for IE\n\t * ---------------------------\n\t * IE <= 10 normalizes the URL when assigned to the anchor node similar to the other\n\t * browsers. However, the parsed components will not be set if the URL assigned did not specify\n\t * them. (e.g. if you assign a.href = \"foo\", then a.protocol, a.host, etc. will be empty.) We\n\t * work around that by performing the parsing in a 2nd step by taking a previously normalized\n\t * URL (e.g. by assigning to a.href) and assigning it a.href again. This correctly populates the\n\t * properties such as protocol, hostname, port, etc.\n\t *\n\t * References:\n\t * http://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement\n\t * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html\n\t * http://url.spec.whatwg.org/#urlutils\n\t * https://github.com/angular/angular.js/pull/2902\n\t * http://james.padolsey.com/javascript/parsing-urls-with-the-dom/\n\t *\n\t * @kind function\n\t * @param {string} url The URL to be parsed.\n\t * @description Normalizes and parses a URL.\n\t * @returns {object} Returns the normalized URL as a dictionary.\n\t *\n\t * | member name | Description |\n\t * |---------------|----------------|\n\t * | href | A normalized version of the provided URL if it was not an absolute URL |\n\t * | protocol | The protocol including the trailing colon |\n\t * | host | The host and port (if the port is non-default) of the normalizedUrl |\n\t * | search | The search params, minus the question mark |\n\t * | hash | The hash string, minus the hash symbol\n\t * | hostname | The hostname\n\t * | port | The port, without \":\"\n\t * | pathname | The pathname, beginning with \"/\"\n\t *\n\t */\n\tfunction urlResolve(url) {\n\t var href = url;\n\t\n\t if (msie) {\n\t // Normalize before parse. Refer Implementation Notes on why this is\n\t // done in two steps on IE.\n\t urlParsingNode.setAttribute(\"href\", href);\n\t href = urlParsingNode.href;\n\t }\n\t\n\t urlParsingNode.setAttribute('href', href);\n\t\n\t // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils\n\t return {\n\t href: urlParsingNode.href,\n\t protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '',\n\t host: urlParsingNode.host,\n\t search: urlParsingNode.search ? urlParsingNode.search.replace(/^\\?/, '') : '',\n\t hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '',\n\t hostname: urlParsingNode.hostname,\n\t port: urlParsingNode.port,\n\t pathname: (urlParsingNode.pathname.charAt(0) === '/')\n\t ? urlParsingNode.pathname\n\t : '/' + urlParsingNode.pathname\n\t };\n\t}\n\t\n\t/**\n\t * Parse a request URL and determine whether this is a same-origin request as the application document.\n\t *\n\t * @param {string|object} requestUrl The url of the request as a string that will be resolved\n\t * or a parsed URL object.\n\t * @returns {boolean} Whether the request is for the same origin as the application document.\n\t */\n\tfunction urlIsSameOrigin(requestUrl) {\n\t var parsed = (isString(requestUrl)) ? urlResolve(requestUrl) : requestUrl;\n\t return (parsed.protocol === originUrl.protocol &&\n\t parsed.host === originUrl.host);\n\t}\n\t\n\t/**\n\t * @ngdoc service\n\t * @name $window\n\t *\n\t * @description\n\t * A reference to the browser's `window` object. While `window`\n\t * is globally available in JavaScript, it causes testability problems, because\n\t * it is a global variable. In angular we always refer to it through the\n\t * `$window` service, so it may be overridden, removed or mocked for testing.\n\t *\n\t * Expressions, like the one defined for the `ngClick` directive in the example\n\t * below, are evaluated with respect to the current scope. Therefore, there is\n\t * no risk of inadvertently coding in a dependency on a global value in such an\n\t * expression.\n\t *\n\t * @example\n\t \n\t \n\t \n\t
\n\t \n\t \n\t
\n\t
\n\t \n\t it('should display the greeting in the input box', function() {\n\t element(by.model('greeting')).sendKeys('Hello, E2E Tests');\n\t // If we click the button it will block the test runner\n\t // element(':button').click();\n\t });\n\t \n\t
\n\t */\n\tfunction $WindowProvider() {\n\t this.$get = valueFn(window);\n\t}\n\t\n\t/**\n\t * @name $$cookieReader\n\t * @requires $document\n\t *\n\t * @description\n\t * This is a private service for reading cookies used by $http and ngCookies\n\t *\n\t * @return {Object} a key/value map of the current cookies\n\t */\n\tfunction $$CookieReader($document) {\n\t var rawDocument = $document[0] || {};\n\t var lastCookies = {};\n\t var lastCookieString = '';\n\t\n\t function safeDecodeURIComponent(str) {\n\t try {\n\t return decodeURIComponent(str);\n\t } catch (e) {\n\t return str;\n\t }\n\t }\n\t\n\t return function() {\n\t var cookieArray, cookie, i, index, name;\n\t var currentCookieString = rawDocument.cookie || '';\n\t\n\t if (currentCookieString !== lastCookieString) {\n\t lastCookieString = currentCookieString;\n\t cookieArray = lastCookieString.split('; ');\n\t lastCookies = {};\n\t\n\t for (i = 0; i < cookieArray.length; i++) {\n\t cookie = cookieArray[i];\n\t index = cookie.indexOf('=');\n\t if (index > 0) { //ignore nameless cookies\n\t name = safeDecodeURIComponent(cookie.substring(0, index));\n\t // the first value that is seen for a cookie is the most\n\t // specific one. values for the same cookie name that\n\t // follow are for less specific paths.\n\t if (isUndefined(lastCookies[name])) {\n\t lastCookies[name] = safeDecodeURIComponent(cookie.substring(index + 1));\n\t }\n\t }\n\t }\n\t }\n\t return lastCookies;\n\t };\n\t}\n\t\n\t$$CookieReader.$inject = ['$document'];\n\t\n\tfunction $$CookieReaderProvider() {\n\t this.$get = $$CookieReader;\n\t}\n\t\n\t/* global currencyFilter: true,\n\t dateFilter: true,\n\t filterFilter: true,\n\t jsonFilter: true,\n\t limitToFilter: true,\n\t lowercaseFilter: true,\n\t numberFilter: true,\n\t orderByFilter: true,\n\t uppercaseFilter: true,\n\t */\n\t\n\t/**\n\t * @ngdoc provider\n\t * @name $filterProvider\n\t * @description\n\t *\n\t * Filters are just functions which transform input to an output. However filters need to be\n\t * Dependency Injected. To achieve this a filter definition consists of a factory function which is\n\t * annotated with dependencies and is responsible for creating a filter function.\n\t *\n\t *
\n\t * **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`.\n\t * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace\n\t * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores\n\t * (`myapp_subsection_filterx`).\n\t *
\n\t *\n\t * ```js\n\t * // Filter registration\n\t * function MyModule($provide, $filterProvider) {\n\t * // create a service to demonstrate injection (not always needed)\n\t * $provide.value('greet', function(name){\n\t * return 'Hello ' + name + '!';\n\t * });\n\t *\n\t * // register a filter factory which uses the\n\t * // greet service to demonstrate DI.\n\t * $filterProvider.register('greet', function(greet){\n\t * // return the filter function which uses the greet service\n\t * // to generate salutation\n\t * return function(text) {\n\t * // filters need to be forgiving so check input validity\n\t * return text && greet(text) || text;\n\t * };\n\t * });\n\t * }\n\t * ```\n\t *\n\t * The filter function is registered with the `$injector` under the filter name suffix with\n\t * `Filter`.\n\t *\n\t * ```js\n\t * it('should be the same instance', inject(\n\t * function($filterProvider) {\n\t * $filterProvider.register('reverse', function(){\n\t * return ...;\n\t * });\n\t * },\n\t * function($filter, reverseFilter) {\n\t * expect($filter('reverse')).toBe(reverseFilter);\n\t * });\n\t * ```\n\t *\n\t *\n\t * For more information about how angular filters work, and how to create your own filters, see\n\t * {@link guide/filter Filters} in the Angular Developer Guide.\n\t */\n\t\n\t/**\n\t * @ngdoc service\n\t * @name $filter\n\t * @kind function\n\t * @description\n\t * Filters are used for formatting data displayed to the user.\n\t *\n\t * The general syntax in templates is as follows:\n\t *\n\t * {{ expression [| filter_name[:parameter_value] ... ] }}\n\t *\n\t * @param {String} name Name of the filter function to retrieve\n\t * @return {Function} the filter function\n\t * @example\n\t \n\t \n\t
\n\t

{{ originalText }}

\n\t

{{ filteredText }}

\n\t
\n\t
\n\t\n\t \n\t angular.module('filterExample', [])\n\t .controller('MainCtrl', function($scope, $filter) {\n\t $scope.originalText = 'hello';\n\t $scope.filteredText = $filter('uppercase')($scope.originalText);\n\t });\n\t \n\t
\n\t */\n\t$FilterProvider.$inject = ['$provide'];\n\tfunction $FilterProvider($provide) {\n\t var suffix = 'Filter';\n\t\n\t /**\n\t * @ngdoc method\n\t * @name $filterProvider#register\n\t * @param {string|Object} name Name of the filter function, or an object map of filters where\n\t * the keys are the filter names and the values are the filter factories.\n\t *\n\t *
\n\t * **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`.\n\t * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace\n\t * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores\n\t * (`myapp_subsection_filterx`).\n\t *
\n\t * @param {Function} factory If the first argument was a string, a factory function for the filter to be registered.\n\t * @returns {Object} Registered filter instance, or if a map of filters was provided then a map\n\t * of the registered filter instances.\n\t */\n\t function register(name, factory) {\n\t if (isObject(name)) {\n\t var filters = {};\n\t forEach(name, function(filter, key) {\n\t filters[key] = register(key, filter);\n\t });\n\t return filters;\n\t } else {\n\t return $provide.factory(name + suffix, factory);\n\t }\n\t }\n\t this.register = register;\n\t\n\t this.$get = ['$injector', function($injector) {\n\t return function(name) {\n\t return $injector.get(name + suffix);\n\t };\n\t }];\n\t\n\t ////////////////////////////////////////\n\t\n\t /* global\n\t currencyFilter: false,\n\t dateFilter: false,\n\t filterFilter: false,\n\t jsonFilter: false,\n\t limitToFilter: false,\n\t lowercaseFilter: false,\n\t numberFilter: false,\n\t orderByFilter: false,\n\t uppercaseFilter: false,\n\t */\n\t\n\t register('currency', currencyFilter);\n\t register('date', dateFilter);\n\t register('filter', filterFilter);\n\t register('json', jsonFilter);\n\t register('limitTo', limitToFilter);\n\t register('lowercase', lowercaseFilter);\n\t register('number', numberFilter);\n\t register('orderBy', orderByFilter);\n\t register('uppercase', uppercaseFilter);\n\t}\n\t\n\t/**\n\t * @ngdoc filter\n\t * @name filter\n\t * @kind function\n\t *\n\t * @description\n\t * Selects a subset of items from `array` and returns it as a new array.\n\t *\n\t * @param {Array} array The source array.\n\t * @param {string|Object|function()} expression The predicate to be used for selecting items from\n\t * `array`.\n\t *\n\t * Can be one of:\n\t *\n\t * - `string`: The string is used for matching against the contents of the `array`. All strings or\n\t * objects with string properties in `array` that match this string will be returned. This also\n\t * applies to nested object properties.\n\t * The predicate can be negated by prefixing the string with `!`.\n\t *\n\t * - `Object`: A pattern object can be used to filter specific properties on objects contained\n\t * by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n\t * which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n\t * property name (`$` by default) can be used (e.g. as in `{$: \"text\"}`) to accept a match\n\t * against any property of the object or its nested object properties. That's equivalent to the\n\t * simple substring match with a `string` as described above. The special property name can be\n\t * overwritten, using the `anyPropertyKey` parameter.\n\t * The predicate can be negated by prefixing the string with `!`.\n\t * For example `{name: \"!M\"}` predicate will return an array of items which have property `name`\n\t * not containing \"M\".\n\t *\n\t * Note that a named property will match properties on the same level only, while the special\n\t * `$` property will match properties on the same level or deeper. E.g. an array item like\n\t * `{name: {first: 'John', last: 'Doe'}}` will **not** be matched by `{name: 'John'}`, but\n\t * **will** be matched by `{$: 'John'}`.\n\t *\n\t * - `function(value, index, array)`: A predicate function can be used to write arbitrary filters.\n\t * The function is called for each element of the array, with the element, its index, and\n\t * the entire array itself as arguments.\n\t *\n\t * The final result is an array of those elements that the predicate returned true for.\n\t *\n\t * @param {function(actual, expected)|true|undefined} comparator Comparator which is used in\n\t * determining if the expected value (from the filter expression) and actual value (from\n\t * the object in the array) should be considered a match.\n\t *\n\t * Can be one of:\n\t *\n\t * - `function(actual, expected)`:\n\t * The function will be given the object value and the predicate value to compare and\n\t * should return true if both values should be considered equal.\n\t *\n\t * - `true`: A shorthand for `function(actual, expected) { return angular.equals(actual, expected)}`.\n\t * This is essentially strict comparison of expected and actual.\n\t *\n\t * - `false|undefined`: A short hand for a function which will look for a substring match in case\n\t * insensitive way.\n\t *\n\t * Primitive values are converted to strings. Objects are not compared against primitives,\n\t * unless they have a custom `toString` method (e.g. `Date` objects).\n\t *\n\t * @param {string=} anyPropertyKey The special property name that matches against any property.\n\t * By default `$`.\n\t *\n\t * @example\n\t \n\t \n\t
\n\t\n\t \n\t \n\t \n\t \n\t \n\t \n\t \n\t
NamePhone
{{friend.name}}{{friend.phone}}
\n\t
\n\t
\n\t
\n\t
\n\t
\n\t \n\t \n\t \n\t \n\t \n\t \n\t
NamePhone
{{friendObj.name}}{{friendObj.phone}}
\n\t
\n\t \n\t var expectFriendNames = function(expectedNames, key) {\n\t element.all(by.repeater(key + ' in friends').column(key + '.name')).then(function(arr) {\n\t arr.forEach(function(wd, i) {\n\t expect(wd.getText()).toMatch(expectedNames[i]);\n\t });\n\t });\n\t };\n\t\n\t it('should search across all fields when filtering with a string', function() {\n\t var searchText = element(by.model('searchText'));\n\t searchText.clear();\n\t searchText.sendKeys('m');\n\t expectFriendNames(['Mary', 'Mike', 'Adam'], 'friend');\n\t\n\t searchText.clear();\n\t searchText.sendKeys('76');\n\t expectFriendNames(['John', 'Julie'], 'friend');\n\t });\n\t\n\t it('should search in specific fields when filtering with a predicate object', function() {\n\t var searchAny = element(by.model('search.$'));\n\t searchAny.clear();\n\t searchAny.sendKeys('i');\n\t expectFriendNames(['Mary', 'Mike', 'Julie', 'Juliette'], 'friendObj');\n\t });\n\t it('should use a equal comparison when comparator is true', function() {\n\t var searchName = element(by.model('search.name'));\n\t var strict = element(by.model('strict'));\n\t searchName.clear();\n\t searchName.sendKeys('Julie');\n\t strict.click();\n\t expectFriendNames(['Julie'], 'friendObj');\n\t });\n\t \n\t
\n\t */\n\t\n\tfunction filterFilter() {\n\t return function(array, expression, comparator, anyPropertyKey) {\n\t if (!isArrayLike(array)) {\n\t if (array == null) {\n\t return array;\n\t } else {\n\t throw minErr('filter')('notarray', 'Expected array but received: {0}', array);\n\t }\n\t }\n\t\n\t anyPropertyKey = anyPropertyKey || '$';\n\t var expressionType = getTypeForFilter(expression);\n\t var predicateFn;\n\t var matchAgainstAnyProp;\n\t\n\t switch (expressionType) {\n\t case 'function':\n\t predicateFn = expression;\n\t break;\n\t case 'boolean':\n\t case 'null':\n\t case 'number':\n\t case 'string':\n\t matchAgainstAnyProp = true;\n\t //jshint -W086\n\t case 'object':\n\t //jshint +W086\n\t predicateFn = createPredicateFn(expression, comparator, anyPropertyKey, matchAgainstAnyProp);\n\t break;\n\t default:\n\t return array;\n\t }\n\t\n\t return Array.prototype.filter.call(array, predicateFn);\n\t };\n\t}\n\t\n\t// Helper functions for `filterFilter`\n\tfunction createPredicateFn(expression, comparator, anyPropertyKey, matchAgainstAnyProp) {\n\t var shouldMatchPrimitives = isObject(expression) && (anyPropertyKey in expression);\n\t var predicateFn;\n\t\n\t if (comparator === true) {\n\t comparator = equals;\n\t } else if (!isFunction(comparator)) {\n\t comparator = function(actual, expected) {\n\t if (isUndefined(actual)) {\n\t // No substring matching against `undefined`\n\t return false;\n\t }\n\t if ((actual === null) || (expected === null)) {\n\t // No substring matching against `null`; only match against `null`\n\t return actual === expected;\n\t }\n\t if (isObject(expected) || (isObject(actual) && !hasCustomToString(actual))) {\n\t // Should not compare primitives against objects, unless they have custom `toString` method\n\t return false;\n\t }\n\t\n\t actual = lowercase('' + actual);\n\t expected = lowercase('' + expected);\n\t return actual.indexOf(expected) !== -1;\n\t };\n\t }\n\t\n\t predicateFn = function(item) {\n\t if (shouldMatchPrimitives && !isObject(item)) {\n\t return deepCompare(item, expression[anyPropertyKey], comparator, anyPropertyKey, false);\n\t }\n\t return deepCompare(item, expression, comparator, anyPropertyKey, matchAgainstAnyProp);\n\t };\n\t\n\t return predicateFn;\n\t}\n\t\n\tfunction deepCompare(actual, expected, comparator, anyPropertyKey, matchAgainstAnyProp, dontMatchWholeObject) {\n\t var actualType = getTypeForFilter(actual);\n\t var expectedType = getTypeForFilter(expected);\n\t\n\t if ((expectedType === 'string') && (expected.charAt(0) === '!')) {\n\t return !deepCompare(actual, expected.substring(1), comparator, anyPropertyKey, matchAgainstAnyProp);\n\t } else if (isArray(actual)) {\n\t // In case `actual` is an array, consider it a match\n\t // if ANY of it's items matches `expected`\n\t return actual.some(function(item) {\n\t return deepCompare(item, expected, comparator, anyPropertyKey, matchAgainstAnyProp);\n\t });\n\t }\n\t\n\t switch (actualType) {\n\t case 'object':\n\t var key;\n\t if (matchAgainstAnyProp) {\n\t for (key in actual) {\n\t if ((key.charAt(0) !== '$') && deepCompare(actual[key], expected, comparator, anyPropertyKey, true)) {\n\t return true;\n\t }\n\t }\n\t return dontMatchWholeObject ? false : deepCompare(actual, expected, comparator, anyPropertyKey, false);\n\t } else if (expectedType === 'object') {\n\t for (key in expected) {\n\t var expectedVal = expected[key];\n\t if (isFunction(expectedVal) || isUndefined(expectedVal)) {\n\t continue;\n\t }\n\t\n\t var matchAnyProperty = key === anyPropertyKey;\n\t var actualVal = matchAnyProperty ? actual : actual[key];\n\t if (!deepCompare(actualVal, expectedVal, comparator, anyPropertyKey, matchAnyProperty, matchAnyProperty)) {\n\t return false;\n\t }\n\t }\n\t return true;\n\t } else {\n\t return comparator(actual, expected);\n\t }\n\t break;\n\t case 'function':\n\t return false;\n\t default:\n\t return comparator(actual, expected);\n\t }\n\t}\n\t\n\t// Used for easily differentiating between `null` and actual `object`\n\tfunction getTypeForFilter(val) {\n\t return (val === null) ? 'null' : typeof val;\n\t}\n\t\n\tvar MAX_DIGITS = 22;\n\tvar DECIMAL_SEP = '.';\n\tvar ZERO_CHAR = '0';\n\t\n\t/**\n\t * @ngdoc filter\n\t * @name currency\n\t * @kind function\n\t *\n\t * @description\n\t * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n\t * symbol for current locale is used.\n\t *\n\t * @param {number} amount Input to filter.\n\t * @param {string=} symbol Currency symbol or identifier to be displayed.\n\t * @param {number=} fractionSize Number of decimal places to round the amount to, defaults to default max fraction size for current locale\n\t * @returns {string} Formatted number.\n\t *\n\t *\n\t * @example\n\t \n\t \n\t \n\t
\n\t
\n\t default currency symbol ($): {{amount | currency}}
\n\t custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n\t no fractions (0): {{amount | currency:\"USD$\":0}}\n\t
\n\t
\n\t \n\t it('should init with 1234.56', function() {\n\t expect(element(by.id('currency-default')).getText()).toBe('$1,234.56');\n\t expect(element(by.id('currency-custom')).getText()).toBe('USD$1,234.56');\n\t expect(element(by.id('currency-no-fractions')).getText()).toBe('USD$1,235');\n\t });\n\t it('should update', function() {\n\t if (browser.params.browser == 'safari') {\n\t // Safari does not understand the minus key. See\n\t // https://github.com/angular/protractor/issues/481\n\t return;\n\t }\n\t element(by.model('amount')).clear();\n\t element(by.model('amount')).sendKeys('-1234');\n\t expect(element(by.id('currency-default')).getText()).toBe('-$1,234.00');\n\t expect(element(by.id('currency-custom')).getText()).toBe('-USD$1,234.00');\n\t expect(element(by.id('currency-no-fractions')).getText()).toBe('-USD$1,234');\n\t });\n\t \n\t
\n\t */\n\tcurrencyFilter.$inject = ['$locale'];\n\tfunction currencyFilter($locale) {\n\t var formats = $locale.NUMBER_FORMATS;\n\t return function(amount, currencySymbol, fractionSize) {\n\t if (isUndefined(currencySymbol)) {\n\t currencySymbol = formats.CURRENCY_SYM;\n\t }\n\t\n\t if (isUndefined(fractionSize)) {\n\t fractionSize = formats.PATTERNS[1].maxFrac;\n\t }\n\t\n\t // if null or undefined pass it through\n\t return (amount == null)\n\t ? amount\n\t : formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, fractionSize).\n\t replace(/\\u00A4/g, currencySymbol);\n\t };\n\t}\n\t\n\t/**\n\t * @ngdoc filter\n\t * @name number\n\t * @kind function\n\t *\n\t * @description\n\t * Formats a number as text.\n\t *\n\t * If the input is null or undefined, it will just be returned.\n\t * If the input is infinite (Infinity or -Infinity), the Infinity symbol '∞' or '-∞' is returned, respectively.\n\t * If the input is not a number an empty string is returned.\n\t *\n\t *\n\t * @param {number|string} number Number to format.\n\t * @param {(number|string)=} fractionSize Number of decimal places to round the number to.\n\t * If this is not provided then the fraction size is computed from the current locale's number\n\t * formatting pattern. In the case of the default locale, it will be 3.\n\t * @returns {string} Number rounded to `fractionSize` appropriately formatted based on the current\n\t * locale (e.g., in the en_US locale it will have \".\" as the decimal separator and\n\t * include \",\" group separators after each third digit).\n\t *\n\t * @example\n\t \n\t \n\t \n\t
\n\t
\n\t Default formatting: {{val | number}}
\n\t No fractions: {{val | number:0}}
\n\t Negative number: {{-val | number:4}}\n\t
\n\t
\n\t \n\t it('should format numbers', function() {\n\t expect(element(by.id('number-default')).getText()).toBe('1,234.568');\n\t expect(element(by.binding('val | number:0')).getText()).toBe('1,235');\n\t expect(element(by.binding('-val | number:4')).getText()).toBe('-1,234.5679');\n\t });\n\t\n\t it('should update', function() {\n\t element(by.model('val')).clear();\n\t element(by.model('val')).sendKeys('3374.333');\n\t expect(element(by.id('number-default')).getText()).toBe('3,374.333');\n\t expect(element(by.binding('val | number:0')).getText()).toBe('3,374');\n\t expect(element(by.binding('-val | number:4')).getText()).toBe('-3,374.3330');\n\t });\n\t \n\t
\n\t */\n\tnumberFilter.$inject = ['$locale'];\n\tfunction numberFilter($locale) {\n\t var formats = $locale.NUMBER_FORMATS;\n\t return function(number, fractionSize) {\n\t\n\t // if null or undefined pass it through\n\t return (number == null)\n\t ? number\n\t : formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n\t fractionSize);\n\t };\n\t}\n\t\n\t/**\n\t * Parse a number (as a string) into three components that can be used\n\t * for formatting the number.\n\t *\n\t * (Significant bits of this parse algorithm came from https://github.com/MikeMcl/big.js/)\n\t *\n\t * @param {string} numStr The number to parse\n\t * @return {object} An object describing this number, containing the following keys:\n\t * - d : an array of digits containing leading zeros as necessary\n\t * - i : the number of the digits in `d` that are to the left of the decimal point\n\t * - e : the exponent for numbers that would need more than `MAX_DIGITS` digits in `d`\n\t *\n\t */\n\tfunction parse(numStr) {\n\t var exponent = 0, digits, numberOfIntegerDigits;\n\t var i, j, zeros;\n\t\n\t // Decimal point?\n\t if ((numberOfIntegerDigits = numStr.indexOf(DECIMAL_SEP)) > -1) {\n\t numStr = numStr.replace(DECIMAL_SEP, '');\n\t }\n\t\n\t // Exponential form?\n\t if ((i = numStr.search(/e/i)) > 0) {\n\t // Work out the exponent.\n\t if (numberOfIntegerDigits < 0) numberOfIntegerDigits = i;\n\t numberOfIntegerDigits += +numStr.slice(i + 1);\n\t numStr = numStr.substring(0, i);\n\t } else if (numberOfIntegerDigits < 0) {\n\t // There was no decimal point or exponent so it is an integer.\n\t numberOfIntegerDigits = numStr.length;\n\t }\n\t\n\t // Count the number of leading zeros.\n\t for (i = 0; numStr.charAt(i) == ZERO_CHAR; i++) {/* jshint noempty: false */}\n\t\n\t if (i == (zeros = numStr.length)) {\n\t // The digits are all zero.\n\t digits = [0];\n\t numberOfIntegerDigits = 1;\n\t } else {\n\t // Count the number of trailing zeros\n\t zeros--;\n\t while (numStr.charAt(zeros) == ZERO_CHAR) zeros--;\n\t\n\t // Trailing zeros are insignificant so ignore them\n\t numberOfIntegerDigits -= i;\n\t digits = [];\n\t // Convert string to array of digits without leading/trailing zeros.\n\t for (j = 0; i <= zeros; i++, j++) {\n\t digits[j] = +numStr.charAt(i);\n\t }\n\t }\n\t\n\t // If the number overflows the maximum allowed digits then use an exponent.\n\t if (numberOfIntegerDigits > MAX_DIGITS) {\n\t digits = digits.splice(0, MAX_DIGITS - 1);\n\t exponent = numberOfIntegerDigits - 1;\n\t numberOfIntegerDigits = 1;\n\t }\n\t\n\t return { d: digits, e: exponent, i: numberOfIntegerDigits };\n\t}\n\t\n\t/**\n\t * Round the parsed number to the specified number of decimal places\n\t * This function changed the parsedNumber in-place\n\t */\n\tfunction roundNumber(parsedNumber, fractionSize, minFrac, maxFrac) {\n\t var digits = parsedNumber.d;\n\t var fractionLen = digits.length - parsedNumber.i;\n\t\n\t // determine fractionSize if it is not specified; `+fractionSize` converts it to a number\n\t fractionSize = (isUndefined(fractionSize)) ? Math.min(Math.max(minFrac, fractionLen), maxFrac) : +fractionSize;\n\t\n\t // The index of the digit to where rounding is to occur\n\t var roundAt = fractionSize + parsedNumber.i;\n\t var digit = digits[roundAt];\n\t\n\t if (roundAt > 0) {\n\t // Drop fractional digits beyond `roundAt`\n\t digits.splice(Math.max(parsedNumber.i, roundAt));\n\t\n\t // Set non-fractional digits beyond `roundAt` to 0\n\t for (var j = roundAt; j < digits.length; j++) {\n\t digits[j] = 0;\n\t }\n\t } else {\n\t // We rounded to zero so reset the parsedNumber\n\t fractionLen = Math.max(0, fractionLen);\n\t parsedNumber.i = 1;\n\t digits.length = Math.max(1, roundAt = fractionSize + 1);\n\t digits[0] = 0;\n\t for (var i = 1; i < roundAt; i++) digits[i] = 0;\n\t }\n\t\n\t if (digit >= 5) {\n\t if (roundAt - 1 < 0) {\n\t for (var k = 0; k > roundAt; k--) {\n\t digits.unshift(0);\n\t parsedNumber.i++;\n\t }\n\t digits.unshift(1);\n\t parsedNumber.i++;\n\t } else {\n\t digits[roundAt - 1]++;\n\t }\n\t }\n\t\n\t // Pad out with zeros to get the required fraction length\n\t for (; fractionLen < Math.max(0, fractionSize); fractionLen++) digits.push(0);\n\t\n\t\n\t // Do any carrying, e.g. a digit was rounded up to 10\n\t var carry = digits.reduceRight(function(carry, d, i, digits) {\n\t d = d + carry;\n\t digits[i] = d % 10;\n\t return Math.floor(d / 10);\n\t }, 0);\n\t if (carry) {\n\t digits.unshift(carry);\n\t parsedNumber.i++;\n\t }\n\t}\n\t\n\t/**\n\t * Format a number into a string\n\t * @param {number} number The number to format\n\t * @param {{\n\t * minFrac, // the minimum number of digits required in the fraction part of the number\n\t * maxFrac, // the maximum number of digits required in the fraction part of the number\n\t * gSize, // number of digits in each group of separated digits\n\t * lgSize, // number of digits in the last group of digits before the decimal separator\n\t * negPre, // the string to go in front of a negative number (e.g. `-` or `(`))\n\t * posPre, // the string to go in front of a positive number\n\t * negSuf, // the string to go after a negative number (e.g. `)`)\n\t * posSuf // the string to go after a positive number\n\t * }} pattern\n\t * @param {string} groupSep The string to separate groups of number (e.g. `,`)\n\t * @param {string} decimalSep The string to act as the decimal separator (e.g. `.`)\n\t * @param {[type]} fractionSize The size of the fractional part of the number\n\t * @return {string} The number formatted as a string\n\t */\n\tfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n\t\n\t if (!(isString(number) || isNumber(number)) || isNaN(number)) return '';\n\t\n\t var isInfinity = !isFinite(number);\n\t var isZero = false;\n\t var numStr = Math.abs(number) + '',\n\t formattedText = '',\n\t parsedNumber;\n\t\n\t if (isInfinity) {\n\t formattedText = '\\u221e';\n\t } else {\n\t parsedNumber = parse(numStr);\n\t\n\t roundNumber(parsedNumber, fractionSize, pattern.minFrac, pattern.maxFrac);\n\t\n\t var digits = parsedNumber.d;\n\t var integerLen = parsedNumber.i;\n\t var exponent = parsedNumber.e;\n\t var decimals = [];\n\t isZero = digits.reduce(function(isZero, d) { return isZero && !d; }, true);\n\t\n\t // pad zeros for small numbers\n\t while (integerLen < 0) {\n\t digits.unshift(0);\n\t integerLen++;\n\t }\n\t\n\t // extract decimals digits\n\t if (integerLen > 0) {\n\t decimals = digits.splice(integerLen, digits.length);\n\t } else {\n\t decimals = digits;\n\t digits = [0];\n\t }\n\t\n\t // format the integer digits with grouping separators\n\t var groups = [];\n\t if (digits.length >= pattern.lgSize) {\n\t groups.unshift(digits.splice(-pattern.lgSize, digits.length).join(''));\n\t }\n\t while (digits.length > pattern.gSize) {\n\t groups.unshift(digits.splice(-pattern.gSize, digits.length).join(''));\n\t }\n\t if (digits.length) {\n\t groups.unshift(digits.join(''));\n\t }\n\t formattedText = groups.join(groupSep);\n\t\n\t // append the decimal digits\n\t if (decimals.length) {\n\t formattedText += decimalSep + decimals.join('');\n\t }\n\t\n\t if (exponent) {\n\t formattedText += 'e+' + exponent;\n\t }\n\t }\n\t if (number < 0 && !isZero) {\n\t return pattern.negPre + formattedText + pattern.negSuf;\n\t } else {\n\t return pattern.posPre + formattedText + pattern.posSuf;\n\t }\n\t}\n\t\n\tfunction padNumber(num, digits, trim, negWrap) {\n\t var neg = '';\n\t if (num < 0 || (negWrap && num <= 0)) {\n\t if (negWrap) {\n\t num = -num + 1;\n\t } else {\n\t num = -num;\n\t neg = '-';\n\t }\n\t }\n\t num = '' + num;\n\t while (num.length < digits) num = ZERO_CHAR + num;\n\t if (trim) {\n\t num = num.substr(num.length - digits);\n\t }\n\t return neg + num;\n\t}\n\t\n\t\n\tfunction dateGetter(name, size, offset, trim, negWrap) {\n\t offset = offset || 0;\n\t return function(date) {\n\t var value = date['get' + name]();\n\t if (offset > 0 || value > -offset) {\n\t value += offset;\n\t }\n\t if (value === 0 && offset == -12) value = 12;\n\t return padNumber(value, size, trim, negWrap);\n\t };\n\t}\n\t\n\tfunction dateStrGetter(name, shortForm, standAlone) {\n\t return function(date, formats) {\n\t var value = date['get' + name]();\n\t var propPrefix = (standAlone ? 'STANDALONE' : '') + (shortForm ? 'SHORT' : '');\n\t var get = uppercase(propPrefix + name);\n\t\n\t return formats[get][value];\n\t };\n\t}\n\t\n\tfunction timeZoneGetter(date, formats, offset) {\n\t var zone = -1 * offset;\n\t var paddedZone = (zone >= 0) ? \"+\" : \"\";\n\t\n\t paddedZone += padNumber(Math[zone > 0 ? 'floor' : 'ceil'](zone / 60), 2) +\n\t padNumber(Math.abs(zone % 60), 2);\n\t\n\t return paddedZone;\n\t}\n\t\n\tfunction getFirstThursdayOfYear(year) {\n\t // 0 = index of January\n\t var dayOfWeekOnFirst = (new Date(year, 0, 1)).getDay();\n\t // 4 = index of Thursday (+1 to account for 1st = 5)\n\t // 11 = index of *next* Thursday (+1 account for 1st = 12)\n\t return new Date(year, 0, ((dayOfWeekOnFirst <= 4) ? 5 : 12) - dayOfWeekOnFirst);\n\t}\n\t\n\tfunction getThursdayThisWeek(datetime) {\n\t return new Date(datetime.getFullYear(), datetime.getMonth(),\n\t // 4 = index of Thursday\n\t datetime.getDate() + (4 - datetime.getDay()));\n\t}\n\t\n\tfunction weekGetter(size) {\n\t return function(date) {\n\t var firstThurs = getFirstThursdayOfYear(date.getFullYear()),\n\t thisThurs = getThursdayThisWeek(date);\n\t\n\t var diff = +thisThurs - +firstThurs,\n\t result = 1 + Math.round(diff / 6.048e8); // 6.048e8 ms per week\n\t\n\t return padNumber(result, size);\n\t };\n\t}\n\t\n\tfunction ampmGetter(date, formats) {\n\t return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n\t}\n\t\n\tfunction eraGetter(date, formats) {\n\t return date.getFullYear() <= 0 ? formats.ERAS[0] : formats.ERAS[1];\n\t}\n\t\n\tfunction longEraGetter(date, formats) {\n\t return date.getFullYear() <= 0 ? formats.ERANAMES[0] : formats.ERANAMES[1];\n\t}\n\t\n\tvar DATE_FORMATS = {\n\t yyyy: dateGetter('FullYear', 4, 0, false, true),\n\t yy: dateGetter('FullYear', 2, 0, true, true),\n\t y: dateGetter('FullYear', 1, 0, false, true),\n\t MMMM: dateStrGetter('Month'),\n\t MMM: dateStrGetter('Month', true),\n\t MM: dateGetter('Month', 2, 1),\n\t M: dateGetter('Month', 1, 1),\n\t LLLL: dateStrGetter('Month', false, true),\n\t dd: dateGetter('Date', 2),\n\t d: dateGetter('Date', 1),\n\t HH: dateGetter('Hours', 2),\n\t H: dateGetter('Hours', 1),\n\t hh: dateGetter('Hours', 2, -12),\n\t h: dateGetter('Hours', 1, -12),\n\t mm: dateGetter('Minutes', 2),\n\t m: dateGetter('Minutes', 1),\n\t ss: dateGetter('Seconds', 2),\n\t s: dateGetter('Seconds', 1),\n\t // while ISO 8601 requires fractions to be prefixed with `.` or `,`\n\t // we can be just safely rely on using `sss` since we currently don't support single or two digit fractions\n\t sss: dateGetter('Milliseconds', 3),\n\t EEEE: dateStrGetter('Day'),\n\t EEE: dateStrGetter('Day', true),\n\t a: ampmGetter,\n\t Z: timeZoneGetter,\n\t ww: weekGetter(2),\n\t w: weekGetter(1),\n\t G: eraGetter,\n\t GG: eraGetter,\n\t GGG: eraGetter,\n\t GGGG: longEraGetter\n\t};\n\t\n\tvar DATE_FORMATS_SPLIT = /((?:[^yMLdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|L+|d+|H+|h+|m+|s+|a|Z|G+|w+))(.*)/,\n\t NUMBER_STRING = /^\\-?\\d+$/;\n\t\n\t/**\n\t * @ngdoc filter\n\t * @name date\n\t * @kind function\n\t *\n\t * @description\n\t * Formats `date` to a string based on the requested `format`.\n\t *\n\t * `format` string can be composed of the following elements:\n\t *\n\t * * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n\t * * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n\t * * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n\t * * `'MMMM'`: Month in year (January-December)\n\t * * `'MMM'`: Month in year (Jan-Dec)\n\t * * `'MM'`: Month in year, padded (01-12)\n\t * * `'M'`: Month in year (1-12)\n\t * * `'LLLL'`: Stand-alone month in year (January-December)\n\t * * `'dd'`: Day in month, padded (01-31)\n\t * * `'d'`: Day in month (1-31)\n\t * * `'EEEE'`: Day in Week,(Sunday-Saturday)\n\t * * `'EEE'`: Day in Week, (Sun-Sat)\n\t * * `'HH'`: Hour in day, padded (00-23)\n\t * * `'H'`: Hour in day (0-23)\n\t * * `'hh'`: Hour in AM/PM, padded (01-12)\n\t * * `'h'`: Hour in AM/PM, (1-12)\n\t * * `'mm'`: Minute in hour, padded (00-59)\n\t * * `'m'`: Minute in hour (0-59)\n\t * * `'ss'`: Second in minute, padded (00-59)\n\t * * `'s'`: Second in minute (0-59)\n\t * * `'sss'`: Millisecond in second, padded (000-999)\n\t * * `'a'`: AM/PM marker\n\t * * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200)\n\t * * `'ww'`: Week of year, padded (00-53). Week 01 is the week with the first Thursday of the year\n\t * * `'w'`: Week of year (0-53). Week 1 is the week with the first Thursday of the year\n\t * * `'G'`, `'GG'`, `'GGG'`: The abbreviated form of the era string (e.g. 'AD')\n\t * * `'GGGG'`: The long form of the era string (e.g. 'Anno Domini')\n\t *\n\t * `format` string can also be one of the following predefined\n\t * {@link guide/i18n localizable formats}:\n\t *\n\t * * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n\t * (e.g. Sep 3, 2010 12:05:08 PM)\n\t * * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US locale (e.g. 9/3/10 12:05 PM)\n\t * * `'fullDate'`: equivalent to `'EEEE, MMMM d, y'` for en_US locale\n\t * (e.g. Friday, September 3, 2010)\n\t * * `'longDate'`: equivalent to `'MMMM d, y'` for en_US locale (e.g. September 3, 2010)\n\t * * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US locale (e.g. Sep 3, 2010)\n\t * * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n\t * * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 PM)\n\t * * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 PM)\n\t *\n\t * `format` string can contain literal values. These need to be escaped by surrounding with single quotes (e.g.\n\t * `\"h 'in the morning'\"`). In order to output a single quote, escape it - i.e., two single quotes in a sequence\n\t * (e.g. `\"h 'o''clock'\"`).\n\t *\n\t * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n\t * number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.sssZ and its\n\t * shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ). If no timezone is\n\t * specified in the string input, the time is considered to be in the local timezone.\n\t * @param {string=} format Formatting rules (see Description). If not specified,\n\t * `mediumDate` is used.\n\t * @param {string=} timezone Timezone to be used for formatting. It understands UTC/GMT and the\n\t * continental US time zone abbreviations, but for general use, use a time zone offset, for\n\t * example, `'+0430'` (4 hours, 30 minutes east of the Greenwich meridian)\n\t * If not specified, the timezone of the browser will be used.\n\t * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n\t *\n\t * @example\n\t \n\t \n\t {{1288323623006 | date:'medium'}}:\n\t {{1288323623006 | date:'medium'}}
\n\t {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}:\n\t {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}
\n\t {{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}:\n\t {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}
\n\t {{1288323623006 | date:\"MM/dd/yyyy 'at' h:mma\"}}:\n\t {{'1288323623006' | date:\"MM/dd/yyyy 'at' h:mma\"}}
\n\t
\n\t \n\t it('should format date', function() {\n\t expect(element(by.binding(\"1288323623006 | date:'medium'\")).getText()).\n\t toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n\t expect(element(by.binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).getText()).\n\t toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} (\\-|\\+)?\\d{4}/);\n\t expect(element(by.binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).getText()).\n\t toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n\t expect(element(by.binding(\"'1288323623006' | date:\\\"MM/dd/yyyy 'at' h:mma\\\"\")).getText()).\n\t toMatch(/10\\/2\\d\\/2010 at \\d{1,2}:\\d{2}(AM|PM)/);\n\t });\n\t \n\t
\n\t */\n\tdateFilter.$inject = ['$locale'];\n\tfunction dateFilter($locale) {\n\t\n\t\n\t var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n\t // 1 2 3 4 5 6 7 8 9 10 11\n\t function jsonStringToDate(string) {\n\t var match;\n\t if (match = string.match(R_ISO8601_STR)) {\n\t var date = new Date(0),\n\t tzHour = 0,\n\t tzMin = 0,\n\t dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear,\n\t timeSetter = match[8] ? date.setUTCHours : date.setHours;\n\t\n\t if (match[9]) {\n\t tzHour = toInt(match[9] + match[10]);\n\t tzMin = toInt(match[9] + match[11]);\n\t }\n\t dateSetter.call(date, toInt(match[1]), toInt(match[2]) - 1, toInt(match[3]));\n\t var h = toInt(match[4] || 0) - tzHour;\n\t var m = toInt(match[5] || 0) - tzMin;\n\t var s = toInt(match[6] || 0);\n\t var ms = Math.round(parseFloat('0.' + (match[7] || 0)) * 1000);\n\t timeSetter.call(date, h, m, s, ms);\n\t return date;\n\t }\n\t return string;\n\t }\n\t\n\t\n\t return function(date, format, timezone) {\n\t var text = '',\n\t parts = [],\n\t fn, match;\n\t\n\t format = format || 'mediumDate';\n\t format = $locale.DATETIME_FORMATS[format] || format;\n\t if (isString(date)) {\n\t date = NUMBER_STRING.test(date) ? toInt(date) : jsonStringToDate(date);\n\t }\n\t\n\t if (isNumber(date)) {\n\t date = new Date(date);\n\t }\n\t\n\t if (!isDate(date) || !isFinite(date.getTime())) {\n\t return date;\n\t }\n\t\n\t while (format) {\n\t match = DATE_FORMATS_SPLIT.exec(format);\n\t if (match) {\n\t parts = concat(parts, match, 1);\n\t format = parts.pop();\n\t } else {\n\t parts.push(format);\n\t format = null;\n\t }\n\t }\n\t\n\t var dateTimezoneOffset = date.getTimezoneOffset();\n\t if (timezone) {\n\t dateTimezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset);\n\t date = convertTimezoneToLocal(date, timezone, true);\n\t }\n\t forEach(parts, function(value) {\n\t fn = DATE_FORMATS[value];\n\t text += fn ? fn(date, $locale.DATETIME_FORMATS, dateTimezoneOffset)\n\t : value === \"''\" ? \"'\" : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n\t });\n\t\n\t return text;\n\t };\n\t}\n\t\n\t\n\t/**\n\t * @ngdoc filter\n\t * @name json\n\t * @kind function\n\t *\n\t * @description\n\t * Allows you to convert a JavaScript object into JSON string.\n\t *\n\t * This filter is mostly useful for debugging. When using the double curly {{value}} notation\n\t * the binding is automatically converted to JSON.\n\t *\n\t * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n\t * @param {number=} spacing The number of spaces to use per indentation, defaults to 2.\n\t * @returns {string} JSON string.\n\t *\n\t *\n\t * @example\n\t \n\t \n\t
{{ {'name':'value'} | json }}
\n\t
{{ {'name':'value'} | json:4 }}
\n\t
\n\t \n\t it('should jsonify filtered objects', function() {\n\t expect(element(by.id('default-spacing')).getText()).toMatch(/\\{\\n \"name\": ?\"value\"\\n}/);\n\t expect(element(by.id('custom-spacing')).getText()).toMatch(/\\{\\n \"name\": ?\"value\"\\n}/);\n\t });\n\t \n\t
\n\t *\n\t */\n\tfunction jsonFilter() {\n\t return function(object, spacing) {\n\t if (isUndefined(spacing)) {\n\t spacing = 2;\n\t }\n\t return toJson(object, spacing);\n\t };\n\t}\n\t\n\t\n\t/**\n\t * @ngdoc filter\n\t * @name lowercase\n\t * @kind function\n\t * @description\n\t * Converts string to lowercase.\n\t * @see angular.lowercase\n\t */\n\tvar lowercaseFilter = valueFn(lowercase);\n\t\n\t\n\t/**\n\t * @ngdoc filter\n\t * @name uppercase\n\t * @kind function\n\t * @description\n\t * Converts string to uppercase.\n\t * @see angular.uppercase\n\t */\n\tvar uppercaseFilter = valueFn(uppercase);\n\t\n\t/**\n\t * @ngdoc filter\n\t * @name limitTo\n\t * @kind function\n\t *\n\t * @description\n\t * Creates a new array or string containing only a specified number of elements. The elements are\n\t * taken from either the beginning or the end of the source array, string or number, as specified by\n\t * the value and sign (positive or negative) of `limit`. Other array-like objects are also supported\n\t * (e.g. array subclasses, NodeLists, jqLite/jQuery collections etc). If a number is used as input,\n\t * it is converted to a string.\n\t *\n\t * @param {Array|ArrayLike|string|number} input - Array/array-like, string or number to be limited.\n\t * @param {string|number} limit - The length of the returned array or string. If the `limit` number\n\t * is positive, `limit` number of items from the beginning of the source array/string are copied.\n\t * If the number is negative, `limit` number of items from the end of the source array/string\n\t * are copied. The `limit` will be trimmed if it exceeds `array.length`. If `limit` is undefined,\n\t * the input will be returned unchanged.\n\t * @param {(string|number)=} begin - Index at which to begin limitation. As a negative index,\n\t * `begin` indicates an offset from the end of `input`. Defaults to `0`.\n\t * @returns {Array|string} A new sub-array or substring of length `limit` or less if the input had\n\t * less than `limit` elements.\n\t *\n\t * @example\n\t \n\t \n\t \n\t
\n\t \n\t

Output numbers: {{ numbers | limitTo:numLimit }}

\n\t \n\t

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

\n\t \n\t

Output long number: {{ longNumber | limitTo:longNumberLimit }}

\n\t
\n\t
\n\t \n\t var numLimitInput = element(by.model('numLimit'));\n\t var letterLimitInput = element(by.model('letterLimit'));\n\t var longNumberLimitInput = element(by.model('longNumberLimit'));\n\t var limitedNumbers = element(by.binding('numbers | limitTo:numLimit'));\n\t var limitedLetters = element(by.binding('letters | limitTo:letterLimit'));\n\t var limitedLongNumber = element(by.binding('longNumber | limitTo:longNumberLimit'));\n\t\n\t it('should limit the number array to first three items', function() {\n\t expect(numLimitInput.getAttribute('value')).toBe('3');\n\t expect(letterLimitInput.getAttribute('value')).toBe('3');\n\t expect(longNumberLimitInput.getAttribute('value')).toBe('3');\n\t expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3]');\n\t expect(limitedLetters.getText()).toEqual('Output letters: abc');\n\t expect(limitedLongNumber.getText()).toEqual('Output long number: 234');\n\t });\n\t\n\t // There is a bug in safari and protractor that doesn't like the minus key\n\t // it('should update the output when -3 is entered', function() {\n\t // numLimitInput.clear();\n\t // numLimitInput.sendKeys('-3');\n\t // letterLimitInput.clear();\n\t // letterLimitInput.sendKeys('-3');\n\t // longNumberLimitInput.clear();\n\t // longNumberLimitInput.sendKeys('-3');\n\t // expect(limitedNumbers.getText()).toEqual('Output numbers: [7,8,9]');\n\t // expect(limitedLetters.getText()).toEqual('Output letters: ghi');\n\t // expect(limitedLongNumber.getText()).toEqual('Output long number: 342');\n\t // });\n\t\n\t it('should not exceed the maximum size of input array', function() {\n\t numLimitInput.clear();\n\t numLimitInput.sendKeys('100');\n\t letterLimitInput.clear();\n\t letterLimitInput.sendKeys('100');\n\t longNumberLimitInput.clear();\n\t longNumberLimitInput.sendKeys('100');\n\t expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3,4,5,6,7,8,9]');\n\t expect(limitedLetters.getText()).toEqual('Output letters: abcdefghi');\n\t expect(limitedLongNumber.getText()).toEqual('Output long number: 2345432342');\n\t });\n\t \n\t
\n\t*/\n\tfunction limitToFilter() {\n\t return function(input, limit, begin) {\n\t if (Math.abs(Number(limit)) === Infinity) {\n\t limit = Number(limit);\n\t } else {\n\t limit = toInt(limit);\n\t }\n\t if (isNaN(limit)) return input;\n\t\n\t if (isNumber(input)) input = input.toString();\n\t if (!isArrayLike(input)) return input;\n\t\n\t begin = (!begin || isNaN(begin)) ? 0 : toInt(begin);\n\t begin = (begin < 0) ? Math.max(0, input.length + begin) : begin;\n\t\n\t if (limit >= 0) {\n\t return sliceFn(input, begin, begin + limit);\n\t } else {\n\t if (begin === 0) {\n\t return sliceFn(input, limit, input.length);\n\t } else {\n\t return sliceFn(input, Math.max(0, begin + limit), begin);\n\t }\n\t }\n\t };\n\t}\n\t\n\tfunction sliceFn(input, begin, end) {\n\t if (isString(input)) return input.slice(begin, end);\n\t\n\t return slice.call(input, begin, end);\n\t}\n\t\n\t/**\n\t * @ngdoc filter\n\t * @name orderBy\n\t * @kind function\n\t *\n\t * @description\n\t * Returns an array containing the items from the specified `collection`, ordered by a `comparator`\n\t * function based on the values computed using the `expression` predicate.\n\t *\n\t * For example, `[{id: 'foo'}, {id: 'bar'}] | orderBy:'id'` would result in\n\t * `[{id: 'bar'}, {id: 'foo'}]`.\n\t *\n\t * The `collection` can be an Array or array-like object (e.g. NodeList, jQuery object, TypedArray,\n\t * String, etc).\n\t *\n\t * The `expression` can be a single predicate, or a list of predicates each serving as a tie-breaker\n\t * for the preceeding one. The `expression` is evaluated against each item and the output is used\n\t * for comparing with other items.\n\t *\n\t * You can change the sorting order by setting `reverse` to `true`. By default, items are sorted in\n\t * ascending order.\n\t *\n\t * The comparison is done using the `comparator` function. If none is specified, a default, built-in\n\t * comparator is used (see below for details - in a nutshell, it compares numbers numerically and\n\t * strings alphabetically).\n\t *\n\t * ### Under the hood\n\t *\n\t * Ordering the specified `collection` happens in two phases:\n\t *\n\t * 1. All items are passed through the predicate (or predicates), and the returned values are saved\n\t * along with their type (`string`, `number` etc). For example, an item `{label: 'foo'}`, passed\n\t * through a predicate that extracts the value of the `label` property, would be transformed to:\n\t * ```\n\t * {\n\t * value: 'foo',\n\t * type: 'string',\n\t * index: ...\n\t * }\n\t * ```\n\t * 2. The comparator function is used to sort the items, based on the derived values, types and\n\t * indices.\n\t *\n\t * If you use a custom comparator, it will be called with pairs of objects of the form\n\t * `{value: ..., type: '...', index: ...}` and is expected to return `0` if the objects are equal\n\t * (as far as the comparator is concerned), `-1` if the 1st one should be ranked higher than the\n\t * second, or `1` otherwise.\n\t *\n\t * In order to ensure that the sorting will be deterministic across platforms, if none of the\n\t * specified predicates can distinguish between two items, `orderBy` will automatically introduce a\n\t * dummy predicate that returns the item's index as `value`.\n\t * (If you are using a custom comparator, make sure it can handle this predicate as well.)\n\t *\n\t * Finally, in an attempt to simplify things, if a predicate returns an object as the extracted\n\t * value for an item, `orderBy` will try to convert that object to a primitive value, before passing\n\t * it to the comparator. The following rules govern the conversion:\n\t *\n\t * 1. If the object has a `valueOf()` method that returns a primitive, its return value will be\n\t * used instead.
\n\t * (If the object has a `valueOf()` method that returns another object, then the returned object\n\t * will be used in subsequent steps.)\n\t * 2. If the object has a custom `toString()` method (i.e. not the one inherited from `Object`) that\n\t * returns a primitive, its return value will be used instead.
\n\t * (If the object has a `toString()` method that returns another object, then the returned object\n\t * will be used in subsequent steps.)\n\t * 3. No conversion; the object itself is used.\n\t *\n\t * ### The default comparator\n\t *\n\t * The default, built-in comparator should be sufficient for most usecases. In short, it compares\n\t * numbers numerically, strings alphabetically (and case-insensitively), for objects falls back to\n\t * using their index in the original collection, and sorts values of different types by type.\n\t *\n\t * More specifically, it follows these steps to determine the relative order of items:\n\t *\n\t * 1. If the compared values are of different types, compare the types themselves alphabetically.\n\t * 2. If both values are of type `string`, compare them alphabetically in a case- and\n\t * locale-insensitive way.\n\t * 3. If both values are objects, compare their indices instead.\n\t * 4. Otherwise, return:\n\t * - `0`, if the values are equal (by strict equality comparison, i.e. using `===`).\n\t * - `-1`, if the 1st value is \"less than\" the 2nd value (compared using the `<` operator).\n\t * - `1`, otherwise.\n\t *\n\t * **Note:** If you notice numbers not being sorted as expected, make sure they are actually being\n\t * saved as numbers and not strings.\n\t *\n\t * @param {Array|ArrayLike} collection - The collection (array or array-like object) to sort.\n\t * @param {(Function|string|Array.)=} expression - A predicate (or list of\n\t * predicates) to be used by the comparator to determine the order of elements.\n\t *\n\t * Can be one of:\n\t *\n\t * - `Function`: A getter function. This function will be called with each item as argument and\n\t * the return value will be used for sorting.\n\t * - `string`: An Angular expression. This expression will be evaluated against each item and the\n\t * result will be used for sorting. For example, use `'label'` to sort by a property called\n\t * `label` or `'label.substring(0, 3)'` to sort by the first 3 characters of the `label`\n\t * property.
\n\t * (The result of a constant expression is interpreted as a property name to be used for\n\t * comparison. For example, use `'\"special name\"'` (note the extra pair of quotes) to sort by a\n\t * property called `special name`.)
\n\t * An expression can be optionally prefixed with `+` or `-` to control the sorting direction,\n\t * ascending or descending. For example, `'+label'` or `'-label'`. If no property is provided,\n\t * (e.g. `'+'` or `'-'`), the collection element itself is used in comparisons.\n\t * - `Array`: An array of function and/or string predicates. If a predicate cannot determine the\n\t * relative order of two items, the next predicate is used as a tie-breaker.\n\t *\n\t * **Note:** If the predicate is missing or empty then it defaults to `'+'`.\n\t *\n\t * @param {boolean=} reverse - If `true`, reverse the sorting order.\n\t * @param {(Function)=} comparator - The comparator function used to determine the relative order of\n\t * value pairs. If omitted, the built-in comparator will be used.\n\t *\n\t * @returns {Array} - The sorted array.\n\t *\n\t *\n\t * @example\n\t * ### Ordering a table with `ngRepeat`\n\t *\n\t * The example below demonstrates a simple {@link ngRepeat ngRepeat}, where the data is sorted by\n\t * age in descending order (expression is set to `'-age'`). The `comparator` is not set, which means\n\t * it defaults to the built-in comparator.\n\t *\n\t \n\t \n\t
\n\t \n\t \n\t \n\t \n\t \n\t \n\t \n\t \n\t \n\t \n\t \n\t
NamePhone NumberAge
{{friend.name}}{{friend.phone}}{{friend.age}}
\n\t
\n\t
\n\t \n\t angular.module('orderByExample1', [])\n\t .controller('ExampleController', ['$scope', function($scope) {\n\t $scope.friends = [\n\t {name: 'John', phone: '555-1212', age: 10},\n\t {name: 'Mary', phone: '555-9876', age: 19},\n\t {name: 'Mike', phone: '555-4321', age: 21},\n\t {name: 'Adam', phone: '555-5678', age: 35},\n\t {name: 'Julie', phone: '555-8765', age: 29}\n\t ];\n\t }]);\n\t \n\t \n\t .friends {\n\t border-collapse: collapse;\n\t }\n\t\n\t .friends th {\n\t border-bottom: 1px solid;\n\t }\n\t .friends td, .friends th {\n\t border-left: 1px solid;\n\t padding: 5px 10px;\n\t }\n\t .friends td:first-child, .friends th:first-child {\n\t border-left: none;\n\t }\n\t \n\t \n\t // Element locators\n\t var names = element.all(by.repeater('friends').column('friend.name'));\n\t\n\t it('should sort friends by age in reverse order', function() {\n\t expect(names.get(0).getText()).toBe('Adam');\n\t expect(names.get(1).getText()).toBe('Julie');\n\t expect(names.get(2).getText()).toBe('Mike');\n\t expect(names.get(3).getText()).toBe('Mary');\n\t expect(names.get(4).getText()).toBe('John');\n\t });\n\t \n\t
\n\t *
\n\t *\n\t * @example\n\t * ### Changing parameters dynamically\n\t *\n\t * All parameters can be changed dynamically. The next example shows how you can make the columns of\n\t * a table sortable, by binding the `expression` and `reverse` parameters to scope properties.\n\t *\n\t \n\t \n\t
\n\t
Sort by = {{propertyName}}; reverse = {{reverse}}
\n\t
\n\t \n\t
\n\t \n\t \n\t \n\t \n\t \n\t \n\t \n\t \n\t \n\t \n\t \n\t
\n\t \n\t \n\t \n\t \n\t \n\t \n\t \n\t \n\t
{{friend.name}}{{friend.phone}}{{friend.age}}
\n\t
\n\t
\n\t \n\t angular.module('orderByExample2', [])\n\t .controller('ExampleController', ['$scope', function($scope) {\n\t var friends = [\n\t {name: 'John', phone: '555-1212', age: 10},\n\t {name: 'Mary', phone: '555-9876', age: 19},\n\t {name: 'Mike', phone: '555-4321', age: 21},\n\t {name: 'Adam', phone: '555-5678', age: 35},\n\t {name: 'Julie', phone: '555-8765', age: 29}\n\t ];\n\t\n\t $scope.propertyName = 'age';\n\t $scope.reverse = true;\n\t $scope.friends = friends;\n\t\n\t $scope.sortBy = function(propertyName) {\n\t $scope.reverse = ($scope.propertyName === propertyName) ? !$scope.reverse : false;\n\t $scope.propertyName = propertyName;\n\t };\n\t }]);\n\t \n\t \n\t .friends {\n\t border-collapse: collapse;\n\t }\n\t\n\t .friends th {\n\t border-bottom: 1px solid;\n\t }\n\t .friends td, .friends th {\n\t border-left: 1px solid;\n\t padding: 5px 10px;\n\t }\n\t .friends td:first-child, .friends th:first-child {\n\t border-left: none;\n\t }\n\t\n\t .sortorder:after {\n\t content: '\\25b2'; // BLACK UP-POINTING TRIANGLE\n\t }\n\t .sortorder.reverse:after {\n\t content: '\\25bc'; // BLACK DOWN-POINTING TRIANGLE\n\t }\n\t \n\t \n\t // Element locators\n\t var unsortButton = element(by.partialButtonText('unsorted'));\n\t var nameHeader = element(by.partialButtonText('Name'));\n\t var phoneHeader = element(by.partialButtonText('Phone'));\n\t var ageHeader = element(by.partialButtonText('Age'));\n\t var firstName = element(by.repeater('friends').column('friend.name').row(0));\n\t var lastName = element(by.repeater('friends').column('friend.name').row(4));\n\t\n\t it('should sort friends by some property, when clicking on the column header', function() {\n\t expect(firstName.getText()).toBe('Adam');\n\t expect(lastName.getText()).toBe('John');\n\t\n\t phoneHeader.click();\n\t expect(firstName.getText()).toBe('John');\n\t expect(lastName.getText()).toBe('Mary');\n\t\n\t nameHeader.click();\n\t expect(firstName.getText()).toBe('Adam');\n\t expect(lastName.getText()).toBe('Mike');\n\t\n\t ageHeader.click();\n\t expect(firstName.getText()).toBe('John');\n\t expect(lastName.getText()).toBe('Adam');\n\t });\n\t\n\t it('should sort friends in reverse order, when clicking on the same column', function() {\n\t expect(firstName.getText()).toBe('Adam');\n\t expect(lastName.getText()).toBe('John');\n\t\n\t ageHeader.click();\n\t expect(firstName.getText()).toBe('John');\n\t expect(lastName.getText()).toBe('Adam');\n\t\n\t ageHeader.click();\n\t expect(firstName.getText()).toBe('Adam');\n\t expect(lastName.getText()).toBe('John');\n\t });\n\t\n\t it('should restore the original order, when clicking \"Set to unsorted\"', function() {\n\t expect(firstName.getText()).toBe('Adam');\n\t expect(lastName.getText()).toBe('John');\n\t\n\t unsortButton.click();\n\t expect(firstName.getText()).toBe('John');\n\t expect(lastName.getText()).toBe('Julie');\n\t });\n\t \n\t
\n\t *
\n\t *\n\t * @example\n\t * ### Using `orderBy` inside a controller\n\t *\n\t * It is also possible to call the `orderBy` filter manually, by injecting `orderByFilter`, and\n\t * calling it with the desired parameters. (Alternatively, you could inject the `$filter` factory\n\t * and retrieve the `orderBy` filter with `$filter('orderBy')`.)\n\t *\n\t \n\t \n\t
\n\t
Sort by = {{propertyName}}; reverse = {{reverse}}
\n\t
\n\t \n\t
\n\t \n\t \n\t \n\t \n\t \n\t \n\t \n\t \n\t \n\t \n\t \n\t
\n\t \n\t \n\t \n\t \n\t \n\t \n\t \n\t \n\t
{{friend.name}}{{friend.phone}}{{friend.age}}
\n\t
\n\t
\n\t \n\t angular.module('orderByExample3', [])\n\t .controller('ExampleController', ['$scope', 'orderByFilter', function($scope, orderBy) {\n\t var friends = [\n\t {name: 'John', phone: '555-1212', age: 10},\n\t {name: 'Mary', phone: '555-9876', age: 19},\n\t {name: 'Mike', phone: '555-4321', age: 21},\n\t {name: 'Adam', phone: '555-5678', age: 35},\n\t {name: 'Julie', phone: '555-8765', age: 29}\n\t ];\n\t\n\t $scope.propertyName = 'age';\n\t $scope.reverse = true;\n\t $scope.friends = orderBy(friends, $scope.propertyName, $scope.reverse);\n\t\n\t $scope.sortBy = function(propertyName) {\n\t $scope.reverse = (propertyName !== null && $scope.propertyName === propertyName)\n\t ? !$scope.reverse : false;\n\t $scope.propertyName = propertyName;\n\t $scope.friends = orderBy(friends, $scope.propertyName, $scope.reverse);\n\t };\n\t }]);\n\t \n\t \n\t .friends {\n\t border-collapse: collapse;\n\t }\n\t\n\t .friends th {\n\t border-bottom: 1px solid;\n\t }\n\t .friends td, .friends th {\n\t border-left: 1px solid;\n\t padding: 5px 10px;\n\t }\n\t .friends td:first-child, .friends th:first-child {\n\t border-left: none;\n\t }\n\t\n\t .sortorder:after {\n\t content: '\\25b2'; // BLACK UP-POINTING TRIANGLE\n\t }\n\t .sortorder.reverse:after {\n\t content: '\\25bc'; // BLACK DOWN-POINTING TRIANGLE\n\t }\n\t \n\t \n\t // Element locators\n\t var unsortButton = element(by.partialButtonText('unsorted'));\n\t var nameHeader = element(by.partialButtonText('Name'));\n\t var phoneHeader = element(by.partialButtonText('Phone'));\n\t var ageHeader = element(by.partialButtonText('Age'));\n\t var firstName = element(by.repeater('friends').column('friend.name').row(0));\n\t var lastName = element(by.repeater('friends').column('friend.name').row(4));\n\t\n\t it('should sort friends by some property, when clicking on the column header', function() {\n\t expect(firstName.getText()).toBe('Adam');\n\t expect(lastName.getText()).toBe('John');\n\t\n\t phoneHeader.click();\n\t expect(firstName.getText()).toBe('John');\n\t expect(lastName.getText()).toBe('Mary');\n\t\n\t nameHeader.click();\n\t expect(firstName.getText()).toBe('Adam');\n\t expect(lastName.getText()).toBe('Mike');\n\t\n\t ageHeader.click();\n\t expect(firstName.getText()).toBe('John');\n\t expect(lastName.getText()).toBe('Adam');\n\t });\n\t\n\t it('should sort friends in reverse order, when clicking on the same column', function() {\n\t expect(firstName.getText()).toBe('Adam');\n\t expect(lastName.getText()).toBe('John');\n\t\n\t ageHeader.click();\n\t expect(firstName.getText()).toBe('John');\n\t expect(lastName.getText()).toBe('Adam');\n\t\n\t ageHeader.click();\n\t expect(firstName.getText()).toBe('Adam');\n\t expect(lastName.getText()).toBe('John');\n\t });\n\t\n\t it('should restore the original order, when clicking \"Set to unsorted\"', function() {\n\t expect(firstName.getText()).toBe('Adam');\n\t expect(lastName.getText()).toBe('John');\n\t\n\t unsortButton.click();\n\t expect(firstName.getText()).toBe('John');\n\t expect(lastName.getText()).toBe('Julie');\n\t });\n\t \n\t
\n\t *
\n\t *\n\t * @example\n\t * ### Using a custom comparator\n\t *\n\t * If you have very specific requirements about the way items are sorted, you can pass your own\n\t * comparator function. For example, you might need to compare some strings in a locale-sensitive\n\t * way. (When specifying a custom comparator, you also need to pass a value for the `reverse`\n\t * argument - passing `false` retains the default sorting order, i.e. ascending.)\n\t *\n\t \n\t \n\t
\n\t
\n\t

Locale-sensitive Comparator

\n\t \n\t \n\t \n\t \n\t \n\t \n\t \n\t \n\t \n\t
NameFavorite Letter
{{friend.name}}{{friend.favoriteLetter}}
\n\t
\n\t
\n\t

Default Comparator

\n\t \n\t \n\t \n\t \n\t \n\t \n\t \n\t \n\t \n\t
NameFavorite Letter
{{friend.name}}{{friend.favoriteLetter}}
\n\t
\n\t
\n\t
\n\t \n\t angular.module('orderByExample4', [])\n\t .controller('ExampleController', ['$scope', function($scope) {\n\t $scope.friends = [\n\t {name: 'John', favoriteLetter: 'Ä'},\n\t {name: 'Mary', favoriteLetter: 'Ü'},\n\t {name: 'Mike', favoriteLetter: 'Ö'},\n\t {name: 'Adam', favoriteLetter: 'H'},\n\t {name: 'Julie', favoriteLetter: 'Z'}\n\t ];\n\t\n\t $scope.localeSensitiveComparator = function(v1, v2) {\n\t // If we don't get strings, just compare by index\n\t if (v1.type !== 'string' || v2.type !== 'string') {\n\t return (v1.index < v2.index) ? -1 : 1;\n\t }\n\t\n\t // Compare strings alphabetically, taking locale into account\n\t return v1.value.localeCompare(v2.value);\n\t };\n\t }]);\n\t \n\t \n\t .friends-container {\n\t display: inline-block;\n\t margin: 0 30px;\n\t }\n\t\n\t .friends {\n\t border-collapse: collapse;\n\t }\n\t\n\t .friends th {\n\t border-bottom: 1px solid;\n\t }\n\t .friends td, .friends th {\n\t border-left: 1px solid;\n\t padding: 5px 10px;\n\t }\n\t .friends td:first-child, .friends th:first-child {\n\t border-left: none;\n\t }\n\t \n\t \n\t // Element locators\n\t var container = element(by.css('.custom-comparator'));\n\t var names = container.all(by.repeater('friends').column('friend.name'));\n\t\n\t it('should sort friends by favorite letter (in correct alphabetical order)', function() {\n\t expect(names.get(0).getText()).toBe('John');\n\t expect(names.get(1).getText()).toBe('Adam');\n\t expect(names.get(2).getText()).toBe('Mike');\n\t expect(names.get(3).getText()).toBe('Mary');\n\t expect(names.get(4).getText()).toBe('Julie');\n\t });\n\t \n\t
\n\t *\n\t */\n\torderByFilter.$inject = ['$parse'];\n\tfunction orderByFilter($parse) {\n\t return function(array, sortPredicate, reverseOrder, compareFn) {\n\t\n\t if (array == null) return array;\n\t if (!isArrayLike(array)) {\n\t throw minErr('orderBy')('notarray', 'Expected array but received: {0}', array);\n\t }\n\t\n\t if (!isArray(sortPredicate)) { sortPredicate = [sortPredicate]; }\n\t if (sortPredicate.length === 0) { sortPredicate = ['+']; }\n\t\n\t var predicates = processPredicates(sortPredicate);\n\t\n\t var descending = reverseOrder ? -1 : 1;\n\t\n\t // Define the `compare()` function. Use a default comparator if none is specified.\n\t var compare = isFunction(compareFn) ? compareFn : defaultCompare;\n\t\n\t // The next three lines are a version of a Swartzian Transform idiom from Perl\n\t // (sometimes called the Decorate-Sort-Undecorate idiom)\n\t // See https://en.wikipedia.org/wiki/Schwartzian_transform\n\t var compareValues = Array.prototype.map.call(array, getComparisonObject);\n\t compareValues.sort(doComparison);\n\t array = compareValues.map(function(item) { return item.value; });\n\t\n\t return array;\n\t\n\t function getComparisonObject(value, index) {\n\t // NOTE: We are adding an extra `tieBreaker` value based on the element's index.\n\t // This will be used to keep the sort stable when none of the input predicates can\n\t // distinguish between two elements.\n\t return {\n\t value: value,\n\t tieBreaker: {value: index, type: 'number', index: index},\n\t predicateValues: predicates.map(function(predicate) {\n\t return getPredicateValue(predicate.get(value), index);\n\t })\n\t };\n\t }\n\t\n\t function doComparison(v1, v2) {\n\t for (var i = 0, ii = predicates.length; i < ii; i++) {\n\t var result = compare(v1.predicateValues[i], v2.predicateValues[i]);\n\t if (result) {\n\t return result * predicates[i].descending * descending;\n\t }\n\t }\n\t\n\t return compare(v1.tieBreaker, v2.tieBreaker) * descending;\n\t }\n\t };\n\t\n\t function processPredicates(sortPredicates) {\n\t return sortPredicates.map(function(predicate) {\n\t var descending = 1, get = identity;\n\t\n\t if (isFunction(predicate)) {\n\t get = predicate;\n\t } else if (isString(predicate)) {\n\t if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n\t descending = predicate.charAt(0) == '-' ? -1 : 1;\n\t predicate = predicate.substring(1);\n\t }\n\t if (predicate !== '') {\n\t get = $parse(predicate);\n\t if (get.constant) {\n\t var key = get();\n\t get = function(value) { return value[key]; };\n\t }\n\t }\n\t }\n\t return {get: get, descending: descending};\n\t });\n\t }\n\t\n\t function isPrimitive(value) {\n\t switch (typeof value) {\n\t case 'number': /* falls through */\n\t case 'boolean': /* falls through */\n\t case 'string':\n\t return true;\n\t default:\n\t return false;\n\t }\n\t }\n\t\n\t function objectValue(value) {\n\t // If `valueOf` is a valid function use that\n\t if (isFunction(value.valueOf)) {\n\t value = value.valueOf();\n\t if (isPrimitive(value)) return value;\n\t }\n\t // If `toString` is a valid function and not the one from `Object.prototype` use that\n\t if (hasCustomToString(value)) {\n\t value = value.toString();\n\t if (isPrimitive(value)) return value;\n\t }\n\t\n\t return value;\n\t }\n\t\n\t function getPredicateValue(value, index) {\n\t var type = typeof value;\n\t if (value === null) {\n\t type = 'string';\n\t value = 'null';\n\t } else if (type === 'object') {\n\t value = objectValue(value);\n\t }\n\t return {value: value, type: type, index: index};\n\t }\n\t\n\t function defaultCompare(v1, v2) {\n\t var result = 0;\n\t var type1 = v1.type;\n\t var type2 = v2.type;\n\t\n\t if (type1 === type2) {\n\t var value1 = v1.value;\n\t var value2 = v2.value;\n\t\n\t if (type1 === 'string') {\n\t // Compare strings case-insensitively\n\t value1 = value1.toLowerCase();\n\t value2 = value2.toLowerCase();\n\t } else if (type1 === 'object') {\n\t // For basic objects, use the position of the object\n\t // in the collection instead of the value\n\t if (isObject(value1)) value1 = v1.index;\n\t if (isObject(value2)) value2 = v2.index;\n\t }\n\t\n\t if (value1 !== value2) {\n\t result = value1 < value2 ? -1 : 1;\n\t }\n\t } else {\n\t result = type1 < type2 ? -1 : 1;\n\t }\n\t\n\t return result;\n\t }\n\t}\n\t\n\tfunction ngDirective(directive) {\n\t if (isFunction(directive)) {\n\t directive = {\n\t link: directive\n\t };\n\t }\n\t directive.restrict = directive.restrict || 'AC';\n\t return valueFn(directive);\n\t}\n\t\n\t/**\n\t * @ngdoc directive\n\t * @name a\n\t * @restrict E\n\t *\n\t * @description\n\t * Modifies the default behavior of the html A tag so that the default action is prevented when\n\t * the href attribute is empty.\n\t *\n\t * This change permits the easy creation of action links with the `ngClick` directive\n\t * without changing the location or causing page reloads, e.g.:\n\t * `Add Item`\n\t */\n\tvar htmlAnchorDirective = valueFn({\n\t restrict: 'E',\n\t compile: function(element, attr) {\n\t if (!attr.href && !attr.xlinkHref) {\n\t return function(scope, element) {\n\t // If the linked element is not an anchor tag anymore, do nothing\n\t if (element[0].nodeName.toLowerCase() !== 'a') return;\n\t\n\t // SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute.\n\t var href = toString.call(element.prop('href')) === '[object SVGAnimatedString]' ?\n\t 'xlink:href' : 'href';\n\t element.on('click', function(event) {\n\t // if we have no href url, then don't navigate anywhere.\n\t if (!element.attr(href)) {\n\t event.preventDefault();\n\t }\n\t });\n\t };\n\t }\n\t }\n\t});\n\t\n\t/**\n\t * @ngdoc directive\n\t * @name ngHref\n\t * @restrict A\n\t * @priority 99\n\t *\n\t * @description\n\t * Using Angular markup like `{{hash}}` in an href attribute will\n\t * make the link go to the wrong URL if the user clicks it before\n\t * Angular has a chance to replace the `{{hash}}` markup with its\n\t * value. Until Angular replaces the markup the link will be broken\n\t * and will most likely return a 404 error. The `ngHref` directive\n\t * solves this problem.\n\t *\n\t * The wrong way to write it:\n\t * ```html\n\t * link1\n\t * ```\n\t *\n\t * The correct way to write it:\n\t * ```html\n\t * link1\n\t * ```\n\t *\n\t * @element A\n\t * @param {template} ngHref any string which can contain `{{}}` markup.\n\t *\n\t * @example\n\t * This example shows various combinations of `href`, `ng-href` and `ng-click` attributes\n\t * in links and their different behaviors:\n\t \n\t \n\t
\n\t link 1 (link, don't reload)
\n\t link 2 (link, don't reload)
\n\t link 3 (link, reload!)
\n\t anchor (link, don't reload)
\n\t anchor (no link)
\n\t link (link, change location)\n\t
\n\t \n\t it('should execute ng-click but not reload when href without value', function() {\n\t element(by.id('link-1')).click();\n\t expect(element(by.model('value')).getAttribute('value')).toEqual('1');\n\t expect(element(by.id('link-1')).getAttribute('href')).toBe('');\n\t });\n\t\n\t it('should execute ng-click but not reload when href empty string', function() {\n\t element(by.id('link-2')).click();\n\t expect(element(by.model('value')).getAttribute('value')).toEqual('2');\n\t expect(element(by.id('link-2')).getAttribute('href')).toBe('');\n\t });\n\t\n\t it('should execute ng-click and change url when ng-href specified', function() {\n\t expect(element(by.id('link-3')).getAttribute('href')).toMatch(/\\/123$/);\n\t\n\t element(by.id('link-3')).click();\n\t\n\t // At this point, we navigate away from an Angular page, so we need\n\t // to use browser.driver to get the base webdriver.\n\t\n\t browser.wait(function() {\n\t return browser.driver.getCurrentUrl().then(function(url) {\n\t return url.match(/\\/123$/);\n\t });\n\t }, 5000, 'page should navigate to /123');\n\t });\n\t\n\t it('should execute ng-click but not reload when href empty string and name specified', function() {\n\t element(by.id('link-4')).click();\n\t expect(element(by.model('value')).getAttribute('value')).toEqual('4');\n\t expect(element(by.id('link-4')).getAttribute('href')).toBe('');\n\t });\n\t\n\t it('should execute ng-click but not reload when no href but name specified', function() {\n\t element(by.id('link-5')).click();\n\t expect(element(by.model('value')).getAttribute('value')).toEqual('5');\n\t expect(element(by.id('link-5')).getAttribute('href')).toBe(null);\n\t });\n\t\n\t it('should only change url when only ng-href', function() {\n\t element(by.model('value')).clear();\n\t element(by.model('value')).sendKeys('6');\n\t expect(element(by.id('link-6')).getAttribute('href')).toMatch(/\\/6$/);\n\t\n\t element(by.id('link-6')).click();\n\t\n\t // At this point, we navigate away from an Angular page, so we need\n\t // to use browser.driver to get the base webdriver.\n\t browser.wait(function() {\n\t return browser.driver.getCurrentUrl().then(function(url) {\n\t return url.match(/\\/6$/);\n\t });\n\t }, 5000, 'page should navigate to /6');\n\t });\n\t \n\t
\n\t */\n\t\n\t/**\n\t * @ngdoc directive\n\t * @name ngSrc\n\t * @restrict A\n\t * @priority 99\n\t *\n\t * @description\n\t * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n\t * work right: The browser will fetch from the URL with the literal\n\t * text `{{hash}}` until Angular replaces the expression inside\n\t * `{{hash}}`. The `ngSrc` directive solves this problem.\n\t *\n\t * The buggy way to write it:\n\t * ```html\n\t * \"Description\"/\n\t * ```\n\t *\n\t * The correct way to write it:\n\t * ```html\n\t * \"Description\"\n\t * ```\n\t *\n\t * @element IMG\n\t * @param {template} ngSrc any string which can contain `{{}}` markup.\n\t */\n\t\n\t/**\n\t * @ngdoc directive\n\t * @name ngSrcset\n\t * @restrict A\n\t * @priority 99\n\t *\n\t * @description\n\t * Using Angular markup like `{{hash}}` in a `srcset` attribute doesn't\n\t * work right: The browser will fetch from the URL with the literal\n\t * text `{{hash}}` until Angular replaces the expression inside\n\t * `{{hash}}`. The `ngSrcset` directive solves this problem.\n\t *\n\t * The buggy way to write it:\n\t * ```html\n\t * \"Description\"/\n\t * ```\n\t *\n\t * The correct way to write it:\n\t * ```html\n\t * \"Description\"\n\t * ```\n\t *\n\t * @element IMG\n\t * @param {template} ngSrcset any string which can contain `{{}}` markup.\n\t */\n\t\n\t/**\n\t * @ngdoc directive\n\t * @name ngDisabled\n\t * @restrict A\n\t * @priority 100\n\t *\n\t * @description\n\t *\n\t * This directive sets the `disabled` attribute on the element if the\n\t * {@link guide/expression expression} inside `ngDisabled` evaluates to truthy.\n\t *\n\t * A special directive is necessary because we cannot use interpolation inside the `disabled`\n\t * attribute. See the {@link guide/interpolation interpolation guide} for more info.\n\t *\n\t * @example\n\t \n\t \n\t
\n\t \n\t
\n\t \n\t it('should toggle button', function() {\n\t expect(element(by.css('button')).getAttribute('disabled')).toBeFalsy();\n\t element(by.model('checked')).click();\n\t expect(element(by.css('button')).getAttribute('disabled')).toBeTruthy();\n\t });\n\t \n\t
\n\t *\n\t * @element INPUT\n\t * @param {expression} ngDisabled If the {@link guide/expression expression} is truthy,\n\t * then the `disabled` attribute will be set on the element\n\t */\n\t\n\t\n\t/**\n\t * @ngdoc directive\n\t * @name ngChecked\n\t * @restrict A\n\t * @priority 100\n\t *\n\t * @description\n\t * Sets the `checked` attribute on the element, if the expression inside `ngChecked` is truthy.\n\t *\n\t * Note that this directive should not be used together with {@link ngModel `ngModel`},\n\t * as this can lead to unexpected behavior.\n\t *\n\t * A special directive is necessary because we cannot use interpolation inside the `checked`\n\t * attribute. See the {@link guide/interpolation interpolation guide} for more info.\n\t *\n\t * @example\n\t \n\t \n\t
\n\t \n\t
\n\t \n\t it('should check both checkBoxes', function() {\n\t expect(element(by.id('checkSlave')).getAttribute('checked')).toBeFalsy();\n\t element(by.model('master')).click();\n\t expect(element(by.id('checkSlave')).getAttribute('checked')).toBeTruthy();\n\t });\n\t \n\t
\n\t *\n\t * @element INPUT\n\t * @param {expression} ngChecked If the {@link guide/expression expression} is truthy,\n\t * then the `checked` attribute will be set on the element\n\t */\n\t\n\t\n\t/**\n\t * @ngdoc directive\n\t * @name ngReadonly\n\t * @restrict A\n\t * @priority 100\n\t *\n\t * @description\n\t *\n\t * Sets the `readonly` attribute on the element, if the expression inside `ngReadonly` is truthy.\n\t * Note that `readonly` applies only to `input` elements with specific types. [See the input docs on\n\t * MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-readonly) for more information.\n\t *\n\t * A special directive is necessary because we cannot use interpolation inside the `readonly`\n\t * attribute. See the {@link guide/interpolation interpolation guide} for more info.\n\t *\n\t * @example\n\t \n\t \n\t
\n\t \n\t
\n\t \n\t it('should toggle readonly attr', function() {\n\t expect(element(by.css('[type=\"text\"]')).getAttribute('readonly')).toBeFalsy();\n\t element(by.model('checked')).click();\n\t expect(element(by.css('[type=\"text\"]')).getAttribute('readonly')).toBeTruthy();\n\t });\n\t \n\t
\n\t *\n\t * @element INPUT\n\t * @param {expression} ngReadonly If the {@link guide/expression expression} is truthy,\n\t * then special attribute \"readonly\" will be set on the element\n\t */\n\t\n\t\n\t/**\n\t * @ngdoc directive\n\t * @name ngSelected\n\t * @restrict A\n\t * @priority 100\n\t *\n\t * @description\n\t *\n\t * Sets the `selected` attribute on the element, if the expression inside `ngSelected` is truthy.\n\t *\n\t * A special directive is necessary because we cannot use interpolation inside the `selected`\n\t * attribute. See the {@link guide/interpolation interpolation guide} for more info.\n\t *\n\t *
\n\t * **Note:** `ngSelected` does not interact with the `select` and `ngModel` directives, it only\n\t * sets the `selected` attribute on the element. If you are using `ngModel` on the select, you\n\t * should not use `ngSelected` on the options, as `ngModel` will set the select value and\n\t * selected options.\n\t *
\n\t *\n\t * @example\n\t \n\t \n\t
\n\t \n\t
\n\t \n\t it('should select Greetings!', function() {\n\t expect(element(by.id('greet')).getAttribute('selected')).toBeFalsy();\n\t element(by.model('selected')).click();\n\t expect(element(by.id('greet')).getAttribute('selected')).toBeTruthy();\n\t });\n\t \n\t
\n\t *\n\t * @element OPTION\n\t * @param {expression} ngSelected If the {@link guide/expression expression} is truthy,\n\t * then special attribute \"selected\" will be set on the element\n\t */\n\t\n\t/**\n\t * @ngdoc directive\n\t * @name ngOpen\n\t * @restrict A\n\t * @priority 100\n\t *\n\t * @description\n\t *\n\t * Sets the `open` attribute on the element, if the expression inside `ngOpen` is truthy.\n\t *\n\t * A special directive is necessary because we cannot use interpolation inside the `open`\n\t * attribute. See the {@link guide/interpolation interpolation guide} for more info.\n\t *\n\t * ## A note about browser compatibility\n\t *\n\t * Edge, Firefox, and Internet Explorer do not support the `details` element, it is\n\t * recommended to use {@link ng.ngShow} and {@link ng.ngHide} instead.\n\t *\n\t * @example\n\t \n\t \n\t
\n\t
\n\t Show/Hide me\n\t
\n\t
\n\t \n\t it('should toggle open', function() {\n\t expect(element(by.id('details')).getAttribute('open')).toBeFalsy();\n\t element(by.model('open')).click();\n\t expect(element(by.id('details')).getAttribute('open')).toBeTruthy();\n\t });\n\t \n\t
\n\t *\n\t * @element DETAILS\n\t * @param {expression} ngOpen If the {@link guide/expression expression} is truthy,\n\t * then special attribute \"open\" will be set on the element\n\t */\n\t\n\tvar ngAttributeAliasDirectives = {};\n\t\n\t// boolean attrs are evaluated\n\tforEach(BOOLEAN_ATTR, function(propName, attrName) {\n\t // binding to multiple is not supported\n\t if (propName == \"multiple\") return;\n\t\n\t function defaultLinkFn(scope, element, attr) {\n\t scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n\t attr.$set(attrName, !!value);\n\t });\n\t }\n\t\n\t var normalized = directiveNormalize('ng-' + attrName);\n\t var linkFn = defaultLinkFn;\n\t\n\t if (propName === 'checked') {\n\t linkFn = function(scope, element, attr) {\n\t // ensuring ngChecked doesn't interfere with ngModel when both are set on the same input\n\t if (attr.ngModel !== attr[normalized]) {\n\t defaultLinkFn(scope, element, attr);\n\t }\n\t };\n\t }\n\t\n\t ngAttributeAliasDirectives[normalized] = function() {\n\t return {\n\t restrict: 'A',\n\t priority: 100,\n\t link: linkFn\n\t };\n\t };\n\t});\n\t\n\t// aliased input attrs are evaluated\n\tforEach(ALIASED_ATTR, function(htmlAttr, ngAttr) {\n\t ngAttributeAliasDirectives[ngAttr] = function() {\n\t return {\n\t priority: 100,\n\t link: function(scope, element, attr) {\n\t //special case ngPattern when a literal regular expression value\n\t //is used as the expression (this way we don't have to watch anything).\n\t if (ngAttr === \"ngPattern\" && attr.ngPattern.charAt(0) == \"/\") {\n\t var match = attr.ngPattern.match(REGEX_STRING_REGEXP);\n\t if (match) {\n\t attr.$set(\"ngPattern\", new RegExp(match[1], match[2]));\n\t return;\n\t }\n\t }\n\t\n\t scope.$watch(attr[ngAttr], function ngAttrAliasWatchAction(value) {\n\t attr.$set(ngAttr, value);\n\t });\n\t }\n\t };\n\t };\n\t});\n\t\n\t// ng-src, ng-srcset, ng-href are interpolated\n\tforEach(['src', 'srcset', 'href'], function(attrName) {\n\t var normalized = directiveNormalize('ng-' + attrName);\n\t ngAttributeAliasDirectives[normalized] = function() {\n\t return {\n\t priority: 99, // it needs to run after the attributes are interpolated\n\t link: function(scope, element, attr) {\n\t var propName = attrName,\n\t name = attrName;\n\t\n\t if (attrName === 'href' &&\n\t toString.call(element.prop('href')) === '[object SVGAnimatedString]') {\n\t name = 'xlinkHref';\n\t attr.$attr[name] = 'xlink:href';\n\t propName = null;\n\t }\n\t\n\t attr.$observe(normalized, function(value) {\n\t if (!value) {\n\t if (attrName === 'href') {\n\t attr.$set(name, null);\n\t }\n\t return;\n\t }\n\t\n\t attr.$set(name, value);\n\t\n\t // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n\t // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n\t // to set the property as well to achieve the desired effect.\n\t // we use attr[attrName] value since $set can sanitize the url.\n\t if (msie && propName) element.prop(propName, attr[name]);\n\t });\n\t }\n\t };\n\t };\n\t});\n\t\n\t/* global -nullFormCtrl, -SUBMITTED_CLASS, addSetValidityMethod: true\n\t */\n\tvar nullFormCtrl = {\n\t $addControl: noop,\n\t $$renameControl: nullFormRenameControl,\n\t $removeControl: noop,\n\t $setValidity: noop,\n\t $setDirty: noop,\n\t $setPristine: noop,\n\t $setSubmitted: noop\n\t},\n\tSUBMITTED_CLASS = 'ng-submitted';\n\t\n\tfunction nullFormRenameControl(control, name) {\n\t control.$name = name;\n\t}\n\t\n\t/**\n\t * @ngdoc type\n\t * @name form.FormController\n\t *\n\t * @property {boolean} $pristine True if user has not interacted with the form yet.\n\t * @property {boolean} $dirty True if user has already interacted with the form.\n\t * @property {boolean} $valid True if all of the containing forms and controls are valid.\n\t * @property {boolean} $invalid True if at least one containing control or form is invalid.\n\t * @property {boolean} $pending True if at least one containing control or form is pending.\n\t * @property {boolean} $submitted True if user has submitted the form even if its invalid.\n\t *\n\t * @property {Object} $error Is an object hash, containing references to controls or\n\t * forms with failing validators, where:\n\t *\n\t * - keys are validation tokens (error names),\n\t * - values are arrays of controls or forms that have a failing validator for given error name.\n\t *\n\t * Built-in validation tokens:\n\t *\n\t * - `email`\n\t * - `max`\n\t * - `maxlength`\n\t * - `min`\n\t * - `minlength`\n\t * - `number`\n\t * - `pattern`\n\t * - `required`\n\t * - `url`\n\t * - `date`\n\t * - `datetimelocal`\n\t * - `time`\n\t * - `week`\n\t * - `month`\n\t *\n\t * @description\n\t * `FormController` keeps track of all its controls and nested forms as well as the state of them,\n\t * such as being valid/invalid or dirty/pristine.\n\t *\n\t * Each {@link ng.directive:form form} directive creates an instance\n\t * of `FormController`.\n\t *\n\t */\n\t//asks for $scope to fool the BC controller module\n\tFormController.$inject = ['$element', '$attrs', '$scope', '$animate', '$interpolate'];\n\tfunction FormController(element, attrs, $scope, $animate, $interpolate) {\n\t var form = this,\n\t controls = [];\n\t\n\t // init state\n\t form.$error = {};\n\t form.$$success = {};\n\t form.$pending = undefined;\n\t form.$name = $interpolate(attrs.name || attrs.ngForm || '')($scope);\n\t form.$dirty = false;\n\t form.$pristine = true;\n\t form.$valid = true;\n\t form.$invalid = false;\n\t form.$submitted = false;\n\t form.$$parentForm = nullFormCtrl;\n\t\n\t /**\n\t * @ngdoc method\n\t * @name form.FormController#$rollbackViewValue\n\t *\n\t * @description\n\t * Rollback all form controls pending updates to the `$modelValue`.\n\t *\n\t * Updates may be pending by a debounced event or because the input is waiting for a some future\n\t * event defined in `ng-model-options`. This method is typically needed by the reset button of\n\t * a form that uses `ng-model-options` to pend updates.\n\t */\n\t form.$rollbackViewValue = function() {\n\t forEach(controls, function(control) {\n\t control.$rollbackViewValue();\n\t });\n\t };\n\t\n\t /**\n\t * @ngdoc method\n\t * @name form.FormController#$commitViewValue\n\t *\n\t * @description\n\t * Commit all form controls pending updates to the `$modelValue`.\n\t *\n\t * Updates may be pending by a debounced event or because the input is waiting for a some future\n\t * event defined in `ng-model-options`. This method is rarely needed as `NgModelController`\n\t * usually handles calling this in response to input events.\n\t */\n\t form.$commitViewValue = function() {\n\t forEach(controls, function(control) {\n\t control.$commitViewValue();\n\t });\n\t };\n\t\n\t /**\n\t * @ngdoc method\n\t * @name form.FormController#$addControl\n\t * @param {object} control control object, either a {@link form.FormController} or an\n\t * {@link ngModel.NgModelController}\n\t *\n\t * @description\n\t * Register a control with the form. Input elements using ngModelController do this automatically\n\t * when they are linked.\n\t *\n\t * Note that the current state of the control will not be reflected on the new parent form. This\n\t * is not an issue with normal use, as freshly compiled and linked controls are in a `$pristine`\n\t * state.\n\t *\n\t * However, if the method is used programmatically, for example by adding dynamically created controls,\n\t * or controls that have been previously removed without destroying their corresponding DOM element,\n\t * it's the developers responsibility to make sure the current state propagates to the parent form.\n\t *\n\t * For example, if an input control is added that is already `$dirty` and has `$error` properties,\n\t * calling `$setDirty()` and `$validate()` afterwards will propagate the state to the parent form.\n\t */\n\t form.$addControl = function(control) {\n\t // Breaking change - before, inputs whose name was \"hasOwnProperty\" were quietly ignored\n\t // and not added to the scope. Now we throw an error.\n\t assertNotHasOwnProperty(control.$name, 'input');\n\t controls.push(control);\n\t\n\t if (control.$name) {\n\t form[control.$name] = control;\n\t }\n\t\n\t control.$$parentForm = form;\n\t };\n\t\n\t // Private API: rename a form control\n\t form.$$renameControl = function(control, newName) {\n\t var oldName = control.$name;\n\t\n\t if (form[oldName] === control) {\n\t delete form[oldName];\n\t }\n\t form[newName] = control;\n\t control.$name = newName;\n\t };\n\t\n\t /**\n\t * @ngdoc method\n\t * @name form.FormController#$removeControl\n\t * @param {object} control control object, either a {@link form.FormController} or an\n\t * {@link ngModel.NgModelController}\n\t *\n\t * @description\n\t * Deregister a control from the form.\n\t *\n\t * Input elements using ngModelController do this automatically when they are destroyed.\n\t *\n\t * Note that only the removed control's validation state (`$errors`etc.) will be removed from the\n\t * form. `$dirty`, `$submitted` states will not be changed, because the expected behavior can be\n\t * different from case to case. For example, removing the only `$dirty` control from a form may or\n\t * may not mean that the form is still `$dirty`.\n\t */\n\t form.$removeControl = function(control) {\n\t if (control.$name && form[control.$name] === control) {\n\t delete form[control.$name];\n\t }\n\t forEach(form.$pending, function(value, name) {\n\t form.$setValidity(name, null, control);\n\t });\n\t forEach(form.$error, function(value, name) {\n\t form.$setValidity(name, null, control);\n\t });\n\t forEach(form.$$success, function(value, name) {\n\t form.$setValidity(name, null, control);\n\t });\n\t\n\t arrayRemove(controls, control);\n\t control.$$parentForm = nullFormCtrl;\n\t };\n\t\n\t\n\t /**\n\t * @ngdoc method\n\t * @name form.FormController#$setValidity\n\t *\n\t * @description\n\t * Sets the validity of a form control.\n\t *\n\t * This method will also propagate to parent forms.\n\t */\n\t addSetValidityMethod({\n\t ctrl: this,\n\t $element: element,\n\t set: function(object, property, controller) {\n\t var list = object[property];\n\t if (!list) {\n\t object[property] = [controller];\n\t } else {\n\t var index = list.indexOf(controller);\n\t if (index === -1) {\n\t list.push(controller);\n\t }\n\t }\n\t },\n\t unset: function(object, property, controller) {\n\t var list = object[property];\n\t if (!list) {\n\t return;\n\t }\n\t arrayRemove(list, controller);\n\t if (list.length === 0) {\n\t delete object[property];\n\t }\n\t },\n\t $animate: $animate\n\t });\n\t\n\t /**\n\t * @ngdoc method\n\t * @name form.FormController#$setDirty\n\t *\n\t * @description\n\t * Sets the form to a dirty state.\n\t *\n\t * This method can be called to add the 'ng-dirty' class and set the form to a dirty\n\t * state (ng-dirty class). This method will also propagate to parent forms.\n\t */\n\t form.$setDirty = function() {\n\t $animate.removeClass(element, PRISTINE_CLASS);\n\t $animate.addClass(element, DIRTY_CLASS);\n\t form.$dirty = true;\n\t form.$pristine = false;\n\t form.$$parentForm.$setDirty();\n\t };\n\t\n\t /**\n\t * @ngdoc method\n\t * @name form.FormController#$setPristine\n\t *\n\t * @description\n\t * Sets the form to its pristine state.\n\t *\n\t * This method can be called to remove the 'ng-dirty' class and set the form to its pristine\n\t * state (ng-pristine class). This method will also propagate to all the controls contained\n\t * in this form.\n\t *\n\t * Setting a form back to a pristine state is often useful when we want to 'reuse' a form after\n\t * saving or resetting it.\n\t */\n\t form.$setPristine = function() {\n\t $animate.setClass(element, PRISTINE_CLASS, DIRTY_CLASS + ' ' + SUBMITTED_CLASS);\n\t form.$dirty = false;\n\t form.$pristine = true;\n\t form.$submitted = false;\n\t forEach(controls, function(control) {\n\t control.$setPristine();\n\t });\n\t };\n\t\n\t /**\n\t * @ngdoc method\n\t * @name form.FormController#$setUntouched\n\t *\n\t * @description\n\t * Sets the form to its untouched state.\n\t *\n\t * This method can be called to remove the 'ng-touched' class and set the form controls to their\n\t * untouched state (ng-untouched class).\n\t *\n\t * Setting a form controls back to their untouched state is often useful when setting the form\n\t * back to its pristine state.\n\t */\n\t form.$setUntouched = function() {\n\t forEach(controls, function(control) {\n\t control.$setUntouched();\n\t });\n\t };\n\t\n\t /**\n\t * @ngdoc method\n\t * @name form.FormController#$setSubmitted\n\t *\n\t * @description\n\t * Sets the form to its submitted state.\n\t */\n\t form.$setSubmitted = function() {\n\t $animate.addClass(element, SUBMITTED_CLASS);\n\t form.$submitted = true;\n\t form.$$parentForm.$setSubmitted();\n\t };\n\t}\n\t\n\t/**\n\t * @ngdoc directive\n\t * @name ngForm\n\t * @restrict EAC\n\t *\n\t * @description\n\t * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n\t * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n\t * sub-group of controls needs to be determined.\n\t *\n\t * Note: the purpose of `ngForm` is to group controls,\n\t * but not to be a replacement for the `
` tag with all of its capabilities\n\t * (e.g. posting to the server, ...).\n\t *\n\t * @param {string=} ngForm|name Name of the form. If specified, the form controller will be published into\n\t * related scope, under this name.\n\t *\n\t */\n\t\n\t /**\n\t * @ngdoc directive\n\t * @name form\n\t * @restrict E\n\t *\n\t * @description\n\t * Directive that instantiates\n\t * {@link form.FormController FormController}.\n\t *\n\t * If the `name` attribute is specified, the form controller is published onto the current scope under\n\t * this name.\n\t *\n\t * # Alias: {@link ng.directive:ngForm `ngForm`}\n\t *\n\t * In Angular, forms can be nested. This means that the outer form is valid when all of the child\n\t * forms are valid as well. However, browsers do not allow nesting of `` elements, so\n\t * Angular provides the {@link ng.directive:ngForm `ngForm`} directive, which behaves identically to\n\t * `form` but can be nested. Nested forms can be useful, for example, if the validity of a sub-group\n\t * of controls needs to be determined.\n\t *\n\t * # CSS classes\n\t * - `ng-valid` is set if the form is valid.\n\t * - `ng-invalid` is set if the form is invalid.\n\t * - `ng-pending` is set if the form is pending.\n\t * - `ng-pristine` is set if the form is pristine.\n\t * - `ng-dirty` is set if the form is dirty.\n\t * - `ng-submitted` is set if the form was submitted.\n\t *\n\t * Keep in mind that ngAnimate can detect each of these classes when added and removed.\n\t *\n\t *\n\t * # Submitting a form and preventing the default action\n\t *\n\t * Since the role of forms in client-side Angular applications is different than in classical\n\t * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n\t * page reload that sends the data to the server. Instead some javascript logic should be triggered\n\t * to handle the form submission in an application-specific way.\n\t *\n\t * For this reason, Angular prevents the default action (form submission to the server) unless the\n\t * `` element has an `action` attribute specified.\n\t *\n\t * You can use one of the following two ways to specify what javascript method should be called when\n\t * a form is submitted:\n\t *\n\t * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n\t * - {@link ng.directive:ngClick ngClick} directive on the first\n\t * button or input field of type submit (input[type=submit])\n\t *\n\t * To prevent double execution of the handler, use only one of the {@link ng.directive:ngSubmit ngSubmit}\n\t * or {@link ng.directive:ngClick ngClick} directives.\n\t * This is because of the following form submission rules in the HTML specification:\n\t *\n\t * - If a form has only one input field then hitting enter in this field triggers form submit\n\t * (`ngSubmit`)\n\t * - if a form has 2+ input fields and no buttons or input[type=submit] then hitting enter\n\t * doesn't trigger submit\n\t * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n\t * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n\t * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n\t *\n\t * Any pending `ngModelOptions` changes will take place immediately when an enclosing form is\n\t * submitted. Note that `ngClick` events will occur before the model is updated. Use `ngSubmit`\n\t * to have access to the updated model.\n\t *\n\t * ## Animation Hooks\n\t *\n\t * Animations in ngForm are triggered when any of the associated CSS classes are added and removed.\n\t * These classes are: `.ng-pristine`, `.ng-dirty`, `.ng-invalid` and `.ng-valid` as well as any\n\t * other validations that are performed within the form. Animations in ngForm are similar to how\n\t * they work in ngClass and animations can be hooked into using CSS transitions, keyframes as well\n\t * as JS animations.\n\t *\n\t * The following example shows a simple way to utilize CSS transitions to style a form element\n\t * that has been rendered as invalid after it has been validated:\n\t *\n\t *
\n\t * //be sure to include ngAnimate as a module to hook into more\n\t * //advanced animations\n\t * .my-form {\n\t *   transition:0.5s linear all;\n\t *   background: white;\n\t * }\n\t * .my-form.ng-invalid {\n\t *   background: red;\n\t *   color:white;\n\t * }\n\t * 
\n\t *\n\t * @example\n\t \n\t \n\t \n\t \n\t \n\t userType: \n\t Required!
\n\t userType = {{userType}}
\n\t myForm.input.$valid = {{myForm.input.$valid}}
\n\t myForm.input.$error = {{myForm.input.$error}}
\n\t myForm.$valid = {{myForm.$valid}}
\n\t myForm.$error.required = {{!!myForm.$error.required}}
\n\t \n\t
\n\t \n\t it('should initialize to model', function() {\n\t var userType = element(by.binding('userType'));\n\t var valid = element(by.binding('myForm.input.$valid'));\n\t\n\t expect(userType.getText()).toContain('guest');\n\t expect(valid.getText()).toContain('true');\n\t });\n\t\n\t it('should be invalid if empty', function() {\n\t var userType = element(by.binding('userType'));\n\t var valid = element(by.binding('myForm.input.$valid'));\n\t var userInput = element(by.model('userType'));\n\t\n\t userInput.clear();\n\t userInput.sendKeys('');\n\t\n\t expect(userType.getText()).toEqual('userType =');\n\t expect(valid.getText()).toContain('false');\n\t });\n\t \n\t
\n\t *\n\t * @param {string=} name Name of the form. If specified, the form controller will be published into\n\t * related scope, under this name.\n\t */\n\tvar formDirectiveFactory = function(isNgForm) {\n\t return ['$timeout', '$parse', function($timeout, $parse) {\n\t var formDirective = {\n\t name: 'form',\n\t restrict: isNgForm ? 'EAC' : 'E',\n\t require: ['form', '^^?form'], //first is the form's own ctrl, second is an optional parent form\n\t controller: FormController,\n\t compile: function ngFormCompile(formElement, attr) {\n\t // Setup initial state of the control\n\t formElement.addClass(PRISTINE_CLASS).addClass(VALID_CLASS);\n\t\n\t var nameAttr = attr.name ? 'name' : (isNgForm && attr.ngForm ? 'ngForm' : false);\n\t\n\t return {\n\t pre: function ngFormPreLink(scope, formElement, attr, ctrls) {\n\t var controller = ctrls[0];\n\t\n\t // if `action` attr is not present on the form, prevent the default action (submission)\n\t if (!('action' in attr)) {\n\t // we can't use jq events because if a form is destroyed during submission the default\n\t // action is not prevented. see #1238\n\t //\n\t // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n\t // page reload if the form was destroyed by submission of the form via a click handler\n\t // on a button in the form. Looks like an IE9 specific bug.\n\t var handleFormSubmission = function(event) {\n\t scope.$apply(function() {\n\t controller.$commitViewValue();\n\t controller.$setSubmitted();\n\t });\n\t\n\t event.preventDefault();\n\t };\n\t\n\t addEventListenerFn(formElement[0], 'submit', handleFormSubmission);\n\t\n\t // unregister the preventDefault listener so that we don't not leak memory but in a\n\t // way that will achieve the prevention of the default action.\n\t formElement.on('$destroy', function() {\n\t $timeout(function() {\n\t removeEventListenerFn(formElement[0], 'submit', handleFormSubmission);\n\t }, 0, false);\n\t });\n\t }\n\t\n\t var parentFormCtrl = ctrls[1] || controller.$$parentForm;\n\t parentFormCtrl.$addControl(controller);\n\t\n\t var setter = nameAttr ? getSetter(controller.$name) : noop;\n\t\n\t if (nameAttr) {\n\t setter(scope, controller);\n\t attr.$observe(nameAttr, function(newValue) {\n\t if (controller.$name === newValue) return;\n\t setter(scope, undefined);\n\t controller.$$parentForm.$$renameControl(controller, newValue);\n\t setter = getSetter(controller.$name);\n\t setter(scope, controller);\n\t });\n\t }\n\t formElement.on('$destroy', function() {\n\t controller.$$parentForm.$removeControl(controller);\n\t setter(scope, undefined);\n\t extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n\t });\n\t }\n\t };\n\t }\n\t };\n\t\n\t return formDirective;\n\t\n\t function getSetter(expression) {\n\t if (expression === '') {\n\t //create an assignable expression, so forms with an empty name can be renamed later\n\t return $parse('this[\"\"]').assign;\n\t }\n\t return $parse(expression).assign || noop;\n\t }\n\t }];\n\t};\n\t\n\tvar formDirective = formDirectiveFactory();\n\tvar ngFormDirective = formDirectiveFactory(true);\n\t\n\t/* global VALID_CLASS: false,\n\t INVALID_CLASS: false,\n\t PRISTINE_CLASS: false,\n\t DIRTY_CLASS: false,\n\t UNTOUCHED_CLASS: false,\n\t TOUCHED_CLASS: false,\n\t ngModelMinErr: false,\n\t*/\n\t\n\t// Regex code was initially obtained from SO prior to modification: https://stackoverflow.com/questions/3143070/javascript-regex-iso-datetime#answer-3143231\n\tvar ISO_DATE_REGEXP = /^\\d{4,}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d+(?:[+-][0-2]\\d:[0-5]\\d|Z)$/;\n\t// See valid URLs in RFC3987 (http://tools.ietf.org/html/rfc3987)\n\t// Note: We are being more lenient, because browsers are too.\n\t// 1. Scheme\n\t// 2. Slashes\n\t// 3. Username\n\t// 4. Password\n\t// 5. Hostname\n\t// 6. Port\n\t// 7. Path\n\t// 8. Query\n\t// 9. Fragment\n\t// 1111111111111111 222 333333 44444 555555555555555555555555 666 77777777 8888888 999\n\tvar URL_REGEXP = /^[a-z][a-z\\d.+-]*:\\/*(?:[^:@]+(?::[^@]+)?@)?(?:[^\\s:/?#]+|\\[[a-f\\d:]+\\])(?::\\d+)?(?:\\/[^?#]*)?(?:\\?[^#]*)?(?:#.*)?$/i;\n\t/* jshint maxlen:220 */\n\tvar EMAIL_REGEXP = /^(?=.{1,254}$)(?=.{1,64}@)[-!#$%&'*+\\/0-9=?A-Z^_`a-z{|}~]+(\\.[-!#$%&'*+\\/0-9=?A-Z^_`a-z{|}~]+)*@[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$/;\n\t/* jshint maxlen:200 */\n\tvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))([eE][+-]?\\d+)?\\s*$/;\n\tvar DATE_REGEXP = /^(\\d{4,})-(\\d{2})-(\\d{2})$/;\n\tvar DATETIMELOCAL_REGEXP = /^(\\d{4,})-(\\d\\d)-(\\d\\d)T(\\d\\d):(\\d\\d)(?::(\\d\\d)(\\.\\d{1,3})?)?$/;\n\tvar WEEK_REGEXP = /^(\\d{4,})-W(\\d\\d)$/;\n\tvar MONTH_REGEXP = /^(\\d{4,})-(\\d\\d)$/;\n\tvar TIME_REGEXP = /^(\\d\\d):(\\d\\d)(?::(\\d\\d)(\\.\\d{1,3})?)?$/;\n\t\n\tvar PARTIAL_VALIDATION_EVENTS = 'keydown wheel mousedown';\n\tvar PARTIAL_VALIDATION_TYPES = createMap();\n\tforEach('date,datetime-local,month,time,week'.split(','), function(type) {\n\t PARTIAL_VALIDATION_TYPES[type] = true;\n\t});\n\t\n\tvar inputType = {\n\t\n\t /**\n\t * @ngdoc input\n\t * @name input[text]\n\t *\n\t * @description\n\t * Standard HTML text input with angular data binding, inherited by most of the `input` elements.\n\t *\n\t *\n\t * @param {string} ngModel Assignable angular expression to data-bind to.\n\t * @param {string=} name Property name of the form under which the control is published.\n\t * @param {string=} required Adds `required` validation error key if the value is not entered.\n\t * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n\t * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n\t * `required` when you want to data-bind to the `required` attribute.\n\t * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n\t * minlength.\n\t * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n\t * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of\n\t * any length.\n\t * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string\n\t * that contains the regular expression body that will be converted to a regular expression\n\t * as in the ngPattern directive.\n\t * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue}\n\t * does not match a RegExp found by evaluating the Angular expression given in the attribute value.\n\t * If the expression evaluates to a RegExp object, then this is used directly.\n\t * If the expression evaluates to a string, then it will be converted to a RegExp\n\t * after wrapping it in `^` and `$` characters. For instance, `\"abc\"` will be converted to\n\t * `new RegExp('^abc$')`.
\n\t * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to\n\t * start at the index of the last search's match, thus not taking the whole input value into\n\t * account.\n\t * @param {string=} ngChange Angular expression to be executed when input changes due to user\n\t * interaction with the input element.\n\t * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.\n\t * This parameter is ignored for input[type=password] controls, which will never trim the\n\t * input.\n\t *\n\t * @example\n\t \n\t \n\t \n\t
\n\t \n\t
\n\t \n\t Required!\n\t \n\t Single word only!\n\t
\n\t text = {{example.text}}
\n\t myForm.input.$valid = {{myForm.input.$valid}}
\n\t myForm.input.$error = {{myForm.input.$error}}
\n\t myForm.$valid = {{myForm.$valid}}
\n\t myForm.$error.required = {{!!myForm.$error.required}}
\n\t
\n\t
\n\t \n\t var text = element(by.binding('example.text'));\n\t var valid = element(by.binding('myForm.input.$valid'));\n\t var input = element(by.model('example.text'));\n\t\n\t it('should initialize to model', function() {\n\t expect(text.getText()).toContain('guest');\n\t expect(valid.getText()).toContain('true');\n\t });\n\t\n\t it('should be invalid if empty', function() {\n\t input.clear();\n\t input.sendKeys('');\n\t\n\t expect(text.getText()).toEqual('text =');\n\t expect(valid.getText()).toContain('false');\n\t });\n\t\n\t it('should be invalid if multi word', function() {\n\t input.clear();\n\t input.sendKeys('hello world');\n\t\n\t expect(valid.getText()).toContain('false');\n\t });\n\t \n\t
\n\t */\n\t 'text': textInputType,\n\t\n\t /**\n\t * @ngdoc input\n\t * @name input[date]\n\t *\n\t * @description\n\t * Input with date validation and transformation. In browsers that do not yet support\n\t * the HTML5 date input, a text element will be used. In that case, text must be entered in a valid ISO-8601\n\t * date format (yyyy-MM-dd), for example: `2009-01-06`. Since many\n\t * modern browsers do not yet support this input type, it is important to provide cues to users on the\n\t * expected input format via a placeholder or label.\n\t *\n\t * The model must always be a Date object, otherwise Angular will throw an error.\n\t * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.\n\t *\n\t * The timezone to be used to read/write the `Date` instance in the model can be defined using\n\t * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.\n\t *\n\t * @param {string} ngModel Assignable angular expression to data-bind to.\n\t * @param {string=} name Property name of the form under which the control is published.\n\t * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a\n\t * valid ISO date string (yyyy-MM-dd). You can also use interpolation inside this attribute\n\t * (e.g. `min=\"{{minDate | date:'yyyy-MM-dd'}}\"`). Note that `min` will also add native HTML5\n\t * constraint validation.\n\t * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be\n\t * a valid ISO date string (yyyy-MM-dd). You can also use interpolation inside this attribute\n\t * (e.g. `max=\"{{maxDate | date:'yyyy-MM-dd'}}\"`). Note that `max` will also add native HTML5\n\t * constraint validation.\n\t * @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO date string\n\t * the `ngMin` expression evaluates to. Note that it does not set the `min` attribute.\n\t * @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO date string\n\t * the `ngMax` expression evaluates to. Note that it does not set the `max` attribute.\n\t * @param {string=} required Sets `required` validation error key if the value is not entered.\n\t * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n\t * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n\t * `required` when you want to data-bind to the `required` attribute.\n\t * @param {string=} ngChange Angular expression to be executed when input changes due to user\n\t * interaction with the input element.\n\t *\n\t * @example\n\t \n\t \n\t \n\t
\n\t \n\t \n\t
\n\t \n\t Required!\n\t \n\t Not a valid date!\n\t
\n\t value = {{example.value | date: \"yyyy-MM-dd\"}}
\n\t myForm.input.$valid = {{myForm.input.$valid}}
\n\t myForm.input.$error = {{myForm.input.$error}}
\n\t myForm.$valid = {{myForm.$valid}}
\n\t myForm.$error.required = {{!!myForm.$error.required}}
\n\t
\n\t
\n\t \n\t var value = element(by.binding('example.value | date: \"yyyy-MM-dd\"'));\n\t var valid = element(by.binding('myForm.input.$valid'));\n\t var input = element(by.model('example.value'));\n\t\n\t // currently protractor/webdriver does not support\n\t // sending keys to all known HTML5 input controls\n\t // for various browsers (see https://github.com/angular/protractor/issues/562).\n\t function setInput(val) {\n\t // set the value of the element and force validation.\n\t var scr = \"var ipt = document.getElementById('exampleInput'); \" +\n\t \"ipt.value = '\" + val + \"';\" +\n\t \"angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('\" + val + \"'); });\";\n\t browser.executeScript(scr);\n\t }\n\t\n\t it('should initialize to model', function() {\n\t expect(value.getText()).toContain('2013-10-22');\n\t expect(valid.getText()).toContain('myForm.input.$valid = true');\n\t });\n\t\n\t it('should be invalid if empty', function() {\n\t setInput('');\n\t expect(value.getText()).toEqual('value =');\n\t expect(valid.getText()).toContain('myForm.input.$valid = false');\n\t });\n\t\n\t it('should be invalid if over max', function() {\n\t setInput('2015-01-01');\n\t expect(value.getText()).toContain('');\n\t expect(valid.getText()).toContain('myForm.input.$valid = false');\n\t });\n\t \n\t
\n\t */\n\t 'date': createDateInputType('date', DATE_REGEXP,\n\t createDateParser(DATE_REGEXP, ['yyyy', 'MM', 'dd']),\n\t 'yyyy-MM-dd'),\n\t\n\t /**\n\t * @ngdoc input\n\t * @name input[datetime-local]\n\t *\n\t * @description\n\t * Input with datetime validation and transformation. In browsers that do not yet support\n\t * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601\n\t * local datetime format (yyyy-MM-ddTHH:mm:ss), for example: `2010-12-28T14:57:00`.\n\t *\n\t * The model must always be a Date object, otherwise Angular will throw an error.\n\t * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.\n\t *\n\t * The timezone to be used to read/write the `Date` instance in the model can be defined using\n\t * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.\n\t *\n\t * @param {string} ngModel Assignable angular expression to data-bind to.\n\t * @param {string=} name Property name of the form under which the control is published.\n\t * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.\n\t * This must be a valid ISO datetime format (yyyy-MM-ddTHH:mm:ss). You can also use interpolation\n\t * inside this attribute (e.g. `min=\"{{minDatetimeLocal | date:'yyyy-MM-ddTHH:mm:ss'}}\"`).\n\t * Note that `min` will also add native HTML5 constraint validation.\n\t * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.\n\t * This must be a valid ISO datetime format (yyyy-MM-ddTHH:mm:ss). You can also use interpolation\n\t * inside this attribute (e.g. `max=\"{{maxDatetimeLocal | date:'yyyy-MM-ddTHH:mm:ss'}}\"`).\n\t * Note that `max` will also add native HTML5 constraint validation.\n\t * @param {(date|string)=} ngMin Sets the `min` validation error key to the Date / ISO datetime string\n\t * the `ngMin` expression evaluates to. Note that it does not set the `min` attribute.\n\t * @param {(date|string)=} ngMax Sets the `max` validation error key to the Date / ISO datetime string\n\t * the `ngMax` expression evaluates to. Note that it does not set the `max` attribute.\n\t * @param {string=} required Sets `required` validation error key if the value is not entered.\n\t * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n\t * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n\t * `required` when you want to data-bind to the `required` attribute.\n\t * @param {string=} ngChange Angular expression to be executed when input changes due to user\n\t * interaction with the input element.\n\t *\n\t * @example\n\t \n\t \n\t \n\t
\n\t \n\t \n\t
\n\t \n\t Required!\n\t \n\t Not a valid date!\n\t
\n\t value = {{example.value | date: \"yyyy-MM-ddTHH:mm:ss\"}}
\n\t myForm.input.$valid = {{myForm.input.$valid}}
\n\t myForm.input.$error = {{myForm.input.$error}}
\n\t myForm.$valid = {{myForm.$valid}}
\n\t myForm.$error.required = {{!!myForm.$error.required}}
\n\t
\n\t
\n\t \n\t var value = element(by.binding('example.value | date: \"yyyy-MM-ddTHH:mm:ss\"'));\n\t var valid = element(by.binding('myForm.input.$valid'));\n\t var input = element(by.model('example.value'));\n\t\n\t // currently protractor/webdriver does not support\n\t // sending keys to all known HTML5 input controls\n\t // for various browsers (https://github.com/angular/protractor/issues/562).\n\t function setInput(val) {\n\t // set the value of the element and force validation.\n\t var scr = \"var ipt = document.getElementById('exampleInput'); \" +\n\t \"ipt.value = '\" + val + \"';\" +\n\t \"angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('\" + val + \"'); });\";\n\t browser.executeScript(scr);\n\t }\n\t\n\t it('should initialize to model', function() {\n\t expect(value.getText()).toContain('2010-12-28T14:57:00');\n\t expect(valid.getText()).toContain('myForm.input.$valid = true');\n\t });\n\t\n\t it('should be invalid if empty', function() {\n\t setInput('');\n\t expect(value.getText()).toEqual('value =');\n\t expect(valid.getText()).toContain('myForm.input.$valid = false');\n\t });\n\t\n\t it('should be invalid if over max', function() {\n\t setInput('2015-01-01T23:59:00');\n\t expect(value.getText()).toContain('');\n\t expect(valid.getText()).toContain('myForm.input.$valid = false');\n\t });\n\t \n\t
\n\t */\n\t 'datetime-local': createDateInputType('datetimelocal', DATETIMELOCAL_REGEXP,\n\t createDateParser(DATETIMELOCAL_REGEXP, ['yyyy', 'MM', 'dd', 'HH', 'mm', 'ss', 'sss']),\n\t 'yyyy-MM-ddTHH:mm:ss.sss'),\n\t\n\t /**\n\t * @ngdoc input\n\t * @name input[time]\n\t *\n\t * @description\n\t * Input with time validation and transformation. In browsers that do not yet support\n\t * the HTML5 time input, a text element will be used. In that case, the text must be entered in a valid ISO-8601\n\t * local time format (HH:mm:ss), for example: `14:57:00`. Model must be a Date object. This binding will always output a\n\t * Date object to the model of January 1, 1970, or local date `new Date(1970, 0, 1, HH, mm, ss)`.\n\t *\n\t * The model must always be a Date object, otherwise Angular will throw an error.\n\t * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.\n\t *\n\t * The timezone to be used to read/write the `Date` instance in the model can be defined using\n\t * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.\n\t *\n\t * @param {string} ngModel Assignable angular expression to data-bind to.\n\t * @param {string=} name Property name of the form under which the control is published.\n\t * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.\n\t * This must be a valid ISO time format (HH:mm:ss). You can also use interpolation inside this\n\t * attribute (e.g. `min=\"{{minTime | date:'HH:mm:ss'}}\"`). Note that `min` will also add\n\t * native HTML5 constraint validation.\n\t * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.\n\t * This must be a valid ISO time format (HH:mm:ss). You can also use interpolation inside this\n\t * attribute (e.g. `max=\"{{maxTime | date:'HH:mm:ss'}}\"`). Note that `max` will also add\n\t * native HTML5 constraint validation.\n\t * @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO time string the\n\t * `ngMin` expression evaluates to. Note that it does not set the `min` attribute.\n\t * @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO time string the\n\t * `ngMax` expression evaluates to. Note that it does not set the `max` attribute.\n\t * @param {string=} required Sets `required` validation error key if the value is not entered.\n\t * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n\t * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n\t * `required` when you want to data-bind to the `required` attribute.\n\t * @param {string=} ngChange Angular expression to be executed when input changes due to user\n\t * interaction with the input element.\n\t *\n\t * @example\n\t \n\t \n\t \n\t
\n\t \n\t \n\t
\n\t \n\t Required!\n\t \n\t Not a valid date!\n\t
\n\t value = {{example.value | date: \"HH:mm:ss\"}}
\n\t myForm.input.$valid = {{myForm.input.$valid}}
\n\t myForm.input.$error = {{myForm.input.$error}}
\n\t myForm.$valid = {{myForm.$valid}}
\n\t myForm.$error.required = {{!!myForm.$error.required}}
\n\t
\n\t
\n\t \n\t var value = element(by.binding('example.value | date: \"HH:mm:ss\"'));\n\t var valid = element(by.binding('myForm.input.$valid'));\n\t var input = element(by.model('example.value'));\n\t\n\t // currently protractor/webdriver does not support\n\t // sending keys to all known HTML5 input controls\n\t // for various browsers (https://github.com/angular/protractor/issues/562).\n\t function setInput(val) {\n\t // set the value of the element and force validation.\n\t var scr = \"var ipt = document.getElementById('exampleInput'); \" +\n\t \"ipt.value = '\" + val + \"';\" +\n\t \"angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('\" + val + \"'); });\";\n\t browser.executeScript(scr);\n\t }\n\t\n\t it('should initialize to model', function() {\n\t expect(value.getText()).toContain('14:57:00');\n\t expect(valid.getText()).toContain('myForm.input.$valid = true');\n\t });\n\t\n\t it('should be invalid if empty', function() {\n\t setInput('');\n\t expect(value.getText()).toEqual('value =');\n\t expect(valid.getText()).toContain('myForm.input.$valid = false');\n\t });\n\t\n\t it('should be invalid if over max', function() {\n\t setInput('23:59:00');\n\t expect(value.getText()).toContain('');\n\t expect(valid.getText()).toContain('myForm.input.$valid = false');\n\t });\n\t \n\t
\n\t */\n\t 'time': createDateInputType('time', TIME_REGEXP,\n\t createDateParser(TIME_REGEXP, ['HH', 'mm', 'ss', 'sss']),\n\t 'HH:mm:ss.sss'),\n\t\n\t /**\n\t * @ngdoc input\n\t * @name input[week]\n\t *\n\t * @description\n\t * Input with week-of-the-year validation and transformation to Date. In browsers that do not yet support\n\t * the HTML5 week input, a text element will be used. In that case, the text must be entered in a valid ISO-8601\n\t * week format (yyyy-W##), for example: `2013-W02`.\n\t *\n\t * The model must always be a Date object, otherwise Angular will throw an error.\n\t * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.\n\t *\n\t * The timezone to be used to read/write the `Date` instance in the model can be defined using\n\t * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.\n\t *\n\t * @param {string} ngModel Assignable angular expression to data-bind to.\n\t * @param {string=} name Property name of the form under which the control is published.\n\t * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.\n\t * This must be a valid ISO week format (yyyy-W##). You can also use interpolation inside this\n\t * attribute (e.g. `min=\"{{minWeek | date:'yyyy-Www'}}\"`). Note that `min` will also add\n\t * native HTML5 constraint validation.\n\t * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.\n\t * This must be a valid ISO week format (yyyy-W##). You can also use interpolation inside this\n\t * attribute (e.g. `max=\"{{maxWeek | date:'yyyy-Www'}}\"`). Note that `max` will also add\n\t * native HTML5 constraint validation.\n\t * @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO week string\n\t * the `ngMin` expression evaluates to. Note that it does not set the `min` attribute.\n\t * @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO week string\n\t * the `ngMax` expression evaluates to. Note that it does not set the `max` attribute.\n\t * @param {string=} required Sets `required` validation error key if the value is not entered.\n\t * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n\t * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n\t * `required` when you want to data-bind to the `required` attribute.\n\t * @param {string=} ngChange Angular expression to be executed when input changes due to user\n\t * interaction with the input element.\n\t *\n\t * @example\n\t \n\t \n\t \n\t
\n\t \n\t
\n\t \n\t Required!\n\t \n\t Not a valid date!\n\t
\n\t value = {{example.value | date: \"yyyy-Www\"}}
\n\t myForm.input.$valid = {{myForm.input.$valid}}
\n\t myForm.input.$error = {{myForm.input.$error}}
\n\t myForm.$valid = {{myForm.$valid}}
\n\t myForm.$error.required = {{!!myForm.$error.required}}
\n\t
\n\t
\n\t \n\t var value = element(by.binding('example.value | date: \"yyyy-Www\"'));\n\t var valid = element(by.binding('myForm.input.$valid'));\n\t var input = element(by.model('example.value'));\n\t\n\t // currently protractor/webdriver does not support\n\t // sending keys to all known HTML5 input controls\n\t // for various browsers (https://github.com/angular/protractor/issues/562).\n\t function setInput(val) {\n\t // set the value of the element and force validation.\n\t var scr = \"var ipt = document.getElementById('exampleInput'); \" +\n\t \"ipt.value = '\" + val + \"';\" +\n\t \"angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('\" + val + \"'); });\";\n\t browser.executeScript(scr);\n\t }\n\t\n\t it('should initialize to model', function() {\n\t expect(value.getText()).toContain('2013-W01');\n\t expect(valid.getText()).toContain('myForm.input.$valid = true');\n\t });\n\t\n\t it('should be invalid if empty', function() {\n\t setInput('');\n\t expect(value.getText()).toEqual('value =');\n\t expect(valid.getText()).toContain('myForm.input.$valid = false');\n\t });\n\t\n\t it('should be invalid if over max', function() {\n\t setInput('2015-W01');\n\t expect(value.getText()).toContain('');\n\t expect(valid.getText()).toContain('myForm.input.$valid = false');\n\t });\n\t \n\t
\n\t */\n\t 'week': createDateInputType('week', WEEK_REGEXP, weekParser, 'yyyy-Www'),\n\t\n\t /**\n\t * @ngdoc input\n\t * @name input[month]\n\t *\n\t * @description\n\t * Input with month validation and transformation. In browsers that do not yet support\n\t * the HTML5 month input, a text element will be used. In that case, the text must be entered in a valid ISO-8601\n\t * month format (yyyy-MM), for example: `2009-01`.\n\t *\n\t * The model must always be a Date object, otherwise Angular will throw an error.\n\t * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.\n\t * If the model is not set to the first of the month, the next view to model update will set it\n\t * to the first of the month.\n\t *\n\t * The timezone to be used to read/write the `Date` instance in the model can be defined using\n\t * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.\n\t *\n\t * @param {string} ngModel Assignable angular expression to data-bind to.\n\t * @param {string=} name Property name of the form under which the control is published.\n\t * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.\n\t * This must be a valid ISO month format (yyyy-MM). You can also use interpolation inside this\n\t * attribute (e.g. `min=\"{{minMonth | date:'yyyy-MM'}}\"`). Note that `min` will also add\n\t * native HTML5 constraint validation.\n\t * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.\n\t * This must be a valid ISO month format (yyyy-MM). You can also use interpolation inside this\n\t * attribute (e.g. `max=\"{{maxMonth | date:'yyyy-MM'}}\"`). Note that `max` will also add\n\t * native HTML5 constraint validation.\n\t * @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO week string\n\t * the `ngMin` expression evaluates to. Note that it does not set the `min` attribute.\n\t * @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO week string\n\t * the `ngMax` expression evaluates to. Note that it does not set the `max` attribute.\n\t\n\t * @param {string=} required Sets `required` validation error key if the value is not entered.\n\t * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n\t * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n\t * `required` when you want to data-bind to the `required` attribute.\n\t * @param {string=} ngChange Angular expression to be executed when input changes due to user\n\t * interaction with the input element.\n\t *\n\t * @example\n\t \n\t \n\t \n\t
\n\t \n\t \n\t
\n\t \n\t Required!\n\t \n\t Not a valid month!\n\t
\n\t value = {{example.value | date: \"yyyy-MM\"}}
\n\t myForm.input.$valid = {{myForm.input.$valid}}
\n\t myForm.input.$error = {{myForm.input.$error}}
\n\t myForm.$valid = {{myForm.$valid}}
\n\t myForm.$error.required = {{!!myForm.$error.required}}
\n\t
\n\t
\n\t \n\t var value = element(by.binding('example.value | date: \"yyyy-MM\"'));\n\t var valid = element(by.binding('myForm.input.$valid'));\n\t var input = element(by.model('example.value'));\n\t\n\t // currently protractor/webdriver does not support\n\t // sending keys to all known HTML5 input controls\n\t // for various browsers (https://github.com/angular/protractor/issues/562).\n\t function setInput(val) {\n\t // set the value of the element and force validation.\n\t var scr = \"var ipt = document.getElementById('exampleInput'); \" +\n\t \"ipt.value = '\" + val + \"';\" +\n\t \"angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('\" + val + \"'); });\";\n\t browser.executeScript(scr);\n\t }\n\t\n\t it('should initialize to model', function() {\n\t expect(value.getText()).toContain('2013-10');\n\t expect(valid.getText()).toContain('myForm.input.$valid = true');\n\t });\n\t\n\t it('should be invalid if empty', function() {\n\t setInput('');\n\t expect(value.getText()).toEqual('value =');\n\t expect(valid.getText()).toContain('myForm.input.$valid = false');\n\t });\n\t\n\t it('should be invalid if over max', function() {\n\t setInput('2015-01');\n\t expect(value.getText()).toContain('');\n\t expect(valid.getText()).toContain('myForm.input.$valid = false');\n\t });\n\t \n\t
\n\t */\n\t 'month': createDateInputType('month', MONTH_REGEXP,\n\t createDateParser(MONTH_REGEXP, ['yyyy', 'MM']),\n\t 'yyyy-MM'),\n\t\n\t /**\n\t * @ngdoc input\n\t * @name input[number]\n\t *\n\t * @description\n\t * Text input with number validation and transformation. Sets the `number` validation\n\t * error if not a valid number.\n\t *\n\t *
\n\t * The model must always be of type `number` otherwise Angular will throw an error.\n\t * Be aware that a string containing a number is not enough. See the {@link ngModel:numfmt}\n\t * error docs for more information and an example of how to convert your model if necessary.\n\t *
\n\t *\n\t * ## Issues with HTML5 constraint validation\n\t *\n\t * In browsers that follow the\n\t * [HTML5 specification](https://html.spec.whatwg.org/multipage/forms.html#number-state-%28type=number%29),\n\t * `input[number]` does not work as expected with {@link ngModelOptions `ngModelOptions.allowInvalid`}.\n\t * If a non-number is entered in the input, the browser will report the value as an empty string,\n\t * which means the view / model values in `ngModel` and subsequently the scope value\n\t * will also be an empty string.\n\t *\n\t *\n\t * @param {string} ngModel Assignable angular expression to data-bind to.\n\t * @param {string=} name Property name of the form under which the control is published.\n\t * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.\n\t * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.\n\t * @param {string=} required Sets `required` validation error key if the value is not entered.\n\t * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n\t * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n\t * `required` when you want to data-bind to the `required` attribute.\n\t * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n\t * minlength.\n\t * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n\t * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of\n\t * any length.\n\t * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string\n\t * that contains the regular expression body that will be converted to a regular expression\n\t * as in the ngPattern directive.\n\t * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue}\n\t * does not match a RegExp found by evaluating the Angular expression given in the attribute value.\n\t * If the expression evaluates to a RegExp object, then this is used directly.\n\t * If the expression evaluates to a string, then it will be converted to a RegExp\n\t * after wrapping it in `^` and `$` characters. For instance, `\"abc\"` will be converted to\n\t * `new RegExp('^abc$')`.
\n\t * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to\n\t * start at the index of the last search's match, thus not taking the whole input value into\n\t * account.\n\t * @param {string=} ngChange Angular expression to be executed when input changes due to user\n\t * interaction with the input element.\n\t *\n\t * @example\n\t \n\t \n\t \n\t
\n\t \n\t
\n\t \n\t Required!\n\t \n\t Not valid number!\n\t
\n\t value = {{example.value}}
\n\t myForm.input.$valid = {{myForm.input.$valid}}
\n\t myForm.input.$error = {{myForm.input.$error}}
\n\t myForm.$valid = {{myForm.$valid}}
\n\t myForm.$error.required = {{!!myForm.$error.required}}
\n\t
\n\t
\n\t \n\t var value = element(by.binding('example.value'));\n\t var valid = element(by.binding('myForm.input.$valid'));\n\t var input = element(by.model('example.value'));\n\t\n\t it('should initialize to model', function() {\n\t expect(value.getText()).toContain('12');\n\t expect(valid.getText()).toContain('true');\n\t });\n\t\n\t it('should be invalid if empty', function() {\n\t input.clear();\n\t input.sendKeys('');\n\t expect(value.getText()).toEqual('value =');\n\t expect(valid.getText()).toContain('false');\n\t });\n\t\n\t it('should be invalid if over max', function() {\n\t input.clear();\n\t input.sendKeys('123');\n\t expect(value.getText()).toEqual('value =');\n\t expect(valid.getText()).toContain('false');\n\t });\n\t \n\t
\n\t */\n\t 'number': numberInputType,\n\t\n\t\n\t /**\n\t * @ngdoc input\n\t * @name input[url]\n\t *\n\t * @description\n\t * Text input with URL validation. Sets the `url` validation error key if the content is not a\n\t * valid URL.\n\t *\n\t *
\n\t * **Note:** `input[url]` uses a regex to validate urls that is derived from the regex\n\t * used in Chromium. If you need stricter validation, you can use `ng-pattern` or modify\n\t * the built-in validators (see the {@link guide/forms Forms guide})\n\t *
\n\t *\n\t * @param {string} ngModel Assignable angular expression to data-bind to.\n\t * @param {string=} name Property name of the form under which the control is published.\n\t * @param {string=} required Sets `required` validation error key if the value is not entered.\n\t * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n\t * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n\t * `required` when you want to data-bind to the `required` attribute.\n\t * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n\t * minlength.\n\t * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n\t * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of\n\t * any length.\n\t * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string\n\t * that contains the regular expression body that will be converted to a regular expression\n\t * as in the ngPattern directive.\n\t * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue}\n\t * does not match a RegExp found by evaluating the Angular expression given in the attribute value.\n\t * If the expression evaluates to a RegExp object, then this is used directly.\n\t * If the expression evaluates to a string, then it will be converted to a RegExp\n\t * after wrapping it in `^` and `$` characters. For instance, `\"abc\"` will be converted to\n\t * `new RegExp('^abc$')`.
\n\t * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to\n\t * start at the index of the last search's match, thus not taking the whole input value into\n\t * account.\n\t * @param {string=} ngChange Angular expression to be executed when input changes due to user\n\t * interaction with the input element.\n\t *\n\t * @example\n\t \n\t \n\t \n\t
\n\t
\n\t \n\t var text = element(by.binding('url.text'));\n\t var valid = element(by.binding('myForm.input.$valid'));\n\t var input = element(by.model('url.text'));\n\t\n\t it('should initialize to model', function() {\n\t expect(text.getText()).toContain('http://google.com');\n\t expect(valid.getText()).toContain('true');\n\t });\n\t\n\t it('should be invalid if empty', function() {\n\t input.clear();\n\t input.sendKeys('');\n\t\n\t expect(text.getText()).toEqual('text =');\n\t expect(valid.getText()).toContain('false');\n\t });\n\t\n\t it('should be invalid if not url', function() {\n\t input.clear();\n\t input.sendKeys('box');\n\t\n\t expect(valid.getText()).toContain('false');\n\t });\n\t \n\t
\n\t */\n\t 'url': urlInputType,\n\t\n\t\n\t /**\n\t * @ngdoc input\n\t * @name input[email]\n\t *\n\t * @description\n\t * Text input with email validation. Sets the `email` validation error key if not a valid email\n\t * address.\n\t *\n\t *
\n\t * **Note:** `input[email]` uses a regex to validate email addresses that is derived from the regex\n\t * used in Chromium. If you need stricter validation (e.g. requiring a top-level domain), you can\n\t * use `ng-pattern` or modify the built-in validators (see the {@link guide/forms Forms guide})\n\t *
\n\t *\n\t * @param {string} ngModel Assignable angular expression to data-bind to.\n\t * @param {string=} name Property name of the form under which the control is published.\n\t * @param {string=} required Sets `required` validation error key if the value is not entered.\n\t * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n\t * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n\t * `required` when you want to data-bind to the `required` attribute.\n\t * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n\t * minlength.\n\t * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n\t * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of\n\t * any length.\n\t * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string\n\t * that contains the regular expression body that will be converted to a regular expression\n\t * as in the ngPattern directive.\n\t * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue}\n\t * does not match a RegExp found by evaluating the Angular expression given in the attribute value.\n\t * If the expression evaluates to a RegExp object, then this is used directly.\n\t * If the expression evaluates to a string, then it will be converted to a RegExp\n\t * after wrapping it in `^` and `$` characters. For instance, `\"abc\"` will be converted to\n\t * `new RegExp('^abc$')`.
\n\t * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to\n\t * start at the index of the last search's match, thus not taking the whole input value into\n\t * account.\n\t * @param {string=} ngChange Angular expression to be executed when input changes due to user\n\t * interaction with the input element.\n\t *\n\t * @example\n\t \n\t \n\t \n\t
\n\t \n\t
\n\t \n\t Required!\n\t \n\t Not valid email!\n\t
\n\t text = {{email.text}}
\n\t myForm.input.$valid = {{myForm.input.$valid}}
\n\t myForm.input.$error = {{myForm.input.$error}}
\n\t myForm.$valid = {{myForm.$valid}}
\n\t myForm.$error.required = {{!!myForm.$error.required}}
\n\t myForm.$error.email = {{!!myForm.$error.email}}
\n\t
\n\t
\n\t \n\t var text = element(by.binding('email.text'));\n\t var valid = element(by.binding('myForm.input.$valid'));\n\t var input = element(by.model('email.text'));\n\t\n\t it('should initialize to model', function() {\n\t expect(text.getText()).toContain('me@example.com');\n\t expect(valid.getText()).toContain('true');\n\t });\n\t\n\t it('should be invalid if empty', function() {\n\t input.clear();\n\t input.sendKeys('');\n\t expect(text.getText()).toEqual('text =');\n\t expect(valid.getText()).toContain('false');\n\t });\n\t\n\t it('should be invalid if not email', function() {\n\t input.clear();\n\t input.sendKeys('xxx');\n\t\n\t expect(valid.getText()).toContain('false');\n\t });\n\t \n\t
\n\t */\n\t 'email': emailInputType,\n\t\n\t\n\t /**\n\t * @ngdoc input\n\t * @name input[radio]\n\t *\n\t * @description\n\t * HTML radio button.\n\t *\n\t * @param {string} ngModel Assignable angular expression to data-bind to.\n\t * @param {string} value The value to which the `ngModel` expression should be set when selected.\n\t * Note that `value` only supports `string` values, i.e. the scope model needs to be a string,\n\t * too. Use `ngValue` if you need complex models (`number`, `object`, ...).\n\t * @param {string=} name Property name of the form under which the control is published.\n\t * @param {string=} ngChange Angular expression to be executed when input changes due to user\n\t * interaction with the input element.\n\t * @param {string} ngValue Angular expression to which `ngModel` will be be set when the radio\n\t * is selected. Should be used instead of the `value` attribute if you need\n\t * a non-string `ngModel` (`boolean`, `array`, ...).\n\t *\n\t * @example\n\t \n\t \n\t \n\t
\n\t
\n\t
\n\t
\n\t color = {{color.name | json}}
\n\t
\n\t Note that `ng-value=\"specialValue\"` sets radio item's value to be the value of `$scope.specialValue`.\n\t
\n\t \n\t it('should change state', function() {\n\t var color = element(by.binding('color.name'));\n\t\n\t expect(color.getText()).toContain('blue');\n\t\n\t element.all(by.model('color.name')).get(0).click();\n\t\n\t expect(color.getText()).toContain('red');\n\t });\n\t \n\t
\n\t */\n\t 'radio': radioInputType,\n\t\n\t\n\t /**\n\t * @ngdoc input\n\t * @name input[checkbox]\n\t *\n\t * @description\n\t * HTML checkbox.\n\t *\n\t * @param {string} ngModel Assignable angular expression to data-bind to.\n\t * @param {string=} name Property name of the form under which the control is published.\n\t * @param {expression=} ngTrueValue The value to which the expression should be set when selected.\n\t * @param {expression=} ngFalseValue The value to which the expression should be set when not selected.\n\t * @param {string=} ngChange Angular expression to be executed when input changes due to user\n\t * interaction with the input element.\n\t *\n\t * @example\n\t \n\t \n\t \n\t
\n\t
\n\t
\n\t value1 = {{checkboxModel.value1}}
\n\t value2 = {{checkboxModel.value2}}
\n\t
\n\t
\n\t \n\t it('should change state', function() {\n\t var value1 = element(by.binding('checkboxModel.value1'));\n\t var value2 = element(by.binding('checkboxModel.value2'));\n\t\n\t expect(value1.getText()).toContain('true');\n\t expect(value2.getText()).toContain('YES');\n\t\n\t element(by.model('checkboxModel.value1')).click();\n\t element(by.model('checkboxModel.value2')).click();\n\t\n\t expect(value1.getText()).toContain('false');\n\t expect(value2.getText()).toContain('NO');\n\t });\n\t \n\t
\n\t */\n\t 'checkbox': checkboxInputType,\n\t\n\t 'hidden': noop,\n\t 'button': noop,\n\t 'submit': noop,\n\t 'reset': noop,\n\t 'file': noop\n\t};\n\t\n\tfunction stringBasedInputType(ctrl) {\n\t ctrl.$formatters.push(function(value) {\n\t return ctrl.$isEmpty(value) ? value : value.toString();\n\t });\n\t}\n\t\n\tfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\t baseInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\t stringBasedInputType(ctrl);\n\t}\n\t\n\tfunction baseInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\t var type = lowercase(element[0].type);\n\t\n\t // In composition mode, users are still inputing intermediate text buffer,\n\t // hold the listener until composition is done.\n\t // More about composition events: https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent\n\t if (!$sniffer.android) {\n\t var composing = false;\n\t\n\t element.on('compositionstart', function() {\n\t composing = true;\n\t });\n\t\n\t element.on('compositionend', function() {\n\t composing = false;\n\t listener();\n\t });\n\t }\n\t\n\t var timeout;\n\t\n\t var listener = function(ev) {\n\t if (timeout) {\n\t $browser.defer.cancel(timeout);\n\t timeout = null;\n\t }\n\t if (composing) return;\n\t var value = element.val(),\n\t event = ev && ev.type;\n\t\n\t // By default we will trim the value\n\t // If the attribute ng-trim exists we will avoid trimming\n\t // If input type is 'password', the value is never trimmed\n\t if (type !== 'password' && (!attr.ngTrim || attr.ngTrim !== 'false')) {\n\t value = trim(value);\n\t }\n\t\n\t // If a control is suffering from bad input (due to native validators), browsers discard its\n\t // value, so it may be necessary to revalidate (by calling $setViewValue again) even if the\n\t // control's value is the same empty value twice in a row.\n\t if (ctrl.$viewValue !== value || (value === '' && ctrl.$$hasNativeValidators)) {\n\t ctrl.$setViewValue(value, event);\n\t }\n\t };\n\t\n\t // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n\t // input event on backspace, delete or cut\n\t if ($sniffer.hasEvent('input')) {\n\t element.on('input', listener);\n\t } else {\n\t var deferListener = function(ev, input, origValue) {\n\t if (!timeout) {\n\t timeout = $browser.defer(function() {\n\t timeout = null;\n\t if (!input || input.value !== origValue) {\n\t listener(ev);\n\t }\n\t });\n\t }\n\t };\n\t\n\t element.on('keydown', function(event) {\n\t var key = event.keyCode;\n\t\n\t // ignore\n\t // command modifiers arrows\n\t if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\t\n\t deferListener(event, this, this.value);\n\t });\n\t\n\t // if user modifies input value using context menu in IE, we need \"paste\" and \"cut\" events to catch it\n\t if ($sniffer.hasEvent('paste')) {\n\t element.on('paste cut', deferListener);\n\t }\n\t }\n\t\n\t // if user paste into input using mouse on older browser\n\t // or form autocomplete on newer browser, we need \"change\" event to catch it\n\t element.on('change', listener);\n\t\n\t // Some native input types (date-family) have the ability to change validity without\n\t // firing any input/change events.\n\t // For these event types, when native validators are present and the browser supports the type,\n\t // check for validity changes on various DOM events.\n\t if (PARTIAL_VALIDATION_TYPES[type] && ctrl.$$hasNativeValidators && type === attr.type) {\n\t element.on(PARTIAL_VALIDATION_EVENTS, function(ev) {\n\t if (!timeout) {\n\t var validity = this[VALIDITY_STATE_PROPERTY];\n\t var origBadInput = validity.badInput;\n\t var origTypeMismatch = validity.typeMismatch;\n\t timeout = $browser.defer(function() {\n\t timeout = null;\n\t if (validity.badInput !== origBadInput || validity.typeMismatch !== origTypeMismatch) {\n\t listener(ev);\n\t }\n\t });\n\t }\n\t });\n\t }\n\t\n\t ctrl.$render = function() {\n\t // Workaround for Firefox validation #12102.\n\t var value = ctrl.$isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue;\n\t if (element.val() !== value) {\n\t element.val(value);\n\t }\n\t };\n\t}\n\t\n\tfunction weekParser(isoWeek, existingDate) {\n\t if (isDate(isoWeek)) {\n\t return isoWeek;\n\t }\n\t\n\t if (isString(isoWeek)) {\n\t WEEK_REGEXP.lastIndex = 0;\n\t var parts = WEEK_REGEXP.exec(isoWeek);\n\t if (parts) {\n\t var year = +parts[1],\n\t week = +parts[2],\n\t hours = 0,\n\t minutes = 0,\n\t seconds = 0,\n\t milliseconds = 0,\n\t firstThurs = getFirstThursdayOfYear(year),\n\t addDays = (week - 1) * 7;\n\t\n\t if (existingDate) {\n\t hours = existingDate.getHours();\n\t minutes = existingDate.getMinutes();\n\t seconds = existingDate.getSeconds();\n\t milliseconds = existingDate.getMilliseconds();\n\t }\n\t\n\t return new Date(year, 0, firstThurs.getDate() + addDays, hours, minutes, seconds, milliseconds);\n\t }\n\t }\n\t\n\t return NaN;\n\t}\n\t\n\tfunction createDateParser(regexp, mapping) {\n\t return function(iso, date) {\n\t var parts, map;\n\t\n\t if (isDate(iso)) {\n\t return iso;\n\t }\n\t\n\t if (isString(iso)) {\n\t // When a date is JSON'ified to wraps itself inside of an extra\n\t // set of double quotes. This makes the date parsing code unable\n\t // to match the date string and parse it as a date.\n\t if (iso.charAt(0) == '\"' && iso.charAt(iso.length - 1) == '\"') {\n\t iso = iso.substring(1, iso.length - 1);\n\t }\n\t if (ISO_DATE_REGEXP.test(iso)) {\n\t return new Date(iso);\n\t }\n\t regexp.lastIndex = 0;\n\t parts = regexp.exec(iso);\n\t\n\t if (parts) {\n\t parts.shift();\n\t if (date) {\n\t map = {\n\t yyyy: date.getFullYear(),\n\t MM: date.getMonth() + 1,\n\t dd: date.getDate(),\n\t HH: date.getHours(),\n\t mm: date.getMinutes(),\n\t ss: date.getSeconds(),\n\t sss: date.getMilliseconds() / 1000\n\t };\n\t } else {\n\t map = { yyyy: 1970, MM: 1, dd: 1, HH: 0, mm: 0, ss: 0, sss: 0 };\n\t }\n\t\n\t forEach(parts, function(part, index) {\n\t if (index < mapping.length) {\n\t map[mapping[index]] = +part;\n\t }\n\t });\n\t return new Date(map.yyyy, map.MM - 1, map.dd, map.HH, map.mm, map.ss || 0, map.sss * 1000 || 0);\n\t }\n\t }\n\t\n\t return NaN;\n\t };\n\t}\n\t\n\tfunction createDateInputType(type, regexp, parseDate, format) {\n\t return function dynamicDateInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter) {\n\t badInputChecker(scope, element, attr, ctrl);\n\t baseInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\t var timezone = ctrl && ctrl.$options && ctrl.$options.timezone;\n\t var previousDate;\n\t\n\t ctrl.$$parserName = type;\n\t ctrl.$parsers.push(function(value) {\n\t if (ctrl.$isEmpty(value)) return null;\n\t if (regexp.test(value)) {\n\t // Note: We cannot read ctrl.$modelValue, as there might be a different\n\t // parser/formatter in the processing chain so that the model\n\t // contains some different data format!\n\t var parsedDate = parseDate(value, previousDate);\n\t if (timezone) {\n\t parsedDate = convertTimezoneToLocal(parsedDate, timezone);\n\t }\n\t return parsedDate;\n\t }\n\t return undefined;\n\t });\n\t\n\t ctrl.$formatters.push(function(value) {\n\t if (value && !isDate(value)) {\n\t throw ngModelMinErr('datefmt', 'Expected `{0}` to be a date', value);\n\t }\n\t if (isValidDate(value)) {\n\t previousDate = value;\n\t if (previousDate && timezone) {\n\t previousDate = convertTimezoneToLocal(previousDate, timezone, true);\n\t }\n\t return $filter('date')(value, format, timezone);\n\t } else {\n\t previousDate = null;\n\t return '';\n\t }\n\t });\n\t\n\t if (isDefined(attr.min) || attr.ngMin) {\n\t var minVal;\n\t ctrl.$validators.min = function(value) {\n\t return !isValidDate(value) || isUndefined(minVal) || parseDate(value) >= minVal;\n\t };\n\t attr.$observe('min', function(val) {\n\t minVal = parseObservedDateValue(val);\n\t ctrl.$validate();\n\t });\n\t }\n\t\n\t if (isDefined(attr.max) || attr.ngMax) {\n\t var maxVal;\n\t ctrl.$validators.max = function(value) {\n\t return !isValidDate(value) || isUndefined(maxVal) || parseDate(value) <= maxVal;\n\t };\n\t attr.$observe('max', function(val) {\n\t maxVal = parseObservedDateValue(val);\n\t ctrl.$validate();\n\t });\n\t }\n\t\n\t function isValidDate(value) {\n\t // Invalid Date: getTime() returns NaN\n\t return value && !(value.getTime && value.getTime() !== value.getTime());\n\t }\n\t\n\t function parseObservedDateValue(val) {\n\t return isDefined(val) && !isDate(val) ? parseDate(val) || undefined : val;\n\t }\n\t };\n\t}\n\t\n\tfunction badInputChecker(scope, element, attr, ctrl) {\n\t var node = element[0];\n\t var nativeValidation = ctrl.$$hasNativeValidators = isObject(node.validity);\n\t if (nativeValidation) {\n\t ctrl.$parsers.push(function(value) {\n\t var validity = element.prop(VALIDITY_STATE_PROPERTY) || {};\n\t return validity.badInput || validity.typeMismatch ? undefined : value;\n\t });\n\t }\n\t}\n\t\n\tfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\t badInputChecker(scope, element, attr, ctrl);\n\t baseInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\t\n\t ctrl.$$parserName = 'number';\n\t ctrl.$parsers.push(function(value) {\n\t if (ctrl.$isEmpty(value)) return null;\n\t if (NUMBER_REGEXP.test(value)) return parseFloat(value);\n\t return undefined;\n\t });\n\t\n\t ctrl.$formatters.push(function(value) {\n\t if (!ctrl.$isEmpty(value)) {\n\t if (!isNumber(value)) {\n\t throw ngModelMinErr('numfmt', 'Expected `{0}` to be a number', value);\n\t }\n\t value = value.toString();\n\t }\n\t return value;\n\t });\n\t\n\t if (isDefined(attr.min) || attr.ngMin) {\n\t var minVal;\n\t ctrl.$validators.min = function(value) {\n\t return ctrl.$isEmpty(value) || isUndefined(minVal) || value >= minVal;\n\t };\n\t\n\t attr.$observe('min', function(val) {\n\t if (isDefined(val) && !isNumber(val)) {\n\t val = parseFloat(val);\n\t }\n\t minVal = isNumber(val) && !isNaN(val) ? val : undefined;\n\t // TODO(matsko): implement validateLater to reduce number of validations\n\t ctrl.$validate();\n\t });\n\t }\n\t\n\t if (isDefined(attr.max) || attr.ngMax) {\n\t var maxVal;\n\t ctrl.$validators.max = function(value) {\n\t return ctrl.$isEmpty(value) || isUndefined(maxVal) || value <= maxVal;\n\t };\n\t\n\t attr.$observe('max', function(val) {\n\t if (isDefined(val) && !isNumber(val)) {\n\t val = parseFloat(val);\n\t }\n\t maxVal = isNumber(val) && !isNaN(val) ? val : undefined;\n\t // TODO(matsko): implement validateLater to reduce number of validations\n\t ctrl.$validate();\n\t });\n\t }\n\t}\n\t\n\tfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\t // Note: no badInputChecker here by purpose as `url` is only a validation\n\t // in browsers, i.e. we can always read out input.value even if it is not valid!\n\t baseInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\t stringBasedInputType(ctrl);\n\t\n\t ctrl.$$parserName = 'url';\n\t ctrl.$validators.url = function(modelValue, viewValue) {\n\t var value = modelValue || viewValue;\n\t return ctrl.$isEmpty(value) || URL_REGEXP.test(value);\n\t };\n\t}\n\t\n\tfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n\t // Note: no badInputChecker here by purpose as `url` is only a validation\n\t // in browsers, i.e. we can always read out input.value even if it is not valid!\n\t baseInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\t stringBasedInputType(ctrl);\n\t\n\t ctrl.$$parserName = 'email';\n\t ctrl.$validators.email = function(modelValue, viewValue) {\n\t var value = modelValue || viewValue;\n\t return ctrl.$isEmpty(value) || EMAIL_REGEXP.test(value);\n\t };\n\t}\n\t\n\tfunction radioInputType(scope, element, attr, ctrl) {\n\t // make the name unique, if not defined\n\t if (isUndefined(attr.name)) {\n\t element.attr('name', nextUid());\n\t }\n\t\n\t var listener = function(ev) {\n\t if (element[0].checked) {\n\t ctrl.$setViewValue(attr.value, ev && ev.type);\n\t }\n\t };\n\t\n\t element.on('click', listener);\n\t\n\t ctrl.$render = function() {\n\t var value = attr.value;\n\t element[0].checked = (value == ctrl.$viewValue);\n\t };\n\t\n\t attr.$observe('value', ctrl.$render);\n\t}\n\t\n\tfunction parseConstantExpr($parse, context, name, expression, fallback) {\n\t var parseFn;\n\t if (isDefined(expression)) {\n\t parseFn = $parse(expression);\n\t if (!parseFn.constant) {\n\t throw ngModelMinErr('constexpr', 'Expected constant expression for `{0}`, but saw ' +\n\t '`{1}`.', name, expression);\n\t }\n\t return parseFn(context);\n\t }\n\t return fallback;\n\t}\n\t\n\tfunction checkboxInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter, $parse) {\n\t var trueValue = parseConstantExpr($parse, scope, 'ngTrueValue', attr.ngTrueValue, true);\n\t var falseValue = parseConstantExpr($parse, scope, 'ngFalseValue', attr.ngFalseValue, false);\n\t\n\t var listener = function(ev) {\n\t ctrl.$setViewValue(element[0].checked, ev && ev.type);\n\t };\n\t\n\t element.on('click', listener);\n\t\n\t ctrl.$render = function() {\n\t element[0].checked = ctrl.$viewValue;\n\t };\n\t\n\t // Override the standard `$isEmpty` because the $viewValue of an empty checkbox is always set to `false`\n\t // This is because of the parser below, which compares the `$modelValue` with `trueValue` to convert\n\t // it to a boolean.\n\t ctrl.$isEmpty = function(value) {\n\t return value === false;\n\t };\n\t\n\t ctrl.$formatters.push(function(value) {\n\t return equals(value, trueValue);\n\t });\n\t\n\t ctrl.$parsers.push(function(value) {\n\t return value ? trueValue : falseValue;\n\t });\n\t}\n\t\n\t\n\t/**\n\t * @ngdoc directive\n\t * @name textarea\n\t * @restrict E\n\t *\n\t * @description\n\t * HTML textarea element control with angular data-binding. The data-binding and validation\n\t * properties of this element are exactly the same as those of the\n\t * {@link ng.directive:input input element}.\n\t *\n\t * @param {string} ngModel Assignable angular expression to data-bind to.\n\t * @param {string=} name Property name of the form under which the control is published.\n\t * @param {string=} required Sets `required` validation error key if the value is not entered.\n\t * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n\t * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n\t * `required` when you want to data-bind to the `required` attribute.\n\t * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n\t * minlength.\n\t * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n\t * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any\n\t * length.\n\t * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue}\n\t * does not match a RegExp found by evaluating the Angular expression given in the attribute value.\n\t * If the expression evaluates to a RegExp object, then this is used directly.\n\t * If the expression evaluates to a string, then it will be converted to a RegExp\n\t * after wrapping it in `^` and `$` characters. For instance, `\"abc\"` will be converted to\n\t * `new RegExp('^abc$')`.
\n\t * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to\n\t * start at the index of the last search's match, thus not taking the whole input value into\n\t * account.\n\t * @param {string=} ngChange Angular expression to be executed when input changes due to user\n\t * interaction with the input element.\n\t * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.\n\t */\n\t\n\t\n\t/**\n\t * @ngdoc directive\n\t * @name input\n\t * @restrict E\n\t *\n\t * @description\n\t * HTML input element control. When used together with {@link ngModel `ngModel`}, it provides data-binding,\n\t * input state control, and validation.\n\t * Input control follows HTML5 input types and polyfills the HTML5 validation behavior for older browsers.\n\t *\n\t *
\n\t * **Note:** Not every feature offered is available for all input types.\n\t * Specifically, data binding and event handling via `ng-model` is unsupported for `input[file]`.\n\t *
\n\t *\n\t * @param {string} ngModel Assignable angular expression to data-bind to.\n\t * @param {string=} name Property name of the form under which the control is published.\n\t * @param {string=} required Sets `required` validation error key if the value is not entered.\n\t * @param {boolean=} ngRequired Sets `required` attribute if set to true\n\t * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n\t * minlength.\n\t * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n\t * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any\n\t * length.\n\t * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue}\n\t * value does not match a RegExp found by evaluating the Angular expression given in the attribute value.\n\t * If the expression evaluates to a RegExp object, then this is used directly.\n\t * If the expression evaluates to a string, then it will be converted to a RegExp\n\t * after wrapping it in `^` and `$` characters. For instance, `\"abc\"` will be converted to\n\t * `new RegExp('^abc$')`.
\n\t * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to\n\t * start at the index of the last search's match, thus not taking the whole input value into\n\t * account.\n\t * @param {string=} ngChange Angular expression to be executed when input changes due to user\n\t * interaction with the input element.\n\t * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.\n\t * This parameter is ignored for input[type=password] controls, which will never trim the\n\t * input.\n\t *\n\t * @example\n\t \n\t \n\t \n\t
\n\t
\n\t \n\t
\n\t \n\t Required!\n\t
\n\t \n\t
\n\t \n\t Too short!\n\t \n\t Too long!\n\t
\n\t
\n\t
\n\t user = {{user}}
\n\t myForm.userName.$valid = {{myForm.userName.$valid}}
\n\t myForm.userName.$error = {{myForm.userName.$error}}
\n\t myForm.lastName.$valid = {{myForm.lastName.$valid}}
\n\t myForm.lastName.$error = {{myForm.lastName.$error}}
\n\t myForm.$valid = {{myForm.$valid}}
\n\t myForm.$error.required = {{!!myForm.$error.required}}
\n\t myForm.$error.minlength = {{!!myForm.$error.minlength}}
\n\t myForm.$error.maxlength = {{!!myForm.$error.maxlength}}
\n\t
\n\t
\n\t \n\t var user = element(by.exactBinding('user'));\n\t var userNameValid = element(by.binding('myForm.userName.$valid'));\n\t var lastNameValid = element(by.binding('myForm.lastName.$valid'));\n\t var lastNameError = element(by.binding('myForm.lastName.$error'));\n\t var formValid = element(by.binding('myForm.$valid'));\n\t var userNameInput = element(by.model('user.name'));\n\t var userLastInput = element(by.model('user.last'));\n\t\n\t it('should initialize to model', function() {\n\t expect(user.getText()).toContain('{\"name\":\"guest\",\"last\":\"visitor\"}');\n\t expect(userNameValid.getText()).toContain('true');\n\t expect(formValid.getText()).toContain('true');\n\t });\n\t\n\t it('should be invalid if empty when required', function() {\n\t userNameInput.clear();\n\t userNameInput.sendKeys('');\n\t\n\t expect(user.getText()).toContain('{\"last\":\"visitor\"}');\n\t expect(userNameValid.getText()).toContain('false');\n\t expect(formValid.getText()).toContain('false');\n\t });\n\t\n\t it('should be valid if empty when min length is set', function() {\n\t userLastInput.clear();\n\t userLastInput.sendKeys('');\n\t\n\t expect(user.getText()).toContain('{\"name\":\"guest\",\"last\":\"\"}');\n\t expect(lastNameValid.getText()).toContain('true');\n\t expect(formValid.getText()).toContain('true');\n\t });\n\t\n\t it('should be invalid if less than required min length', function() {\n\t userLastInput.clear();\n\t userLastInput.sendKeys('xx');\n\t\n\t expect(user.getText()).toContain('{\"name\":\"guest\"}');\n\t expect(lastNameValid.getText()).toContain('false');\n\t expect(lastNameError.getText()).toContain('minlength');\n\t expect(formValid.getText()).toContain('false');\n\t });\n\t\n\t it('should be invalid if longer than max length', function() {\n\t userLastInput.clear();\n\t userLastInput.sendKeys('some ridiculously long name');\n\t\n\t expect(user.getText()).toContain('{\"name\":\"guest\"}');\n\t expect(lastNameValid.getText()).toContain('false');\n\t expect(lastNameError.getText()).toContain('maxlength');\n\t expect(formValid.getText()).toContain('false');\n\t });\n\t \n\t
\n\t */\n\tvar inputDirective = ['$browser', '$sniffer', '$filter', '$parse',\n\t function($browser, $sniffer, $filter, $parse) {\n\t return {\n\t restrict: 'E',\n\t require: ['?ngModel'],\n\t link: {\n\t pre: function(scope, element, attr, ctrls) {\n\t if (ctrls[0]) {\n\t (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrls[0], $sniffer,\n\t $browser, $filter, $parse);\n\t }\n\t }\n\t }\n\t };\n\t}];\n\t\n\t\n\t\n\tvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n\t/**\n\t * @ngdoc directive\n\t * @name ngValue\n\t *\n\t * @description\n\t * Binds the given expression to the value of `
\n\t \n\t \n\t it('should show correct pluralized string', function() {\n\t var withoutOffset = element.all(by.css('ng-pluralize')).get(0);\n\t var withOffset = element.all(by.css('ng-pluralize')).get(1);\n\t var countInput = element(by.model('personCount'));\n\t\n\t expect(withoutOffset.getText()).toEqual('1 person is viewing.');\n\t expect(withOffset.getText()).toEqual('Igor is viewing.');\n\t\n\t countInput.clear();\n\t countInput.sendKeys('0');\n\t\n\t expect(withoutOffset.getText()).toEqual('Nobody is viewing.');\n\t expect(withOffset.getText()).toEqual('Nobody is viewing.');\n\t\n\t countInput.clear();\n\t countInput.sendKeys('2');\n\t\n\t expect(withoutOffset.getText()).toEqual('2 people are viewing.');\n\t expect(withOffset.getText()).toEqual('Igor and Misko are viewing.');\n\t\n\t countInput.clear();\n\t countInput.sendKeys('3');\n\t\n\t expect(withoutOffset.getText()).toEqual('3 people are viewing.');\n\t expect(withOffset.getText()).toEqual('Igor, Misko and one other person are viewing.');\n\t\n\t countInput.clear();\n\t countInput.sendKeys('4');\n\t\n\t expect(withoutOffset.getText()).toEqual('4 people are viewing.');\n\t expect(withOffset.getText()).toEqual('Igor, Misko and 2 other people are viewing.');\n\t });\n\t it('should show data-bound names', function() {\n\t var withOffset = element.all(by.css('ng-pluralize')).get(1);\n\t var personCount = element(by.model('personCount'));\n\t var person1 = element(by.model('person1'));\n\t var person2 = element(by.model('person2'));\n\t personCount.clear();\n\t personCount.sendKeys('4');\n\t person1.clear();\n\t person1.sendKeys('Di');\n\t person2.clear();\n\t person2.sendKeys('Vojta');\n\t expect(withOffset.getText()).toEqual('Di, Vojta and 2 other people are viewing.');\n\t });\n\t \n\t \n\t */\n\tvar ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale, $interpolate, $log) {\n\t var BRACE = /{}/g,\n\t IS_WHEN = /^when(Minus)?(.+)$/;\n\t\n\t return {\n\t link: function(scope, element, attr) {\n\t var numberExp = attr.count,\n\t whenExp = attr.$attr.when && element.attr(attr.$attr.when), // we have {{}} in attrs\n\t offset = attr.offset || 0,\n\t whens = scope.$eval(whenExp) || {},\n\t whensExpFns = {},\n\t startSymbol = $interpolate.startSymbol(),\n\t endSymbol = $interpolate.endSymbol(),\n\t braceReplacement = startSymbol + numberExp + '-' + offset + endSymbol,\n\t watchRemover = angular.noop,\n\t lastCount;\n\t\n\t forEach(attr, function(expression, attributeName) {\n\t var tmpMatch = IS_WHEN.exec(attributeName);\n\t if (tmpMatch) {\n\t var whenKey = (tmpMatch[1] ? '-' : '') + lowercase(tmpMatch[2]);\n\t whens[whenKey] = element.attr(attr.$attr[attributeName]);\n\t }\n\t });\n\t forEach(whens, function(expression, key) {\n\t whensExpFns[key] = $interpolate(expression.replace(BRACE, braceReplacement));\n\t\n\t });\n\t\n\t scope.$watch(numberExp, function ngPluralizeWatchAction(newVal) {\n\t var count = parseFloat(newVal);\n\t var countIsNaN = isNaN(count);\n\t\n\t if (!countIsNaN && !(count in whens)) {\n\t // If an explicit number rule such as 1, 2, 3... is defined, just use it.\n\t // Otherwise, check it against pluralization rules in $locale service.\n\t count = $locale.pluralCat(count - offset);\n\t }\n\t\n\t // If both `count` and `lastCount` are NaN, we don't need to re-register a watch.\n\t // In JS `NaN !== NaN`, so we have to explicitly check.\n\t if ((count !== lastCount) && !(countIsNaN && isNumber(lastCount) && isNaN(lastCount))) {\n\t watchRemover();\n\t var whenExpFn = whensExpFns[count];\n\t if (isUndefined(whenExpFn)) {\n\t if (newVal != null) {\n\t $log.debug(\"ngPluralize: no rule defined for '\" + count + \"' in \" + whenExp);\n\t }\n\t watchRemover = noop;\n\t updateElementText();\n\t } else {\n\t watchRemover = scope.$watch(whenExpFn, updateElementText);\n\t }\n\t lastCount = count;\n\t }\n\t });\n\t\n\t function updateElementText(newText) {\n\t element.text(newText || '');\n\t }\n\t }\n\t };\n\t}];\n\t\n\t/**\n\t * @ngdoc directive\n\t * @name ngRepeat\n\t * @multiElement\n\t *\n\t * @description\n\t * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n\t * instance gets its own scope, where the given loop variable is set to the current collection item,\n\t * and `$index` is set to the item index or key.\n\t *\n\t * Special properties are exposed on the local scope of each template instance, including:\n\t *\n\t * | Variable | Type | Details |\n\t * |-----------|-----------------|-----------------------------------------------------------------------------|\n\t * | `$index` | {@type number} | iterator offset of the repeated element (0..length-1) |\n\t * | `$first` | {@type boolean} | true if the repeated element is first in the iterator. |\n\t * | `$middle` | {@type boolean} | true if the repeated element is between the first and last in the iterator. |\n\t * | `$last` | {@type boolean} | true if the repeated element is last in the iterator. |\n\t * | `$even` | {@type boolean} | true if the iterator position `$index` is even (otherwise false). |\n\t * | `$odd` | {@type boolean} | true if the iterator position `$index` is odd (otherwise false). |\n\t *\n\t *
\n\t * Creating aliases for these properties is possible with {@link ng.directive:ngInit `ngInit`}.\n\t * This may be useful when, for instance, nesting ngRepeats.\n\t *
\n\t *\n\t *\n\t * # Iterating over object properties\n\t *\n\t * It is possible to get `ngRepeat` to iterate over the properties of an object using the following\n\t * syntax:\n\t *\n\t * ```js\n\t *
...
\n\t * ```\n\t *\n\t * However, there are a limitations compared to array iteration:\n\t *\n\t * - The JavaScript specification does not define the order of keys\n\t * returned for an object, so Angular relies on the order returned by the browser\n\t * when running `for key in myObj`. Browsers generally follow the strategy of providing\n\t * keys in the order in which they were defined, although there are exceptions when keys are deleted\n\t * and reinstated. See the\n\t * [MDN page on `delete` for more info](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete#Cross-browser_notes).\n\t *\n\t * - `ngRepeat` will silently *ignore* object keys starting with `$`, because\n\t * it's a prefix used by Angular for public (`$`) and private (`$$`) properties.\n\t *\n\t * - The built-in filters {@link ng.orderBy orderBy} and {@link ng.filter filter} do not work with\n\t * objects, and will throw an error if used with one.\n\t *\n\t * If you are hitting any of these limitations, the recommended workaround is to convert your object into an array\n\t * that is sorted into the order that you prefer before providing it to `ngRepeat`. You could\n\t * do this with a filter such as [toArrayFilter](http://ngmodules.org/modules/angular-toArrayFilter)\n\t * or implement a `$watch` on the object yourself.\n\t *\n\t *\n\t * # Tracking and Duplicates\n\t *\n\t * `ngRepeat` uses {@link $rootScope.Scope#$watchCollection $watchCollection} to detect changes in\n\t * the collection. When a change happens, ngRepeat then makes the corresponding changes to the DOM:\n\t *\n\t * * When an item is added, a new instance of the template is added to the DOM.\n\t * * When an item is removed, its template instance is removed from the DOM.\n\t * * When items are reordered, their respective templates are reordered in the DOM.\n\t *\n\t * To minimize creation of DOM elements, `ngRepeat` uses a function\n\t * to \"keep track\" of all items in the collection and their corresponding DOM elements.\n\t * For example, if an item is added to the collection, ngRepeat will know that all other items\n\t * already have DOM elements, and will not re-render them.\n\t *\n\t * The default tracking function (which tracks items by their identity) does not allow\n\t * duplicate items in arrays. This is because when there are duplicates, it is not possible\n\t * to maintain a one-to-one mapping between collection items and DOM elements.\n\t *\n\t * If you do need to repeat duplicate items, you can substitute the default tracking behavior\n\t * with your own using the `track by` expression.\n\t *\n\t * For example, you may track items by the index of each item in the collection, using the\n\t * special scope property `$index`:\n\t * ```html\n\t *
\n\t * {{n}}\n\t *
\n\t * ```\n\t *\n\t * You may also use arbitrary expressions in `track by`, including references to custom functions\n\t * on the scope:\n\t * ```html\n\t *
\n\t * {{n}}\n\t *
\n\t * ```\n\t *\n\t *
\n\t * If you are working with objects that have an identifier property, you should track\n\t * by the identifier instead of the whole object. Should you reload your data later, `ngRepeat`\n\t * will not have to rebuild the DOM elements for items it has already rendered, even if the\n\t * JavaScript objects in the collection have been substituted for new ones. For large collections,\n\t * this significantly improves rendering performance. If you don't have a unique identifier,\n\t * `track by $index` can also provide a performance boost.\n\t *
\n\t * ```html\n\t *
\n\t * {{model.name}}\n\t *
\n\t * ```\n\t *\n\t * When no `track by` expression is provided, it is equivalent to tracking by the built-in\n\t * `$id` function, which tracks items by their identity:\n\t * ```html\n\t *
\n\t * {{obj.prop}}\n\t *
\n\t * ```\n\t *\n\t *
\n\t * **Note:** `track by` must always be the last expression:\n\t *
\n\t * ```\n\t *
\n\t * {{model.name}}\n\t *
\n\t * ```\n\t *\n\t * # Special repeat start and end points\n\t * To repeat a series of elements instead of just one parent element, ngRepeat (as well as other ng directives) supports extending\n\t * the range of the repeater by defining explicit start and end points by using **ng-repeat-start** and **ng-repeat-end** respectively.\n\t * The **ng-repeat-start** directive works the same as **ng-repeat**, but will repeat all the HTML code (including the tag it's defined on)\n\t * up to and including the ending HTML tag where **ng-repeat-end** is placed.\n\t *\n\t * The example below makes use of this feature:\n\t * ```html\n\t *
\n\t * Header {{ item }}\n\t *
\n\t *
\n\t * Body {{ item }}\n\t *
\n\t *
\n\t * Footer {{ item }}\n\t *
\n\t * ```\n\t *\n\t * And with an input of {@type ['A','B']} for the items variable in the example above, the output will evaluate to:\n\t * ```html\n\t *
\n\t * Header A\n\t *
\n\t *
\n\t * Body A\n\t *
\n\t *
\n\t * Footer A\n\t *
\n\t *
\n\t * Header B\n\t *
\n\t *
\n\t * Body B\n\t *
\n\t *
\n\t * Footer B\n\t *
\n\t * ```\n\t *\n\t * The custom start and end points for ngRepeat also support all other HTML directive syntax flavors provided in AngularJS (such\n\t * as **data-ng-repeat-start**, **x-ng-repeat-start** and **ng:repeat-start**).\n\t *\n\t * @animations\n\t * | Animation | Occurs |\n\t * |----------------------------------|-------------------------------------|\n\t * | {@link ng.$animate#enter enter} | when a new item is added to the list or when an item is revealed after a filter |\n\t * | {@link ng.$animate#leave leave} | when an item is removed from the list or when an item is filtered out |\n\t * | {@link ng.$animate#move move } | when an adjacent item is filtered out causing a reorder or when the item contents are reordered |\n\t *\n\t * See the example below for defining CSS animations with ngRepeat.\n\t *\n\t * @element ANY\n\t * @scope\n\t * @priority 1000\n\t * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. These\n\t * formats are currently supported:\n\t *\n\t * * `variable in expression` – where variable is the user defined loop variable and `expression`\n\t * is a scope expression giving the collection to enumerate.\n\t *\n\t * For example: `album in artist.albums`.\n\t *\n\t * * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n\t * and `expression` is the scope expression giving the collection to enumerate.\n\t *\n\t * For example: `(name, age) in {'adam':10, 'amalie':12}`.\n\t *\n\t * * `variable in expression track by tracking_expression` – You can also provide an optional tracking expression\n\t * which can be used to associate the objects in the collection with the DOM elements. If no tracking expression\n\t * is specified, ng-repeat associates elements by identity. It is an error to have\n\t * more than one tracking expression value resolve to the same key. (This would mean that two distinct objects are\n\t * mapped to the same DOM element, which is not possible.)\n\t *\n\t * Note that the tracking expression must come last, after any filters, and the alias expression.\n\t *\n\t * For example: `item in items` is equivalent to `item in items track by $id(item)`. This implies that the DOM elements\n\t * will be associated by item identity in the array.\n\t *\n\t * For example: `item in items track by $id(item)`. A built in `$id()` function can be used to assign a unique\n\t * `$$hashKey` property to each item in the array. This property is then used as a key to associated DOM elements\n\t * with the corresponding item in the array by identity. Moving the same object in array would move the DOM\n\t * element in the same way in the DOM.\n\t *\n\t * For example: `item in items track by item.id` is a typical pattern when the items come from the database. In this\n\t * case the object identity does not matter. Two objects are considered equivalent as long as their `id`\n\t * property is same.\n\t *\n\t * For example: `item in items | filter:searchText track by item.id` is a pattern that might be used to apply a filter\n\t * to items in conjunction with a tracking expression.\n\t *\n\t * * `variable in expression as alias_expression` – You can also provide an optional alias expression which will then store the\n\t * intermediate results of the repeater after the filters have been applied. Typically this is used to render a special message\n\t * when a filter is active on the repeater, but the filtered result set is empty.\n\t *\n\t * For example: `item in items | filter:x as results` will store the fragment of the repeated items as `results`, but only after\n\t * the items have been processed through the filter.\n\t *\n\t * Please note that `as [variable name] is not an operator but rather a part of ngRepeat micro-syntax so it can be used only at the end\n\t * (and not as operator, inside an expression).\n\t *\n\t * For example: `item in items | filter : x | orderBy : order | limitTo : limit as results` .\n\t *\n\t * @example\n\t * This example uses `ngRepeat` to display a list of people. A filter is used to restrict the displayed\n\t * results by name. New (entering) and removed (leaving) items are animated.\n\t \n\t \n\t
\n\t I have {{friends.length}} friends. They are:\n\t \n\t
    \n\t
  • \n\t [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n\t
  • \n\t
  • \n\t No results found...\n\t
  • \n\t
\n\t
\n\t
\n\t \n\t angular.module('ngRepeat', ['ngAnimate']).controller('repeatController', function($scope) {\n\t $scope.friends = [\n\t {name:'John', age:25, gender:'boy'},\n\t {name:'Jessie', age:30, gender:'girl'},\n\t {name:'Johanna', age:28, gender:'girl'},\n\t {name:'Joy', age:15, gender:'girl'},\n\t {name:'Mary', age:28, gender:'girl'},\n\t {name:'Peter', age:95, gender:'boy'},\n\t {name:'Sebastian', age:50, gender:'boy'},\n\t {name:'Erika', age:27, gender:'girl'},\n\t {name:'Patrick', age:40, gender:'boy'},\n\t {name:'Samantha', age:60, gender:'girl'}\n\t ];\n\t });\n\t \n\t \n\t .example-animate-container {\n\t background:white;\n\t border:1px solid black;\n\t list-style:none;\n\t margin:0;\n\t padding:0 10px;\n\t }\n\t\n\t .animate-repeat {\n\t line-height:30px;\n\t list-style:none;\n\t box-sizing:border-box;\n\t }\n\t\n\t .animate-repeat.ng-move,\n\t .animate-repeat.ng-enter,\n\t .animate-repeat.ng-leave {\n\t transition:all linear 0.5s;\n\t }\n\t\n\t .animate-repeat.ng-leave.ng-leave-active,\n\t .animate-repeat.ng-move,\n\t .animate-repeat.ng-enter {\n\t opacity:0;\n\t max-height:0;\n\t }\n\t\n\t .animate-repeat.ng-leave,\n\t .animate-repeat.ng-move.ng-move-active,\n\t .animate-repeat.ng-enter.ng-enter-active {\n\t opacity:1;\n\t max-height:30px;\n\t }\n\t \n\t \n\t var friends = element.all(by.repeater('friend in friends'));\n\t\n\t it('should render initial data set', function() {\n\t expect(friends.count()).toBe(10);\n\t expect(friends.get(0).getText()).toEqual('[1] John who is 25 years old.');\n\t expect(friends.get(1).getText()).toEqual('[2] Jessie who is 30 years old.');\n\t expect(friends.last().getText()).toEqual('[10] Samantha who is 60 years old.');\n\t expect(element(by.binding('friends.length')).getText())\n\t .toMatch(\"I have 10 friends. They are:\");\n\t });\n\t\n\t it('should update repeater when filter predicate changes', function() {\n\t expect(friends.count()).toBe(10);\n\t\n\t element(by.model('q')).sendKeys('ma');\n\t\n\t expect(friends.count()).toBe(2);\n\t expect(friends.get(0).getText()).toEqual('[1] Mary who is 28 years old.');\n\t expect(friends.last().getText()).toEqual('[2] Samantha who is 60 years old.');\n\t });\n\t \n\t
\n\t */\n\tvar ngRepeatDirective = ['$parse', '$animate', '$compile', function($parse, $animate, $compile) {\n\t var NG_REMOVED = '$$NG_REMOVED';\n\t var ngRepeatMinErr = minErr('ngRepeat');\n\t\n\t var updateScope = function(scope, index, valueIdentifier, value, keyIdentifier, key, arrayLength) {\n\t // TODO(perf): generate setters to shave off ~40ms or 1-1.5%\n\t scope[valueIdentifier] = value;\n\t if (keyIdentifier) scope[keyIdentifier] = key;\n\t scope.$index = index;\n\t scope.$first = (index === 0);\n\t scope.$last = (index === (arrayLength - 1));\n\t scope.$middle = !(scope.$first || scope.$last);\n\t // jshint bitwise: false\n\t scope.$odd = !(scope.$even = (index&1) === 0);\n\t // jshint bitwise: true\n\t };\n\t\n\t var getBlockStart = function(block) {\n\t return block.clone[0];\n\t };\n\t\n\t var getBlockEnd = function(block) {\n\t return block.clone[block.clone.length - 1];\n\t };\n\t\n\t\n\t return {\n\t restrict: 'A',\n\t multiElement: true,\n\t transclude: 'element',\n\t priority: 1000,\n\t terminal: true,\n\t $$tlb: true,\n\t compile: function ngRepeatCompile($element, $attr) {\n\t var expression = $attr.ngRepeat;\n\t var ngRepeatEndComment = $compile.$$createComment('end ngRepeat', expression);\n\t\n\t var match = expression.match(/^\\s*([\\s\\S]+?)\\s+in\\s+([\\s\\S]+?)(?:\\s+as\\s+([\\s\\S]+?))?(?:\\s+track\\s+by\\s+([\\s\\S]+?))?\\s*$/);\n\t\n\t if (!match) {\n\t throw ngRepeatMinErr('iexp', \"Expected expression in form of '_item_ in _collection_[ track by _id_]' but got '{0}'.\",\n\t expression);\n\t }\n\t\n\t var lhs = match[1];\n\t var rhs = match[2];\n\t var aliasAs = match[3];\n\t var trackByExp = match[4];\n\t\n\t match = lhs.match(/^(?:(\\s*[\\$\\w]+)|\\(\\s*([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\s*\\))$/);\n\t\n\t if (!match) {\n\t throw ngRepeatMinErr('iidexp', \"'_item_' in '_item_ in _collection_' should be an identifier or '(_key_, _value_)' expression, but got '{0}'.\",\n\t lhs);\n\t }\n\t var valueIdentifier = match[3] || match[1];\n\t var keyIdentifier = match[2];\n\t\n\t if (aliasAs && (!/^[$a-zA-Z_][$a-zA-Z0-9_]*$/.test(aliasAs) ||\n\t /^(null|undefined|this|\\$index|\\$first|\\$middle|\\$last|\\$even|\\$odd|\\$parent|\\$root|\\$id)$/.test(aliasAs))) {\n\t throw ngRepeatMinErr('badident', \"alias '{0}' is invalid --- must be a valid JS identifier which is not a reserved name.\",\n\t aliasAs);\n\t }\n\t\n\t var trackByExpGetter, trackByIdExpFn, trackByIdArrayFn, trackByIdObjFn;\n\t var hashFnLocals = {$id: hashKey};\n\t\n\t if (trackByExp) {\n\t trackByExpGetter = $parse(trackByExp);\n\t } else {\n\t trackByIdArrayFn = function(key, value) {\n\t return hashKey(value);\n\t };\n\t trackByIdObjFn = function(key) {\n\t return key;\n\t };\n\t }\n\t\n\t return function ngRepeatLink($scope, $element, $attr, ctrl, $transclude) {\n\t\n\t if (trackByExpGetter) {\n\t trackByIdExpFn = function(key, value, index) {\n\t // assign key, value, and $index to the locals so that they can be used in hash functions\n\t if (keyIdentifier) hashFnLocals[keyIdentifier] = key;\n\t hashFnLocals[valueIdentifier] = value;\n\t hashFnLocals.$index = index;\n\t return trackByExpGetter($scope, hashFnLocals);\n\t };\n\t }\n\t\n\t // Store a list of elements from previous run. This is a hash where key is the item from the\n\t // iterator, and the value is objects with following properties.\n\t // - scope: bound scope\n\t // - element: previous element.\n\t // - index: position\n\t //\n\t // We are using no-proto object so that we don't need to guard against inherited props via\n\t // hasOwnProperty.\n\t var lastBlockMap = createMap();\n\t\n\t //watch props\n\t $scope.$watchCollection(rhs, function ngRepeatAction(collection) {\n\t var index, length,\n\t previousNode = $element[0], // node that cloned nodes should be inserted after\n\t // initialized to the comment node anchor\n\t nextNode,\n\t // Same as lastBlockMap but it has the current state. It will become the\n\t // lastBlockMap on the next iteration.\n\t nextBlockMap = createMap(),\n\t collectionLength,\n\t key, value, // key/value of iteration\n\t trackById,\n\t trackByIdFn,\n\t collectionKeys,\n\t block, // last object information {scope, element, id}\n\t nextBlockOrder,\n\t elementsToRemove;\n\t\n\t if (aliasAs) {\n\t $scope[aliasAs] = collection;\n\t }\n\t\n\t if (isArrayLike(collection)) {\n\t collectionKeys = collection;\n\t trackByIdFn = trackByIdExpFn || trackByIdArrayFn;\n\t } else {\n\t trackByIdFn = trackByIdExpFn || trackByIdObjFn;\n\t // if object, extract keys, in enumeration order, unsorted\n\t collectionKeys = [];\n\t for (var itemKey in collection) {\n\t if (hasOwnProperty.call(collection, itemKey) && itemKey.charAt(0) !== '$') {\n\t collectionKeys.push(itemKey);\n\t }\n\t }\n\t }\n\t\n\t collectionLength = collectionKeys.length;\n\t nextBlockOrder = new Array(collectionLength);\n\t\n\t // locate existing items\n\t for (index = 0; index < collectionLength; index++) {\n\t key = (collection === collectionKeys) ? index : collectionKeys[index];\n\t value = collection[key];\n\t trackById = trackByIdFn(key, value, index);\n\t if (lastBlockMap[trackById]) {\n\t // found previously seen block\n\t block = lastBlockMap[trackById];\n\t delete lastBlockMap[trackById];\n\t nextBlockMap[trackById] = block;\n\t nextBlockOrder[index] = block;\n\t } else if (nextBlockMap[trackById]) {\n\t // if collision detected. restore lastBlockMap and throw an error\n\t forEach(nextBlockOrder, function(block) {\n\t if (block && block.scope) lastBlockMap[block.id] = block;\n\t });\n\t throw ngRepeatMinErr('dupes',\n\t \"Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}, Duplicate value: {2}\",\n\t expression, trackById, value);\n\t } else {\n\t // new never before seen block\n\t nextBlockOrder[index] = {id: trackById, scope: undefined, clone: undefined};\n\t nextBlockMap[trackById] = true;\n\t }\n\t }\n\t\n\t // remove leftover items\n\t for (var blockKey in lastBlockMap) {\n\t block = lastBlockMap[blockKey];\n\t elementsToRemove = getBlockNodes(block.clone);\n\t $animate.leave(elementsToRemove);\n\t if (elementsToRemove[0].parentNode) {\n\t // if the element was not removed yet because of pending animation, mark it as deleted\n\t // so that we can ignore it later\n\t for (index = 0, length = elementsToRemove.length; index < length; index++) {\n\t elementsToRemove[index][NG_REMOVED] = true;\n\t }\n\t }\n\t block.scope.$destroy();\n\t }\n\t\n\t // we are not using forEach for perf reasons (trying to avoid #call)\n\t for (index = 0; index < collectionLength; index++) {\n\t key = (collection === collectionKeys) ? index : collectionKeys[index];\n\t value = collection[key];\n\t block = nextBlockOrder[index];\n\t\n\t if (block.scope) {\n\t // if we have already seen this object, then we need to reuse the\n\t // associated scope/element\n\t\n\t nextNode = previousNode;\n\t\n\t // skip nodes that are already pending removal via leave animation\n\t do {\n\t nextNode = nextNode.nextSibling;\n\t } while (nextNode && nextNode[NG_REMOVED]);\n\t\n\t if (getBlockStart(block) != nextNode) {\n\t // existing item which got moved\n\t $animate.move(getBlockNodes(block.clone), null, previousNode);\n\t }\n\t previousNode = getBlockEnd(block);\n\t updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength);\n\t } else {\n\t // new item which we don't know about\n\t $transclude(function ngRepeatTransclude(clone, scope) {\n\t block.scope = scope;\n\t // http://jsperf.com/clone-vs-createcomment\n\t var endNode = ngRepeatEndComment.cloneNode(false);\n\t clone[clone.length++] = endNode;\n\t\n\t $animate.enter(clone, null, previousNode);\n\t previousNode = endNode;\n\t // Note: We only need the first/last node of the cloned nodes.\n\t // However, we need to keep the reference to the jqlite wrapper as it might be changed later\n\t // by a directive with templateUrl when its template arrives.\n\t block.clone = clone;\n\t nextBlockMap[block.id] = block;\n\t updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength);\n\t });\n\t }\n\t }\n\t lastBlockMap = nextBlockMap;\n\t });\n\t };\n\t }\n\t };\n\t}];\n\t\n\tvar NG_HIDE_CLASS = 'ng-hide';\n\tvar NG_HIDE_IN_PROGRESS_CLASS = 'ng-hide-animate';\n\t/**\n\t * @ngdoc directive\n\t * @name ngShow\n\t * @multiElement\n\t *\n\t * @description\n\t * The `ngShow` directive shows or hides the given HTML element based on the expression\n\t * provided to the `ngShow` attribute. The element is shown or hidden by removing or adding\n\t * the `.ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined\n\t * in AngularJS and sets the display style to none (using an !important flag).\n\t * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).\n\t *\n\t * ```html\n\t * \n\t *
\n\t *\n\t * \n\t *
\n\t * ```\n\t *\n\t * When the `ngShow` expression evaluates to a falsy value then the `.ng-hide` CSS class is added to the class\n\t * attribute on the element causing it to become hidden. When truthy, the `.ng-hide` CSS class is removed\n\t * from the element causing the element not to appear hidden.\n\t *\n\t * ## Why is !important used?\n\t *\n\t * You may be wondering why !important is used for the `.ng-hide` CSS class. This is because the `.ng-hide` selector\n\t * can be easily overridden by heavier selectors. For example, something as simple\n\t * as changing the display style on a HTML list item would make hidden elements appear visible.\n\t * This also becomes a bigger issue when dealing with CSS frameworks.\n\t *\n\t * By using !important, the show and hide behavior will work as expected despite any clash between CSS selector\n\t * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the\n\t * styling to change how to hide an element then it is just a matter of using !important in their own CSS code.\n\t *\n\t * ### Overriding `.ng-hide`\n\t *\n\t * By default, the `.ng-hide` class will style the element with `display: none!important`. If you wish to change\n\t * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`\n\t * class CSS. Note that the selector that needs to be used is actually `.ng-hide:not(.ng-hide-animate)` to cope\n\t * with extra animation classes that can be added.\n\t *\n\t * ```css\n\t * .ng-hide:not(.ng-hide-animate) {\n\t * /* this is just another form of hiding an element */\n\t * display: block!important;\n\t * position: absolute;\n\t * top: -9999px;\n\t * left: -9999px;\n\t * }\n\t * ```\n\t *\n\t * By default you don't need to override in CSS anything and the animations will work around the display style.\n\t *\n\t * ## A note about animations with `ngShow`\n\t *\n\t * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression\n\t * is true and false. This system works like the animation system present with ngClass except that\n\t * you must also include the !important flag to override the display property\n\t * so that you can perform an animation when the element is hidden during the time of the animation.\n\t *\n\t * ```css\n\t * //\n\t * //a working example can be found at the bottom of this page\n\t * //\n\t * .my-element.ng-hide-add, .my-element.ng-hide-remove {\n\t * /* this is required as of 1.3x to properly\n\t * apply all styling in a show/hide animation */\n\t * transition: 0s linear all;\n\t * }\n\t *\n\t * .my-element.ng-hide-add-active,\n\t * .my-element.ng-hide-remove-active {\n\t * /* the transition is defined in the active class */\n\t * transition: 1s linear all;\n\t * }\n\t *\n\t * .my-element.ng-hide-add { ... }\n\t * .my-element.ng-hide-add.ng-hide-add-active { ... }\n\t * .my-element.ng-hide-remove { ... }\n\t * .my-element.ng-hide-remove.ng-hide-remove-active { ... }\n\t * ```\n\t *\n\t * Keep in mind that, as of AngularJS version 1.3, there is no need to change the display\n\t * property to block during animation states--ngAnimate will handle the style toggling automatically for you.\n\t *\n\t * @animations\n\t * | Animation | Occurs |\n\t * |----------------------------------|-------------------------------------|\n\t * | {@link $animate#addClass addClass} `.ng-hide` | after the `ngShow` expression evaluates to a non truthy value and just before the contents are set to hidden |\n\t * | {@link $animate#removeClass removeClass} `.ng-hide` | after the `ngShow` expression evaluates to a truthy value and just before contents are set to visible |\n\t *\n\t * @element ANY\n\t * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n\t * then the element is shown or hidden respectively.\n\t *\n\t * @example\n\t \n\t \n\t Click me:
\n\t
\n\t Show:\n\t
\n\t I show up when your checkbox is checked.\n\t
\n\t
\n\t
\n\t Hide:\n\t
\n\t I hide when your checkbox is checked.\n\t
\n\t
\n\t
\n\t \n\t @import url(../../components/bootstrap-3.1.1/css/bootstrap.css);\n\t \n\t \n\t .animate-show {\n\t line-height: 20px;\n\t opacity: 1;\n\t padding: 10px;\n\t border: 1px solid black;\n\t background: white;\n\t }\n\t\n\t .animate-show.ng-hide-add, .animate-show.ng-hide-remove {\n\t transition: all linear 0.5s;\n\t }\n\t\n\t .animate-show.ng-hide {\n\t line-height: 0;\n\t opacity: 0;\n\t padding: 0 10px;\n\t }\n\t\n\t .check-element {\n\t padding: 10px;\n\t border: 1px solid black;\n\t background: white;\n\t }\n\t \n\t \n\t var thumbsUp = element(by.css('span.glyphicon-thumbs-up'));\n\t var thumbsDown = element(by.css('span.glyphicon-thumbs-down'));\n\t\n\t it('should check ng-show / ng-hide', function() {\n\t expect(thumbsUp.isDisplayed()).toBeFalsy();\n\t expect(thumbsDown.isDisplayed()).toBeTruthy();\n\t\n\t element(by.model('checked')).click();\n\t\n\t expect(thumbsUp.isDisplayed()).toBeTruthy();\n\t expect(thumbsDown.isDisplayed()).toBeFalsy();\n\t });\n\t \n\t
\n\t */\n\tvar ngShowDirective = ['$animate', function($animate) {\n\t return {\n\t restrict: 'A',\n\t multiElement: true,\n\t link: function(scope, element, attr) {\n\t scope.$watch(attr.ngShow, function ngShowWatchAction(value) {\n\t // we're adding a temporary, animation-specific class for ng-hide since this way\n\t // we can control when the element is actually displayed on screen without having\n\t // to have a global/greedy CSS selector that breaks when other animations are run.\n\t // Read: https://github.com/angular/angular.js/issues/9103#issuecomment-58335845\n\t $animate[value ? 'removeClass' : 'addClass'](element, NG_HIDE_CLASS, {\n\t tempClasses: NG_HIDE_IN_PROGRESS_CLASS\n\t });\n\t });\n\t }\n\t };\n\t}];\n\t\n\t\n\t/**\n\t * @ngdoc directive\n\t * @name ngHide\n\t * @multiElement\n\t *\n\t * @description\n\t * The `ngHide` directive shows or hides the given HTML element based on the expression\n\t * provided to the `ngHide` attribute. The element is shown or hidden by removing or adding\n\t * the `ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined\n\t * in AngularJS and sets the display style to none (using an !important flag).\n\t * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).\n\t *\n\t * ```html\n\t * \n\t *
\n\t *\n\t * \n\t *
\n\t * ```\n\t *\n\t * When the `ngHide` expression evaluates to a truthy value then the `.ng-hide` CSS class is added to the class\n\t * attribute on the element causing it to become hidden. When falsy, the `.ng-hide` CSS class is removed\n\t * from the element causing the element not to appear hidden.\n\t *\n\t * ## Why is !important used?\n\t *\n\t * You may be wondering why !important is used for the `.ng-hide` CSS class. This is because the `.ng-hide` selector\n\t * can be easily overridden by heavier selectors. For example, something as simple\n\t * as changing the display style on a HTML list item would make hidden elements appear visible.\n\t * This also becomes a bigger issue when dealing with CSS frameworks.\n\t *\n\t * By using !important, the show and hide behavior will work as expected despite any clash between CSS selector\n\t * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the\n\t * styling to change how to hide an element then it is just a matter of using !important in their own CSS code.\n\t *\n\t * ### Overriding `.ng-hide`\n\t *\n\t * By default, the `.ng-hide` class will style the element with `display: none!important`. If you wish to change\n\t * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`\n\t * class in CSS:\n\t *\n\t * ```css\n\t * .ng-hide {\n\t * /* this is just another form of hiding an element */\n\t * display: block!important;\n\t * position: absolute;\n\t * top: -9999px;\n\t * left: -9999px;\n\t * }\n\t * ```\n\t *\n\t * By default you don't need to override in CSS anything and the animations will work around the display style.\n\t *\n\t * ## A note about animations with `ngHide`\n\t *\n\t * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression\n\t * is true and false. This system works like the animation system present with ngClass, except that the `.ng-hide`\n\t * CSS class is added and removed for you instead of your own CSS class.\n\t *\n\t * ```css\n\t * //\n\t * //a working example can be found at the bottom of this page\n\t * //\n\t * .my-element.ng-hide-add, .my-element.ng-hide-remove {\n\t * transition: 0.5s linear all;\n\t * }\n\t *\n\t * .my-element.ng-hide-add { ... }\n\t * .my-element.ng-hide-add.ng-hide-add-active { ... }\n\t * .my-element.ng-hide-remove { ... }\n\t * .my-element.ng-hide-remove.ng-hide-remove-active { ... }\n\t * ```\n\t *\n\t * Keep in mind that, as of AngularJS version 1.3, there is no need to change the display\n\t * property to block during animation states--ngAnimate will handle the style toggling automatically for you.\n\t *\n\t * @animations\n\t * | Animation | Occurs |\n\t * |----------------------------------|-------------------------------------|\n\t * | {@link $animate#addClass addClass} `.ng-hide` | after the `ngHide` expression evaluates to a truthy value and just before the contents are set to hidden |\n\t * | {@link $animate#removeClass removeClass} `.ng-hide` | after the `ngHide` expression evaluates to a non truthy value and just before contents are set to visible |\n\t *\n\t *\n\t * @element ANY\n\t * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n\t * the element is shown or hidden respectively.\n\t *\n\t * @example\n\t \n\t \n\t Click me:
\n\t
\n\t Show:\n\t
\n\t I show up when your checkbox is checked.\n\t
\n\t
\n\t
\n\t Hide:\n\t
\n\t I hide when your checkbox is checked.\n\t
\n\t
\n\t
\n\t \n\t @import url(../../components/bootstrap-3.1.1/css/bootstrap.css);\n\t \n\t \n\t .animate-hide {\n\t transition: all linear 0.5s;\n\t line-height: 20px;\n\t opacity: 1;\n\t padding: 10px;\n\t border: 1px solid black;\n\t background: white;\n\t }\n\t\n\t .animate-hide.ng-hide {\n\t line-height: 0;\n\t opacity: 0;\n\t padding: 0 10px;\n\t }\n\t\n\t .check-element {\n\t padding: 10px;\n\t border: 1px solid black;\n\t background: white;\n\t }\n\t \n\t \n\t var thumbsUp = element(by.css('span.glyphicon-thumbs-up'));\n\t var thumbsDown = element(by.css('span.glyphicon-thumbs-down'));\n\t\n\t it('should check ng-show / ng-hide', function() {\n\t expect(thumbsUp.isDisplayed()).toBeFalsy();\n\t expect(thumbsDown.isDisplayed()).toBeTruthy();\n\t\n\t element(by.model('checked')).click();\n\t\n\t expect(thumbsUp.isDisplayed()).toBeTruthy();\n\t expect(thumbsDown.isDisplayed()).toBeFalsy();\n\t });\n\t \n\t
\n\t */\n\tvar ngHideDirective = ['$animate', function($animate) {\n\t return {\n\t restrict: 'A',\n\t multiElement: true,\n\t link: function(scope, element, attr) {\n\t scope.$watch(attr.ngHide, function ngHideWatchAction(value) {\n\t // The comment inside of the ngShowDirective explains why we add and\n\t // remove a temporary class for the show/hide animation\n\t $animate[value ? 'addClass' : 'removeClass'](element,NG_HIDE_CLASS, {\n\t tempClasses: NG_HIDE_IN_PROGRESS_CLASS\n\t });\n\t });\n\t }\n\t };\n\t}];\n\t\n\t/**\n\t * @ngdoc directive\n\t * @name ngStyle\n\t * @restrict AC\n\t *\n\t * @description\n\t * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n\t *\n\t * @knownIssue\n\t * You should not use {@link guide/interpolation interpolation} in the value of the `style`\n\t * attribute, when using the `ngStyle` directive on the same element.\n\t * See {@link guide/interpolation#known-issues here} for more info.\n\t *\n\t * @element ANY\n\t * @param {expression} ngStyle\n\t *\n\t * {@link guide/expression Expression} which evals to an\n\t * object whose keys are CSS style names and values are corresponding values for those CSS\n\t * keys.\n\t *\n\t * Since some CSS style names are not valid keys for an object, they must be quoted.\n\t * See the 'background-color' style in the example below.\n\t *\n\t * @example\n\t \n\t \n\t \n\t \n\t \n\t
\n\t Sample Text\n\t
myStyle={{myStyle}}
\n\t
\n\t \n\t span {\n\t color: black;\n\t }\n\t \n\t \n\t var colorSpan = element(by.css('span'));\n\t\n\t it('should check ng-style', function() {\n\t expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)');\n\t element(by.css('input[value=\\'set color\\']')).click();\n\t expect(colorSpan.getCssValue('color')).toBe('rgba(255, 0, 0, 1)');\n\t element(by.css('input[value=clear]')).click();\n\t expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)');\n\t });\n\t \n\t
\n\t */\n\tvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n\t scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n\t if (oldStyles && (newStyles !== oldStyles)) {\n\t forEach(oldStyles, function(val, style) { element.css(style, '');});\n\t }\n\t if (newStyles) element.css(newStyles);\n\t }, true);\n\t});\n\t\n\t/**\n\t * @ngdoc directive\n\t * @name ngSwitch\n\t * @restrict EA\n\t *\n\t * @description\n\t * The `ngSwitch` directive is used to conditionally swap DOM structure on your template based on a scope expression.\n\t * Elements within `ngSwitch` but without `ngSwitchWhen` or `ngSwitchDefault` directives will be preserved at the location\n\t * as specified in the template.\n\t *\n\t * The directive itself works similar to ngInclude, however, instead of downloading template code (or loading it\n\t * from the template cache), `ngSwitch` simply chooses one of the nested elements and makes it visible based on which element\n\t * matches the value obtained from the evaluated expression. In other words, you define a container element\n\t * (where you place the directive), place an expression on the **`on=\"...\"` attribute**\n\t * (or the **`ng-switch=\"...\"` attribute**), define any inner elements inside of the directive and place\n\t * a when attribute per element. The when attribute is used to inform ngSwitch which element to display when the on\n\t * expression is evaluated. If a matching expression is not found via a when attribute then an element with the default\n\t * attribute is displayed.\n\t *\n\t *
\n\t * Be aware that the attribute values to match against cannot be expressions. They are interpreted\n\t * as literal string values to match against.\n\t * For example, **`ng-switch-when=\"someVal\"`** will match against the string `\"someVal\"` not against the\n\t * value of the expression `$scope.someVal`.\n\t *
\n\t\n\t * @animations\n\t * | Animation | Occurs |\n\t * |----------------------------------|-------------------------------------|\n\t * | {@link ng.$animate#enter enter} | after the ngSwitch contents change and the matched child element is placed inside the container |\n\t * | {@link ng.$animate#leave leave} | after the ngSwitch contents change and just before the former contents are removed from the DOM |\n\t *\n\t * @usage\n\t *\n\t * ```\n\t * \n\t * ...\n\t * ...\n\t * ...\n\t * \n\t * ```\n\t *\n\t *\n\t * @scope\n\t * @priority 1200\n\t * @param {*} ngSwitch|on expression to match against ng-switch-when.\n\t * On child elements add:\n\t *\n\t * * `ngSwitchWhen`: the case statement to match against. If match then this\n\t * case will be displayed. If the same match appears multiple times, all the\n\t * elements will be displayed.\n\t * * `ngSwitchDefault`: the default case when no other case match. If there\n\t * are multiple default cases, all of them will be displayed when no other\n\t * case match.\n\t *\n\t *\n\t * @example\n\t \n\t \n\t
\n\t \n\t selection={{selection}}\n\t
\n\t
\n\t
Settings Div
\n\t
Home Span
\n\t
default
\n\t
\n\t
\n\t
\n\t \n\t angular.module('switchExample', ['ngAnimate'])\n\t .controller('ExampleController', ['$scope', function($scope) {\n\t $scope.items = ['settings', 'home', 'other'];\n\t $scope.selection = $scope.items[0];\n\t }]);\n\t \n\t \n\t .animate-switch-container {\n\t position:relative;\n\t background:white;\n\t border:1px solid black;\n\t height:40px;\n\t overflow:hidden;\n\t }\n\t\n\t .animate-switch {\n\t padding:10px;\n\t }\n\t\n\t .animate-switch.ng-animate {\n\t transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n\t\n\t position:absolute;\n\t top:0;\n\t left:0;\n\t right:0;\n\t bottom:0;\n\t }\n\t\n\t .animate-switch.ng-leave.ng-leave-active,\n\t .animate-switch.ng-enter {\n\t top:-50px;\n\t }\n\t .animate-switch.ng-leave,\n\t .animate-switch.ng-enter.ng-enter-active {\n\t top:0;\n\t }\n\t \n\t \n\t var switchElem = element(by.css('[ng-switch]'));\n\t var select = element(by.model('selection'));\n\t\n\t it('should start in settings', function() {\n\t expect(switchElem.getText()).toMatch(/Settings Div/);\n\t });\n\t it('should change to home', function() {\n\t select.all(by.css('option')).get(1).click();\n\t expect(switchElem.getText()).toMatch(/Home Span/);\n\t });\n\t it('should select default', function() {\n\t select.all(by.css('option')).get(2).click();\n\t expect(switchElem.getText()).toMatch(/default/);\n\t });\n\t \n\t
\n\t */\n\tvar ngSwitchDirective = ['$animate', '$compile', function($animate, $compile) {\n\t return {\n\t require: 'ngSwitch',\n\t\n\t // asks for $scope to fool the BC controller module\n\t controller: ['$scope', function ngSwitchController() {\n\t this.cases = {};\n\t }],\n\t link: function(scope, element, attr, ngSwitchController) {\n\t var watchExpr = attr.ngSwitch || attr.on,\n\t selectedTranscludes = [],\n\t selectedElements = [],\n\t previousLeaveAnimations = [],\n\t selectedScopes = [];\n\t\n\t var spliceFactory = function(array, index) {\n\t return function() { array.splice(index, 1); };\n\t };\n\t\n\t scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n\t var i, ii;\n\t for (i = 0, ii = previousLeaveAnimations.length; i < ii; ++i) {\n\t $animate.cancel(previousLeaveAnimations[i]);\n\t }\n\t previousLeaveAnimations.length = 0;\n\t\n\t for (i = 0, ii = selectedScopes.length; i < ii; ++i) {\n\t var selected = getBlockNodes(selectedElements[i].clone);\n\t selectedScopes[i].$destroy();\n\t var promise = previousLeaveAnimations[i] = $animate.leave(selected);\n\t promise.then(spliceFactory(previousLeaveAnimations, i));\n\t }\n\t\n\t selectedElements.length = 0;\n\t selectedScopes.length = 0;\n\t\n\t if ((selectedTranscludes = ngSwitchController.cases['!' + value] || ngSwitchController.cases['?'])) {\n\t forEach(selectedTranscludes, function(selectedTransclude) {\n\t selectedTransclude.transclude(function(caseElement, selectedScope) {\n\t selectedScopes.push(selectedScope);\n\t var anchor = selectedTransclude.element;\n\t caseElement[caseElement.length++] = $compile.$$createComment('end ngSwitchWhen');\n\t var block = { clone: caseElement };\n\t\n\t selectedElements.push(block);\n\t $animate.enter(caseElement, anchor.parent(), anchor);\n\t });\n\t });\n\t }\n\t });\n\t }\n\t };\n\t}];\n\t\n\tvar ngSwitchWhenDirective = ngDirective({\n\t transclude: 'element',\n\t priority: 1200,\n\t require: '^ngSwitch',\n\t multiElement: true,\n\t link: function(scope, element, attrs, ctrl, $transclude) {\n\t ctrl.cases['!' + attrs.ngSwitchWhen] = (ctrl.cases['!' + attrs.ngSwitchWhen] || []);\n\t ctrl.cases['!' + attrs.ngSwitchWhen].push({ transclude: $transclude, element: element });\n\t }\n\t});\n\t\n\tvar ngSwitchDefaultDirective = ngDirective({\n\t transclude: 'element',\n\t priority: 1200,\n\t require: '^ngSwitch',\n\t multiElement: true,\n\t link: function(scope, element, attr, ctrl, $transclude) {\n\t ctrl.cases['?'] = (ctrl.cases['?'] || []);\n\t ctrl.cases['?'].push({ transclude: $transclude, element: element });\n\t }\n\t});\n\t\n\t/**\n\t * @ngdoc directive\n\t * @name ngTransclude\n\t * @restrict EAC\n\t *\n\t * @description\n\t * Directive that marks the insertion point for the transcluded DOM of the nearest parent directive that uses transclusion.\n\t *\n\t * You can specify that you want to insert a named transclusion slot, instead of the default slot, by providing the slot name\n\t * as the value of the `ng-transclude` or `ng-transclude-slot` attribute.\n\t *\n\t * If the transcluded content is not empty (i.e. contains one or more DOM nodes, including whitespace text nodes), any existing\n\t * content of this element will be removed before the transcluded content is inserted.\n\t * If the transcluded content is empty, the existing content is left intact. This lets you provide fallback content in the case\n\t * that no transcluded content is provided.\n\t *\n\t * @element ANY\n\t *\n\t * @param {string} ngTransclude|ngTranscludeSlot the name of the slot to insert at this point. If this is not provided, is empty\n\t * or its value is the same as the name of the attribute then the default slot is used.\n\t *\n\t * @example\n\t * ### Basic transclusion\n\t * This example demonstrates basic transclusion of content into a component directive.\n\t * \n\t * \n\t * \n\t *
\n\t *
\n\t *
\n\t * {{text}}\n\t *
\n\t *
\n\t * \n\t * it('should have transcluded', function() {\n\t * var titleElement = element(by.model('title'));\n\t * titleElement.clear();\n\t * titleElement.sendKeys('TITLE');\n\t * var textElement = element(by.model('text'));\n\t * textElement.clear();\n\t * textElement.sendKeys('TEXT');\n\t * expect(element(by.binding('title')).getText()).toEqual('TITLE');\n\t * expect(element(by.binding('text')).getText()).toEqual('TEXT');\n\t * });\n\t * \n\t *
\n\t *\n\t * @example\n\t * ### Transclude fallback content\n\t * This example shows how to use `NgTransclude` with fallback content, that\n\t * is displayed if no transcluded content is provided.\n\t *\n\t * \n\t * \n\t * \n\t * \n\t * \n\t * \n\t * \n\t * Button2\n\t * \n\t * \n\t * \n\t * it('should have different transclude element content', function() {\n\t * expect(element(by.id('fallback')).getText()).toBe('Button1');\n\t * expect(element(by.id('modified')).getText()).toBe('Button2');\n\t * });\n\t * \n\t * \n\t *\n\t * @example\n\t * ### Multi-slot transclusion\n\t * This example demonstrates using multi-slot transclusion in a component directive.\n\t * \n\t * \n\t * \n\t *
\n\t *
\n\t *
\n\t * \n\t * {{title}}\n\t *

{{text}}

\n\t *
\n\t *
\n\t *
\n\t * \n\t * angular.module('multiSlotTranscludeExample', [])\n\t * .directive('pane', function(){\n\t * return {\n\t * restrict: 'E',\n\t * transclude: {\n\t * 'title': '?paneTitle',\n\t * 'body': 'paneBody',\n\t * 'footer': '?paneFooter'\n\t * },\n\t * template: '
' +\n\t * '
Fallback Title
' +\n\t * '
' +\n\t * '
Fallback Footer
' +\n\t * '
'\n\t * };\n\t * })\n\t * .controller('ExampleController', ['$scope', function($scope) {\n\t * $scope.title = 'Lorem Ipsum';\n\t * $scope.link = \"https://google.com\";\n\t * $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n\t * }]);\n\t *
\n\t * \n\t * it('should have transcluded the title and the body', function() {\n\t * var titleElement = element(by.model('title'));\n\t * titleElement.clear();\n\t * titleElement.sendKeys('TITLE');\n\t * var textElement = element(by.model('text'));\n\t * textElement.clear();\n\t * textElement.sendKeys('TEXT');\n\t * expect(element(by.css('.title')).getText()).toEqual('TITLE');\n\t * expect(element(by.binding('text')).getText()).toEqual('TEXT');\n\t * expect(element(by.css('.footer')).getText()).toEqual('Fallback Footer');\n\t * });\n\t * \n\t *
\n\t */\n\tvar ngTranscludeMinErr = minErr('ngTransclude');\n\tvar ngTranscludeDirective = ['$compile', function($compile) {\n\t return {\n\t restrict: 'EAC',\n\t terminal: true,\n\t compile: function ngTranscludeCompile(tElement) {\n\t\n\t // Remove and cache any original content to act as a fallback\n\t var fallbackLinkFn = $compile(tElement.contents());\n\t tElement.empty();\n\t\n\t return function ngTranscludePostLink($scope, $element, $attrs, controller, $transclude) {\n\t\n\t if (!$transclude) {\n\t throw ngTranscludeMinErr('orphan',\n\t 'Illegal use of ngTransclude directive in the template! ' +\n\t 'No parent directive that requires a transclusion found. ' +\n\t 'Element: {0}',\n\t startingTag($element));\n\t }\n\t\n\t\n\t // If the attribute is of the form: `ng-transclude=\"ng-transclude\"` then treat it like the default\n\t if ($attrs.ngTransclude === $attrs.$attr.ngTransclude) {\n\t $attrs.ngTransclude = '';\n\t }\n\t var slotName = $attrs.ngTransclude || $attrs.ngTranscludeSlot;\n\t\n\t // If the slot is required and no transclusion content is provided then this call will throw an error\n\t $transclude(ngTranscludeCloneAttachFn, null, slotName);\n\t\n\t // If the slot is optional and no transclusion content is provided then use the fallback content\n\t if (slotName && !$transclude.isSlotFilled(slotName)) {\n\t useFallbackContent();\n\t }\n\t\n\t function ngTranscludeCloneAttachFn(clone, transcludedScope) {\n\t if (clone.length) {\n\t $element.append(clone);\n\t } else {\n\t useFallbackContent();\n\t // There is nothing linked against the transcluded scope since no content was available,\n\t // so it should be safe to clean up the generated scope.\n\t transcludedScope.$destroy();\n\t }\n\t }\n\t\n\t function useFallbackContent() {\n\t // Since this is the fallback content rather than the transcluded content,\n\t // we link against the scope of this directive rather than the transcluded scope\n\t fallbackLinkFn($scope, function(clone) {\n\t $element.append(clone);\n\t });\n\t }\n\t };\n\t }\n\t };\n\t}];\n\t\n\t/**\n\t * @ngdoc directive\n\t * @name script\n\t * @restrict E\n\t *\n\t * @description\n\t * Load the content of a `\n\t\n\t Load inlined template\n\t
\n\t \n\t \n\t it('should load template defined inside script tag', function() {\n\t element(by.css('#tpl-link')).click();\n\t expect(element(by.css('#tpl-content')).getText()).toMatch(/Content of the template/);\n\t });\n\t \n\t \n\t */\n\tvar scriptDirective = ['$templateCache', function($templateCache) {\n\t return {\n\t restrict: 'E',\n\t terminal: true,\n\t compile: function(element, attr) {\n\t if (attr.type == 'text/ng-template') {\n\t var templateUrl = attr.id,\n\t text = element[0].text;\n\t\n\t $templateCache.put(templateUrl, text);\n\t }\n\t }\n\t };\n\t}];\n\t\n\tvar noopNgModelController = { $setViewValue: noop, $render: noop };\n\t\n\tfunction chromeHack(optionElement) {\n\t // Workaround for https://code.google.com/p/chromium/issues/detail?id=381459\n\t // Adding an