340. EPMO Open Source Coordination Office Redaction File Detail Report

Produced by Araxis Merge on 12/7/2018 11:36:15 AM Central Standard Time. See www.araxis.com for information about Merge. This report uses XHTML and CSS2, and is best viewed with a modern standards-compliant browser. For optimum results when printing this report, use landscape orientation and enable printing of background images and colours in your browser.

340.1 Files compared

# Location File Last Modified
1 C:\SCRUB\MHED\MHED\VATS 2.3.0\var-utility-web-2.3.0@19406cb7810\app\libs\angular\js angular.js Thu Sep 13 18:55:48 2018 UTC
2 C:\MHED-scrubbed\MHED\MHED\VATS 2.3.0\var-utility-web-2.3.0@19406cb7810\app\libs\angular\js angular.js Fri Dec 7 13:48:30 2018 UTC

340.2 Comparison summary

Description Between
Files 1 and 2
Text Blocks Lines
Unchanged 50 51730
Changed 49 104
Inserted 0 0
Removed 0 0

340.3 Comparison options

Whitespace
Character case Differences in character case are significant
Line endings Differences in line endings (CR and LF characters) are ignored
CR/LF characters Not shown in the comparison detail

340.4 Active regular expressions

No regular expressions were active.

340.5 Comparison detail

  1   /**
  2    * @licens e AngularJ S v1.3.5
  3    * (c) 201 0-2014 Goo gle, Inc.  http://ang ularjs.org
  4    * License : MIT
  5    */
  6   (function( window, do cument, un defined) { 'use stric t';
  7  
  8   /**
  9    * @descri ption
  10    *
  11    * This ob ject provi des a util ity for pr oducing ri ch Error m essages wi thin
  12    * Angular . It can b e called a s follows:
  13    *
  14    * var exa mpleMinErr  = minErr( 'example') ;
  15    * throw e xampleMinE rr('one',  'This {0}  is {1}', f oo, bar);
  16    *
  17    * The abo ve creates  an instan ce of minE rr in the  example na mespace. T he
  18    * resulti ng error w ill have a  namespace d error co de of exam ple.one.   The
  19    * resulti ng error w ill replac e {0} with  the value  of foo, a nd {1} wit h the
  20    * value o f bar. The  object is  not restr icted in t he number  of argumen ts it can
  21    * take.
  22    *
  23    * If fewe r argument s are spec ified than  necessary  for inter polation,  the extra
  24    * interpo lation mar kers will  be preserv ed in the  final stri ng.
  25    *
  26    * Since d ata will b e parsed s tatically  during a b uild step,  some rest rictions
  27    * are app lied with  respect to  how minEr r instance s are crea ted and ca lled.
  28    * Instanc es should  have names  of the fo rm namespa ceMinErr f or a minEr r created
  29    * using m inErr('nam espace') .  Error cod es, namesp aces and t emplate st rings
  30    * should  all be sta tic string s, not var iables or  general ex pressions.
  31    *
  32    * @param  {string} m odule The  namespace  to use for  the new m inErr inst ance.
  33    * @param  {function}  ErrorCons tructor Cu stom error  construct or to be i nstantiate d when ret urning
  34    *   error  from retu rned funct ion, for c ases when  a particul ar type of  error is  useful.
  35    * @return s {functio n(code:str ing, templ ate:string , ...templ ateArgs):  Error} min Err instan ce
  36    */
  37  
  38   function m inErr(modu le, ErrorC onstructor ) {
  39     ErrorCon structor =  ErrorCons tructor ||  Error;
  40     return f unction()  {
  41       var co de = argum ents[0],
  42         pref ix = '[' +  (module ?  module +  ':' : '')  + code + ' ] ',
  43         temp late = arg uments[1],
  44         temp lateArgs =  arguments ,
  45  
  46         mess age, i;
  47  
  48       messag e = prefix  + templat e.replace( /\{\d+\}/g , function (match) {
  49         var  index = +m atch.slice (1, -1), a rg;
  50  
  51         if ( index + 2  < template Args.lengt h) {
  52           re turn toDeb ugString(t emplateArg s[index +  2]);
  53         }
  54         retu rn match;
  55       });
  56  
  57       messag e = messag e + '\nhtt p://errors .angularjs .org/1.3.5 /' +
  58         (mod ule ? modu le + '/' :  '') + cod e;
  59       for (i  = 2; i <  arguments. length; i+ +) {
  60         mess age = mess age + (i = = 2 ? '?'  : '&') + ' p' + (i -  2) + '=' +
  61           en codeURICom ponent(toD ebugString (arguments [i]));
  62       }
  63       return  new Error Constructo r(message) ;
  64     };
  65   }
  66  
  67   /* We need  to tell j shint what  variables  are being  exported  */
  68   /* global  angular: t rue,
  69     msie: tr ue,
  70     jqLite:  true,
  71     jQuery:  true,
  72     slice: t rue,
  73     splice:  true,
  74     push: tr ue,
  75     toString : true,
  76     ngMinErr : true,
  77     angularM odule: tru e,
  78     uid: tru e,
  79     REGEX_ST RING_REGEX P: true,
  80     VALIDITY _STATE_PRO PERTY: tru e,
  81  
  82     lowercas e: true,
  83     uppercas e: true,
  84     manualLo wercase: t rue,
  85     manualUp percase: t rue,
  86     nodeName _: true,
  87     isArrayL ike: true,
  88     forEach:  true,
  89     sortedKe ys: true,
  90     forEachS orted: tru e,
  91     reverseP arams: tru e,
  92     nextUid:  true,
  93     setHashK ey: true,
  94     extend:  true,
  95     int: tru e,
  96     inherit:  true,
  97     noop: tr ue,
  98     identity : true,
  99     valueFn:  true,
  100     isUndefi ned: true,
  101     isDefine d: true,
  102     isObject : true,
  103     isString : true,
  104     isNumber : true,
  105     isDate:  true,
  106     isArray:  true,
  107     isFuncti on: true,
  108     isRegExp : true,
  109     isWindow : true,
  110     isScope:  true,
  111     isFile:  true,
  112     isBlob:  true,
  113     isBoolea n: true,
  114     isPromis eLike: tru e,
  115     trim: tr ue,
  116     escapeFo rRegexp: t rue,
  117     isElemen t: true,
  118     makeMap:  true,
  119     includes : true,
  120     arrayRem ove: true,
  121     copy: tr ue,
  122     shallowC opy: true,
  123     equals:  true,
  124     csp: tru e,
  125     concat:  true,
  126     sliceArg s: true,
  127     bind: tr ue,
  128     toJsonRe placer: tr ue,
  129     toJson:  true,
  130     fromJson : true,
  131     starting Tag: true,
  132     tryDecod eURICompon ent: true,
  133     parseKey Value: tru e,
  134     toKeyVal ue: true,
  135     encodeUr iSegment:  true,
  136     encodeUr iQuery: tr ue,
  137     angularI nit: true,
  138     bootstra p: true,
  139     getTesta bility: tr ue,
  140     snake_ca se: true,
  141     bindJQue ry: true,
  142     assertAr g: true,
  143     assertAr gFn: true,
  144     assertNo tHasOwnPro perty: tru e,
  145     getter:  true,
  146     getBlock Nodes: tru e,
  147     hasOwnPr operty: tr ue,
  148     createMa p: true,
  149  
  150     NODE_TYP E_ELEMENT:  true,
  151     NODE_TYP E_TEXT: tr ue,
  152     NODE_TYP E_COMMENT:  true,
  153     NODE_TYP E_DOCUMENT : true,
  154     NODE_TYP E_DOCUMENT _FRAGMENT:  true,
  155   */
  156  
  157   ////////// ////////// ////////// //////
  158  
  159   /**
  160    * @ngdoc  module
  161    * @name n g
  162    * @module  ng
  163    * @descri ption
  164    *
  165    * # ng (c ore module )
  166    * The ng  module is  loaded by  default wh en an Angu larJS appl ication is  started.  The module  itself
  167    * contain s the esse ntial comp onents for  an Angula rJS applic ation to f unction. T he table b elow
  168    * lists a  high leve l breakdow n of each  of the ser vices/fact ories, fil ters, dire ctives and  testing
  169    * compone nts availa ble within  this core  module.
  170    *
  171    * <div do c-module-c omponents= "ng"></div >
  172    */
  173  
  174   var REGEX_ STRING_REG EXP = /^\/ (.+)\/([a- z]*)$/;
  175  
  176   // The nam e of a for m control' s Validity State prop erty.
  177   // This is  used so t hat it's p ossible fo r internal  tests to  create moc k Validity States.
  178   var VALIDI TY_STATE_P ROPERTY =  'validity' ;
  179  
  180   /**
  181    * @ngdoc  function
  182    * @name a ngular.low ercase
  183    * @module  ng
  184    * @kind f unction
  185    *
  186    * @descri ption Conv erts the s pecified s tring to l owercase.
  187    * @param  {string} s tring Stri ng to be c onverted t o lowercas e.
  188    * @return s {string}  Lowercase d string.
  189    */
  190   var lowerc ase = func tion(strin g) {return  isString( string) ?  string.toL owerCase()  : string; };
  191   var hasOwn Property =  Object.pr ototype.ha sOwnProper ty;
  192  
  193   /**
  194    * @ngdoc  function
  195    * @name a ngular.upp ercase
  196    * @module  ng
  197    * @kind f unction
  198    *
  199    * @descri ption Conv erts the s pecified s tring to u ppercase.
  200    * @param  {string} s tring Stri ng to be c onverted t o uppercas e.
  201    * @return s {string}  Uppercase d string.
  202    */
  203   var upperc ase = func tion(strin g) {return  isString( string) ?  string.toU pperCase()  : string; };
  204  
  205  
  206   var manual Lowercase  = function (s) {
  207     /* jshin t bitwise:  false */
  208     return i sString(s)
  209         ? s. replace(/[ A-Z]/g, fu nction(ch)  {return S tring.from CharCode(c h.charCode At(0) | 32 );})
  210         : s;
  211   };
  212   var manual Uppercase  = function (s) {
  213     /* jshin t bitwise:  false */
  214     return i sString(s)
  215         ? s. replace(/[ a-z]/g, fu nction(ch)  {return S tring.from CharCode(c h.charCode At(0) & ~3 2);})
  216         : s;
  217   };
  218  
  219  
  220   // String# toLowerCas e and Stri ng#toUpper Case don't  produce c orrect res ults in br owsers wit h Turkish
  221   // locale,  for this  reason we  need to de tect this  case and r edefine lo wercase/up percase me thods
  222   // with co rrect but  slower alt ernatives.
  223   if ('i' != = 'I'.toLo werCase())  {
  224     lowercas e = manual Lowercase;
  225     uppercas e = manual Uppercase;
  226   }
  227  
  228  
  229   var
  230       msie,               // holds  major ver sion numbe r for IE,  or NaN if  UA is not  IE.
  231       jqLite ,            // delay  binding s ince jQuer y could be  loaded af ter us.
  232       jQuery ,            // delay  binding
  233       slice               = [].sli ce,
  234       splice              = [].spl ice,
  235       push                = [].pus h,
  236       toStri ng           = Object .prototype .toString,
  237       ngMinE rr           = minErr ('ng'),
  238  
  239       /** @n ame angula r */
  240       angula r            = window .angular | | (window. angular =  {}),
  241       angula rModule,
  242       uid                 = 0;
  243  
  244   /**
  245    * documen tMode is a n IE-only  property
  246    * http:// msdn.micro soft.com/e n-us/libra ry/ie/cc19 6988(v=vs. 85).aspx
  247    */
  248   msie = doc ument.docu mentMode;
  249  
  250  
  251   /**
  252    * @privat e
  253    * @param  {*} obj
  254    * @return  {boolean}  Returns t rue if `ob j` is an a rray or ar ray-like o bject (Nod eList, Arg uments,
  255    *                     String .. .)
  256    */
  257   function i sArrayLike (obj) {
  258     if (obj  == null ||  isWindow( obj)) {
  259       return  false;
  260     }
  261  
  262     var leng th = obj.l ength;
  263  
  264     if (obj. nodeType = == NODE_TY PE_ELEMENT  && length ) {
  265       return  true;
  266     }
  267  
  268     return i sString(ob j) || isAr ray(obj) | | length = == 0 ||
  269            t ypeof leng th === 'nu mber' && l ength > 0  && (length  - 1) in o bj;
  270   }
  271  
  272   /**
  273    * @ngdoc  function
  274    * @name a ngular.for Each
  275    * @module  ng
  276    * @kind f unction
  277    *
  278    * @descri ption
  279    * Invokes  the `iter ator` func tion once  for each i tem in `ob j` collect ion, which  can be ei ther an
  280    * object  or an arra y. The `it erator` fu nction is  invoked wi th `iterat or(value,  key, obj)` , where `v alue`
  281    * is the  value of a n object p roperty or  an array  element, ` key` is th e object p roperty ke y or
  282    * array e lement ind ex and obj  is the `o bj` itself . Specifyi ng a `cont ext` for t he functio n is optio nal.
  283    *
  284    * It is w orth notin g that `.f orEach` do es not ite rate over  inherited  properties  because i t filters
  285    * using t he `hasOwn Property`  method.
  286    *
  287    * Unlike  ES262's
  288    * [Array. prototype. forEach](h ttp://www. ecma-inter national.o rg/ecma-26 2/5.1/#sec -15.4.4.18 ),
  289    * Providi ng 'undefi ned' or 'n ull' value s for `obj ` will not  throw a T ypeError,  but rather  just
  290    * return  the value  provided.
  291    *
  292      ```js
  293        var v alues = {n ame: 'misk o', gender : 'male'};
  294        var l og = [];
  295        angul ar.forEach (values, f unction(va lue, key)  {
  296          thi s.push(key  + ': ' +  value);
  297        }, lo g);
  298        expec t(log).toE qual(['nam e: misko',  'gender:  male']);
  299      ```
  300    *
  301    * @param  {Object|Ar ray} obj O bject to i terate ove r.
  302    * @param  {Function}  iterator  Iterator f unction.
  303    * @param  {Object=}  context Ob ject to be come conte xt (`this` ) for the  iterator f unction.
  304    * @return s {Object| Array} Ref erence to  `obj`.
  305    */
  306  
  307   function f orEach(obj , iterator , context)  {
  308     var key,  length;
  309     if (obj)  {
  310       if (is Function(o bj)) {
  311         for  (key in ob j) {
  312           //  Need to c heck if ha sOwnProper ty exists,
  313           //  as on IE8  the resul t of query SelectorAl l is an ob ject witho ut a hasOw nProperty  function
  314           if  (key != ' prototype'  && key !=  'length'  && key !=  'name' &&  (!obj.hasO wnProperty  || obj.ha sOwnProper ty(key)))  {
  315              iterator.c all(contex t, obj[key ], key, ob j);
  316           }
  317         }
  318       } else  if (isArr ay(obj) ||  isArrayLi ke(obj)) {
  319         var  isPrimitiv e = typeof  obj !== ' object';
  320         for  (key = 0,  length = o bj.length;  key < len gth; key++ ) {
  321           if  (isPrimit ive || key  in obj) {
  322              iterator.c all(contex t, obj[key ], key, ob j);
  323           }
  324         }
  325       } else  if (obj.f orEach &&  obj.forEac h !== forE ach) {
  326           ob j.forEach( iterator,  context, o bj);
  327       } else  {
  328         for  (key in ob j) {
  329           if  (obj.hasO wnProperty (key)) {
  330              iterator.c all(contex t, obj[key ], key, ob j);
  331           }
  332         }
  333       }
  334     }
  335     return o bj;
  336   }
  337  
  338   function s ortedKeys( obj) {
  339     return O bject.keys (obj).sort ();
  340   }
  341  
  342   function f orEachSort ed(obj, it erator, co ntext) {
  343     var keys  = sortedK eys(obj);
  344     for (var  i = 0; i  < keys.len gth; i++)  {
  345       iterat or.call(co ntext, obj [keys[i]],  keys[i]);
  346     }
  347     return k eys;
  348   }
  349  
  350  
  351   /**
  352    * when us ing forEac h the para ms are val ue, key, b ut it is o ften usefu l to have  key, value .
  353    * @param  {function( string, *) } iterator Fn
  354    * @return s {functio n(*, strin g)}
  355    */
  356   function r eversePara ms(iterato rFn) {
  357     return f unction(va lue, key)  { iterator Fn(key, va lue); };
  358   }
  359  
  360   /**
  361    * A consi stent way  of creatin g unique I Ds in angu lar.
  362    *
  363    * Using s imple numb ers allows  us to gen erate 28.6  million u nique ids  per second  for 10 ye ars before
  364    * we hit  number pre cision iss ues in Jav aScript.
  365    *
  366    * Math.po w(2,53) /  60 / 60 /  24 / 365 /  10 = 28.6 M
  367    *
  368    * @return s {number}  an unique  alpha-num eric strin g
  369    */
  370   function n extUid() {
  371     return + +uid;
  372   }
  373  
  374  
  375   /**
  376    * Set or  clear the  hashkey fo r an objec t.
  377    * @param  obj object
  378    * @param  h the hash key (!trut hy to dele te the has hkey)
  379    */
  380   function s etHashKey( obj, h) {
  381     if (h) {
  382       obj.$$ hashKey =  h;
  383     }
  384     else {
  385       delete  obj.$$has hKey;
  386     }
  387   }
  388  
  389   /**
  390    * @ngdoc  function
  391    * @name a ngular.ext end
  392    * @module  ng
  393    * @kind f unction
  394    *
  395    * @descri ption
  396    * Extends  the desti nation obj ect `dst`  by copying  own enume rable prop erties fro m the `src ` object(s )
  397    * to `dst `. You can  specify m ultiple `s rc` object s. If you  want to pr eserve ori ginal obje cts, you c an do so
  398    * by pass ing an emp ty object  as the tar get: `var  object = a ngular.ext end({}, ob ject1, obj ect2)`.
  399    * Note: K eep in min d that `an gular.exte nd` does n ot support  recursive  merge (de ep copy).
  400    *
  401    * @param  {Object} d st Destina tion objec t.
  402    * @param  {...Object } src Sour ce object( s).
  403    * @return s {Object}  Reference  to `dst`.
  404    */
  405   function e xtend(dst)  {
  406     var h =  dst.$$hash Key;
  407  
  408     for (var  i = 1, ii  = argumen ts.length;  i < ii; i ++) {
  409       var ob j = argume nts[i];
  410       if (ob j) {
  411         var  keys = Obj ect.keys(o bj);
  412         for  (var j = 0 , jj = key s.length;  j < jj; j+ +) {
  413           va r key = ke ys[j];
  414           ds t[key] = o bj[key];
  415         }
  416       }
  417     }
  418  
  419     setHashK ey(dst, h) ;
  420     return d st;
  421   }
  422  
  423   function i nt(str) {
  424     return p arseInt(st r, 10);
  425   }
  426  
  427  
  428   function i nherit(par ent, extra ) {
  429     return e xtend(Obje ct.create( parent), e xtra);
  430   }
  431  
  432   /**
  433    * @ngdoc  function
  434    * @name a ngular.noo p
  435    * @module  ng
  436    * @kind f unction
  437    *
  438    * @descri ption
  439    * A funct ion that p erforms no  operation s. This fu nction can  be useful  when writ ing code i n the
  440    * functio nal style.
  441      ```js
  442        funct ion foo(ca llback) {
  443          var  result =  calculateR esult();
  444          (ca llback ||  angular.no op)(result );
  445        }
  446      ```
  447    */
  448   function n oop() {}
  449   noop.$inje ct = [];
  450  
  451  
  452   /**
  453    * @ngdoc  function
  454    * @name a ngular.ide ntity
  455    * @module  ng
  456    * @kind f unction
  457    *
  458    * @descri ption
  459    * A funct ion that r eturns its  first arg ument. Thi s function  is useful  when writ ing code i n the
  460    * functio nal style.
  461    *
  462      ```js
  463        funct ion transf ormer(tran sformation Fn, value)  {
  464          ret urn (trans formationF n || angul ar.identit y)(value);
  465        };
  466      ```
  467    */
  468   function i dentity($)  {return $ ;}
  469   identity.$ inject = [ ];
  470  
  471  
  472   function v alueFn(val ue) {retur n function () {return  value;};}
  473  
  474   /**
  475    * @ngdoc  function
  476    * @name a ngular.isU ndefined
  477    * @module  ng
  478    * @kind f unction
  479    *
  480    * @descri ption
  481    * Determi nes if a r eference i s undefine d.
  482    *
  483    * @param  {*} value  Reference  to check.
  484    * @return s {boolean } True if  `value` is  undefined .
  485    */
  486   function i sUndefined (value) {r eturn type of value = == 'undefi ned';}
  487  
  488  
  489   /**
  490    * @ngdoc  function
  491    * @name a ngular.isD efined
  492    * @module  ng
  493    * @kind f unction
  494    *
  495    * @descri ption
  496    * Determi nes if a r eference i s defined.
  497    *
  498    * @param  {*} value  Reference  to check.
  499    * @return s {boolean } True if  `value` is  defined.
  500    */
  501   function i sDefined(v alue) {ret urn typeof  value !==  'undefine d';}
  502  
  503  
  504   /**
  505    * @ngdoc  function
  506    * @name a ngular.isO bject
  507    * @module  ng
  508    * @kind f unction
  509    *
  510    * @descri ption
  511    * Determi nes if a r eference i s an `Obje ct`. Unlik e `typeof`  in JavaSc ript, `nul l`s are no t
  512    * conside red to be  objects. N ote that J avaScript  arrays are  objects.
  513    *
  514    * @param  {*} value  Reference  to check.
  515    * @return s {boolean } True if  `value` is  an `Objec t` but not  `null`.
  516    */
  517   function i sObject(va lue) {
  518     // http: //jsperf.c om/isobjec t4
  519     return v alue !== n ull && typ eof value  === 'objec t';
  520   }
  521  
  522  
  523   /**
  524    * @ngdoc  function
  525    * @name a ngular.isS tring
  526    * @module  ng
  527    * @kind f unction
  528    *
  529    * @descri ption
  530    * Determi nes if a r eference i s a `Strin g`.
  531    *
  532    * @param  {*} value  Reference  to check.
  533    * @return s {boolean } True if  `value` is  a `String `.
  534    */
  535   function i sString(va lue) {retu rn typeof  value ===  'string';}
  536  
  537  
  538   /**
  539    * @ngdoc  function
  540    * @name a ngular.isN umber
  541    * @module  ng
  542    * @kind f unction
  543    *
  544    * @descri ption
  545    * Determi nes if a r eference i s a `Numbe r`.
  546    *
  547    * @param  {*} value  Reference  to check.
  548    * @return s {boolean } True if  `value` is  a `Number `.
  549    */
  550   function i sNumber(va lue) {retu rn typeof  value ===  'number';}
  551  
  552  
  553   /**
  554    * @ngdoc  function
  555    * @name a ngular.isD ate
  556    * @module  ng
  557    * @kind f unction
  558    *
  559    * @descri ption
  560    * Determi nes if a v alue is a  date.
  561    *
  562    * @param  {*} value  Reference  to check.
  563    * @return s {boolean } True if  `value` is  a `Date`.
  564    */
  565   function i sDate(valu e) {
  566     return t oString.ca ll(value)  === '[obje ct Date]';
  567   }
  568  
  569  
  570   /**
  571    * @ngdoc  function
  572    * @name a ngular.isA rray
  573    * @module  ng
  574    * @kind f unction
  575    *
  576    * @descri ption
  577    * Determi nes if a r eference i s an `Arra y`.
  578    *
  579    * @param  {*} value  Reference  to check.
  580    * @return s {boolean } True if  `value` is  an `Array `.
  581    */
  582   var isArra y = Array. isArray;
  583  
  584   /**
  585    * @ngdoc  function
  586    * @name a ngular.isF unction
  587    * @module  ng
  588    * @kind f unction
  589    *
  590    * @descri ption
  591    * Determi nes if a r eference i s a `Funct ion`.
  592    *
  593    * @param  {*} value  Reference  to check.
  594    * @return s {boolean } True if  `value` is  a `Functi on`.
  595    */
  596   function i sFunction( value) {re turn typeo f value == = 'functio n';}
  597  
  598  
  599   /**
  600    * Determi nes if a v alue is a  regular ex pression o bject.
  601    *
  602    * @privat e
  603    * @param  {*} value  Reference  to check.
  604    * @return s {boolean } True if  `value` is  a `RegExp `.
  605    */
  606   function i sRegExp(va lue) {
  607     return t oString.ca ll(value)  === '[obje ct RegExp] ';
  608   }
  609  
  610  
  611   /**
  612    * Checks  if `obj` i s a window  object.
  613    *
  614    * @privat e
  615    * @param  {*} obj Ob ject to ch eck
  616    * @return s {boolean } True if  `obj` is a  window ob j.
  617    */
  618   function i sWindow(ob j) {
  619     return o bj && obj. window ===  obj;
  620   }
  621  
  622  
  623   function i sScope(obj ) {
  624       return obj  && obj.$e DNS    ync && obj .$watch;
  625   }
  626  
  627  
  628   function i sFile(obj)  {
  629     return t oString.ca ll(obj) == = '[object  File]';
  630   }
  631  
  632  
  633   function i sBlob(obj)  {
  634     return t oString.ca ll(obj) == = '[object  Blob]';
  635   }
  636  
  637  
  638   function i sBoolean(v alue) {
  639     return t ypeof valu e === 'boo lean';
  640   }
  641  
  642  
  643   function i sPromiseLi ke(obj) {
  644     return o bj && isFu nction(obj .then);
  645   }
  646  
  647  
  648   var trim =  function( value) {
  649     return i sString(va lue) ? val ue.trim()  : value;
  650   };
  651  
  652   // Copied  from:
  653   // http:// docs.closu re-library .googlecod e.com/git/ local_clos ure_goog_s tring_stri ng.js.sour ce.html#li ne1021
  654   // Prereq:  s is a st ring.
  655   var escape ForRegexp  = function (s) {
  656     return s .replace(/ ([-()\[\]{ }+?*.$\^|, :#<!\\])/g , '\\$1').
  657               replace(/ \x08/g, '\ \x08');
  658   };
  659  
  660  
  661   /**
  662    * @ngdoc  function
  663    * @name a ngular.isE lement
  664    * @module  ng
  665    * @kind f unction
  666    *
  667    * @descri ption
  668    * Determi nes if a r eference i s a DOM el ement (or  wrapped jQ uery eleme nt).
  669    *
  670    * @param  {*} value  Reference  to check.
  671    * @return s {boolean } True if  `value` is  a DOM ele ment (or w rapped jQu ery elemen t).
  672    */
  673   function i sElement(n ode) {
  674     return ! !(node &&
  675       (node. nodeName   // we are  a direct e lement
  676       || (no de.prop &&  node.attr  && node.f ind)));  / / we have  an on and  find metho d part of  jQuery API
  677   }
  678  
  679   /**
  680    * @param  str 'key1, key2,...'
  681    * @return s {object}  in the fo rm of {key 1:true, ke y2:true, . ..}
  682    */
  683   function m akeMap(str ) {
  684     var obj  = {}, item s = str.sp lit(","),  i;
  685     for (i =  0; i < it ems.length ; i++)
  686       obj[ i tems[i] ]  = true;
  687     return o bj;
  688   }
  689  
  690  
  691   function n odeName_(e lement) {
  692     return l owercase(e lement.nod eName || ( element[0]  && elemen t[0].nodeN ame));
  693   }
  694  
  695   function i ncludes(ar ray, obj)  {
  696     return A rray.proto type.index Of.call(ar ray, obj)  != -1;
  697   }
  698  
  699   function a rrayRemove (array, va lue) {
  700     var inde x = array. indexOf(va lue);
  701     if (inde x >= 0)
  702       array. splice(ind ex, 1);
  703     return v alue;
  704   }
  705  
  706   /**
  707    * @ngdoc  function
  708    * @name a ngular.cop y
  709    * @module  ng
  710    * @kind f unction
  711    *
  712    * @descri ption
  713    * Creates  a deep co py of `sou rce`, whic h should b e an objec t or an ar ray.
  714    *
  715    * * If no  destinati on is supp lied, a co py of the  object or  array is c reated.
  716    * * If a  destinatio n is provi ded, all o f its elem ents (for  array) or  properties  (for obje cts)
  717    *   are d eleted and  then all  elements/p roperties  from the s ource are  copied to  it.
  718    * * If `s ource` is  not an obj ect or arr ay (inc. ` null` and  `undefined `), `sourc e` is retu rned.
  719    * * If `s ource` is  identical  to 'destin ation' an  exception  will be th rown.
  720    *
  721    * @param  {*} source  The sourc e that wil l be used  to make a  copy.
  722    *                     Can be an y type, in cluding pr imitives,  `null`, an d `undefin ed`.
  723    * @param  {(Object|A rray)=} de stination  Destinatio n into whi ch the sou rce is cop ied. If
  724    *     pro vided, mus t be of th e same typ e as `sour ce`.
  725    * @return s {*} The  copy or up dated `des tination`,  if `desti nation` wa s specifie d.
  726    *
  727    * @exampl e
  728    <example  module="co pyExample" >
  729    <file nam e="index.h tml">
  730    <div ng-c ontroller= "ExampleCo ntroller">
  731    <form nov alidate cl ass="simpl e-form">
  732    Name: <in put type=" text" ng-m odel="user .name" />< br />
  733    E-mail: < input type ="email" n g-model="u ser.email"  /><br />
  734    Gender: < input type ="radio" n g-model="u ser.gender " value="m ale" />mal e
  735    <input ty pe="radio"  ng-model= "user.gend er" value= "female" / >female<br  />
  736    <button n g-click="r eset()">RE SET</butto n>
  737    <button n g-click="u pdate(user )">SAVE</b utton>
  738    </form>
  739    <pre>form  = {{user  | json}}</ pre>
  740    <pre>mast er = {{mas ter | json }}</pre>
  741    </div>
  742  
  743    <script>
  744     angular. module('co pyExample' , [])
  745       .contr oller('Exa mpleContro ller', ['$ scope', fu nction($sc ope) {
  746         $sco pe.master=  {};
  747  
  748         $sco pe.update  = function (user) {
  749           //  Example w ith 1 argu ment
  750           $s cope.maste r= angular .copy(user );
  751         };
  752  
  753         $sco pe.reset =  function( ) {
  754           //  Example w ith 2 argu ments
  755           an gular.copy ($scope.ma ster, $sco pe.user);
  756         };
  757  
  758         $sco pe.reset() ;
  759       }]);
  760    </script>
  761    </file>
  762    </example >
  763    */
  764   function c opy(source , destinat ion, stack Source, st ackDest) {
  765     if (isWi ndow(sourc e) || isSc ope(source )) {
  766       throw  ngMinErr(' cpws',
  767         "Can 't copy! M aking copi es of Wind ow or Scop e instance s is not s upported." );
  768     }
  769  
  770     if (!des tination)  {
  771       destin ation = so urce;
  772       if (so urce) {
  773         if ( isArray(so urce)) {
  774           de stination  = copy(sou rce, [], s tackSource , stackDes t);
  775         } el se if (isD ate(source )) {
  776           de stination  = new Date (source.ge tTime());
  777         } el se if (isR egExp(sour ce)) {
  778           de stination  = new RegE xp(source. source, so urce.toStr ing().matc h(/[^\/]*$ /)[0]);
  779           de stination. lastIndex  = source.l astIndex;
  780         } el se if (isO bject(sour ce)) {
  781           va r emptyObj ect = Obje ct.create( Object.get PrototypeO f(source)) ;
  782           de stination  = copy(sou rce, empty Object, st ackSource,  stackDest );
  783         }
  784       }
  785     } else {
  786       if (so urce === d estination ) throw ng MinErr('cp i',
  787         "Can 't copy! S ource and  destinatio n are iden tical.");
  788  
  789       stackS ource = st ackSource  || [];
  790       stackD est = stac kDest || [ ];
  791  
  792       if (is Object(sou rce)) {
  793         var  index = st ackSource. indexOf(so urce);
  794         if ( index !==  -1) return  stackDest [index];
  795  
  796         stac kSource.pu sh(source) ;
  797         stac kDest.push (destinati on);
  798       }
  799  
  800       var re sult;
  801       if (is Array(sour ce)) {
  802         dest ination.le ngth = 0;
  803         for  (var i = 0 ; i < sour ce.length;  i++) {
  804           re sult = cop y(source[i ], null, s tackSource , stackDes t);
  805           if  (isObject (source[i] )) {
  806              stackSourc e.push(sou rce[i]);
  807              stackDest. push(resul t);
  808           }
  809           de stination. push(resul t);
  810         }
  811       } else  {
  812         var  h = destin ation.$$ha shKey;
  813         if ( isArray(de stination) ) {
  814           de stination. length = 0 ;
  815         } el se {
  816           fo rEach(dest ination, f unction(va lue, key)  {
  817              delete des tination[k ey];
  818           }) ;
  819         }
  820         for  (var key i n source)  {
  821           if  (source.h asOwnPrope rty(key))  {
  822              result = c opy(source [key], nul l, stackSo urce, stac kDest);
  823              if (isObje ct(source[ key])) {
  824                stackSou rce.push(s ource[key] );
  825                stackDes t.push(res ult);
  826              }
  827              destinatio n[key] = r esult;
  828           }
  829         }
  830         setH ashKey(des tination,h );
  831       }
  832  
  833     }
  834     return d estination ;
  835   }
  836  
  837   /**
  838    * Creates  a shallow  copy of a n object,  an array o r a primit ive.
  839    *
  840    * Assumes  that ther e are no p roto prope rties for  objects.
  841    */
  842   function s hallowCopy (src, dst)  {
  843     if (isAr ray(src))  {
  844       dst =  dst || [];
  845  
  846       for (v ar i = 0,  ii = src.l ength; i <  ii; i++)  {
  847         dst[ i] = src[i ];
  848       }
  849     } else i f (isObjec t(src)) {
  850       dst =  dst || {};
  851  
  852       for (v ar key in  src) {
  853         if ( !(key.char At(0) ===  '$' && key .charAt(1)  === '$'))  {
  854           ds t[key] = s rc[key];
  855         }
  856       }
  857     }
  858  
  859     return d st || src;
  860   }
  861  
  862  
  863   /**
  864    * @ngdoc  function
  865    * @name a ngular.equ als
  866    * @module  ng
  867    * @kind f unction
  868    *
  869    * @descri ption
  870    * Determi nes if two  objects o r two valu es are equ ivalent. S upports va lue types,  regular
  871    * express ions, arra ys and obj ects.
  872    *
  873    * Two obj ects or va lues are c onsidered  equivalent  if at lea st one of  the follow ing is tru e:
  874    *
  875    * * Both  objects or  values pa ss `===` c omparison.
  876    * * Both  objects or  values ar e of the s ame type a nd all of  their prop erties are  equal by
  877    *   compa ring them  with `angu lar.equals `.
  878    * * Both  values are  NaN. (In  JavaScript , NaN == N aN => fals e. But we  consider t wo NaN as  equal)
  879    * * Both  values rep resent the  same regu lar expres sion (In J avaScript,
  880    *   /abc/  == /abc/  => false.  But we con sider two  regular ex pressions  as equal w hen their  textual
  881    *   repre sentation  matches).
  882    *
  883    * During  a property  compariso n, propert ies of `fu nction` ty pe and pro perties wi th names
  884    * that be gin with ` $` are ign ored.
  885    *
  886    * Scope a nd DOMWind ow objects  are being  compared  only by id entify (`= ==`).
  887    *
  888    * @param  {*} o1 Obj ect or val ue to comp are.
  889    * @param  {*} o2 Obj ect or val ue to comp are.
  890    * @return s {boolean } True if  arguments  are equal.
  891    */
  892   function e quals(o1,  o2) {
  893     if (o1 = == o2) ret urn true;
  894     if (o1 = == null ||  o2 === nu ll) return  false;
  895     if (o1 ! == o1 && o 2 !== o2)  return tru e; // NaN  === NaN
  896     var t1 =  typeof o1 , t2 = typ eof o2, le ngth, key,  keySet;
  897     if (t1 = = t2) {
  898       if (t1  == 'objec t') {
  899         if ( isArray(o1 )) {
  900           if  (!isArray (o2)) retu rn false;
  901           if  ((length  = o1.lengt h) == o2.l ength) {
  902              for (key =  0; key <  length; ke y++) {
  903                if (!equ als(o1[key ], o2[key] )) return  false;
  904              }
  905              return tru e;
  906           }
  907         } el se if (isD ate(o1)) {
  908           if  (!isDate( o2)) retur n false;
  909           re turn equal s(o1.getTi me(), o2.g etTime());
  910         } el se if (isR egExp(o1)  && isRegEx p(o2)) {
  911           re turn o1.to String() = = o2.toStr ing();
  912         } el se {
  913           if  (isScope( o1) || isS cope(o2) | | isWindow (o1) || is Window(o2)  || isArra y(o2)) ret urn false;
  914           ke ySet = {};
  915           fo r (key in  o1) {
  916              if (key.ch arAt(0) == = '$' || i sFunction( o1[key]))  continue;
  917              if (!equal s(o1[key],  o2[key]))  return fa lse;
  918              keySet[key ] = true;
  919           }
  920           fo r (key in  o2) {
  921              if (!keySe t.hasOwnPr operty(key ) &&
  922                  key.ch arAt(0) != = '$' &&
  923                  o2[key ] !== unde fined &&
  924                  !isFun ction(o2[k ey])) retu rn false;
  925           }
  926           re turn true;
  927         }
  928       }
  929     }
  930     return f alse;
  931   }
  932  
  933   var csp =  function()  {
  934     if (isDe fined(csp. isActive_) ) return c sp.isActiv e_;
  935  
  936     var acti ve = !!(do cument.que rySelector ('[ng-csp] ') ||
  937                      do cument.que rySelector ('[data-ng -csp]'));
  938  
  939     if (!act ive) {
  940       try {
  941         /* j shint -W03 1, -W054 * /
  942         new  Function(' ');
  943         /* j shint +W03 1, +W054 * /
  944       } catc h (e) {
  945         acti ve = true;
  946       }
  947     }
  948  
  949     return ( csp.isActi ve_ = acti ve);
  950   };
  951  
  952  
  953  
  954   function c oncat(arra y1, array2 , index) {
  955     return a rray1.conc at(slice.c all(array2 , index));
  956   }
  957  
  958   function s liceArgs(a rgs, start Index) {
  959     return s lice.call( args, star tIndex ||  0);
  960   }
  961  
  962  
  963   /* jshint  -W101 */
  964   /**
  965    * @ngdoc  function
  966    * @name a ngular.bin d
  967    * @module  ng
  968    * @kind f unction
  969    *
  970    * @descri ption
  971    * Returns  a functio n which ca lls functi on `fn` bo und to `se lf` (`self ` becomes  the `this`  for
  972    * `fn`).  You can su pply optio nal `args`  that are  prebound t o the func tion. This  feature i s also
  973    * known a s [partial  applicati on](http:/ /en.wikipe dia.org/wi ki/Partial _applicati on), as
  974    * disting uished fro m [functio n currying ](http://e n.wikipedi a.org/wiki /Currying# Contrast_w ith_partia l_function _applicati on).
  975    *
  976    * @param  {Object} s elf Contex t which `f n` should  be evaluat ed in.
  977    * @param  {function( )} fn Func tion to be  bound.
  978    * @param  {...*} arg s Optional  arguments  to be pre bound to t he `fn` fu nction cal l.
  979    * @return s {functio n()} Funct ion that w raps the ` fn` with a ll the spe cified bin dings.
  980    */
  981   /* jshint  +W101 */
  982   function b ind(self,  fn) {
  983     var curr yArgs = ar guments.le ngth > 2 ?  sliceArgs (arguments , 2) : [];
  984     if (isFu nction(fn)  && !(fn i nstanceof  RegExp)) {
  985       return  curryArgs .length
  986         ? fu nction() {
  987              return arg uments.len gth
  988                ? fn.app ly(self, c oncat(curr yArgs, arg uments, 0) )
  989                : fn.app ly(self, c urryArgs);
  990           }
  991         : fu nction() {
  992              return arg uments.len gth
  993                ? fn.app ly(self, a rguments)
  994                : fn.cal l(self);
  995           };
  996     } else {
  997       // in  IE, native  methods a re not fun ctions so  they canno t be bound  (note: th ey don't n eed to be)
  998       return  fn;
  999     }
  1000   }
  1001  
  1002  
  1003   function t oJsonRepla cer(key, v alue) {
  1004     var val  = value;
  1005  
  1006     if (type of key ===  'string'  && key.cha rAt(0) ===  '$' && ke y.charAt(1 ) === '$')  {
  1007       val =  undefined;
  1008     } else i f (isWindo w(value))  {
  1009       val =  '$WINDOW';
  1010     } else i f (value & &  documen t === valu e) {
  1011       val =  '$DOCUMENT ';
  1012     } else i f (isScope (value)) {
  1013       val =  '$SCOPE';
  1014     }
  1015  
  1016     return v al;
  1017   }
  1018  
  1019  
  1020   /**
  1021    * @ngdoc  function
  1022    * @name a ngular.toJ son
  1023    * @module  ng
  1024    * @kind f unction
  1025    *
  1026    * @descri ption
  1027    * Seriali zes input  into a JSO N-formatte d string.  Properties  with lead ing $$ cha racters wi ll be
  1028    * strippe d since an gular uses  this nota tion inter nally.
  1029    *
  1030    * @param  {Object|Ar ray|Date|s tring|numb er} obj In put to be  serialized  into JSON .
  1031    * @param  {boolean=}  pretty If  set to tr ue, the JS ON output  will conta in newline s and whit espace.
  1032    * @return s {string| undefined}  JSON-ifie d string r epresentin g `obj`.
  1033    */
  1034   function t oJson(obj,  pretty) {
  1035     if (type of obj ===  'undefine d') return  undefined ;
  1036     return J SON.string ify(obj, t oJsonRepla cer, prett y ? '  ' :  null);
  1037   }
  1038  
  1039  
  1040   /**
  1041    * @ngdoc  function
  1042    * @name a ngular.fro mJson
  1043    * @module  ng
  1044    * @kind f unction
  1045    *
  1046    * @descri ption
  1047    * Deseria lizes a JS ON string.
  1048    *
  1049    * @param  {string} j son JSON s tring to d eserialize .
  1050    * @return s {Object| Array|stri ng|number}  Deseriali zed thingy .
  1051    */
  1052   function f romJson(js on) {
  1053     return i sString(js on)
  1054         ? JS ON.parse(j son)
  1055         : js on;
  1056   }
  1057  
  1058  
  1059   /**
  1060    * @return s {string}  Returns t he string  representa tion of th e element.
  1061    */
  1062   function s tartingTag (element)  {
  1063     element  = jqLite(e lement).cl one();
  1064     try {
  1065       // tur ns out IE  does not l et you set  .html() o n elements  which
  1066       // are  not allow ed to have  children.  So we jus t ignore i t.
  1067       elemen t.empty();
  1068     } catch  (e) {}
  1069     var elem Html = jqL ite('<div> ').append( element).h tml();
  1070     try {
  1071       return  element[0 ].nodeType  === NODE_ TYPE_TEXT  ? lowercas e(elemHtml ) :
  1072           el emHtml.
  1073              match(/^(< [^>]+>)/)[ 1].
  1074              replace(/^ <([\w\-]+) /, functio n(match, n odeName) {  return '< ' + lowerc ase(nodeNa me); });
  1075     } catch  (e) {
  1076       return  lowercase (elemHtml) ;
  1077     }
  1078  
  1079   }
  1080  
  1081  
  1082   ////////// ////////// ////////// ////////// /////////
  1083  
  1084   /**
  1085    * Tries t o decode t he URI com ponent wit hout throw ing an exc eption.
  1086    *
  1087    * @privat e
  1088    * @param  str value  potential  URI compon ent to che ck.
  1089    * @return s {boolean } True if  `value` ca n be decod ed
  1090    * with th e decodeUR IComponent  function.
  1091    */
  1092   function t ryDecodeUR IComponent (value) {
  1093     try {
  1094       return  decodeURI Component( value);
  1095     } catch  (e) {
  1096       // Ign ore any in valid uri  component
  1097     }
  1098   }
  1099  
  1100  
  1101   /**
  1102    * Parses  an escaped  url query  string in to key-val ue pairs.
  1103    * @return s {Object. <string,bo olean|Arra y>}
  1104    */
  1105   function p arseKeyVal ue(/**stri ng*/keyVal ue) {
  1106     var obj  = {}, key_ value, key ;
  1107     forEach( (keyValue  || "").spl it('&'), f unction(ke yValue) {
  1108       if (ke yValue) {
  1109         key_ value = ke yValue.rep lace(/\+/g ,'%20').sp lit('=');
  1110         key  = tryDecod eURICompon ent(key_va lue[0]);
  1111         if ( isDefined( key)) {
  1112           va r val = is Defined(ke y_value[1] ) ? tryDec odeURIComp onent(key_ value[1])  : true;
  1113           if  (!hasOwnP roperty.ca ll(obj, ke y)) {
  1114              obj[key] =  val;
  1115           }  else if (i sArray(obj [key])) {
  1116              obj[key].p ush(val);
  1117           }  else {
  1118              obj[key] =  [obj[key] ,val];
  1119           }
  1120         }
  1121       }
  1122     });
  1123     return o bj;
  1124   }
  1125  
  1126   function t oKeyValue( obj) {
  1127     var part s = [];
  1128     forEach( obj, funct ion(value,  key) {
  1129       if (is Array(valu e)) {
  1130         forE ach(value,  function( arrayValue ) {
  1131           pa rts.push(e ncodeUriQu ery(key, t rue) +
  1132                       ( arrayValue  === true  ? '' : '='  + encodeU riQuery(ar rayValue,  true)));
  1133         });
  1134       } else  {
  1135       parts. push(encod eUriQuery( key, true)  +
  1136                   (valu e === true  ? '' : '= ' + encode UriQuery(v alue, true )));
  1137       }
  1138     });
  1139     return p arts.lengt h ? parts. join('&')  : '';
  1140   }
  1141  
  1142  
  1143   /**
  1144    * We need  our custo m method b ecause enc odeURIComp onent is t oo aggress ive and do esn't foll ow
  1145    * http:// www.ietf.o rg/rfc/rfc 3986.txt w ith regard s to the c haracter s et (pchar)  allowed i n path
  1146    * segment s:
  1147    *    segm ent        = *pchar
  1148    *    pcha r          = unreserv ed / pct-e ncoded / s ub-delims  / ":" / "@ "
  1149    *    pct- encoded    = "%" HEXD IG HEXDIG
  1150    *    unre served     = ALPHA /  DIGIT / "- " / "." /  "_" / "~"
  1151    *    sub- delims     = "!" / "$ " / "&" /  "'" / "("  / ")"
  1152    *                       / "*" /  "+" / ","  / ";" / " ="
  1153    */
  1154   function e ncodeUriSe gment(val)  {
  1155     return e ncodeUriQu ery(val, t rue).
  1156                 replace (/%26/gi,  '&').
  1157                 replace (/%3D/gi,  '=').
  1158                 replace (/%2B/gi,  '+');
  1159   }
  1160  
  1161  
  1162   /**
  1163    * This me thod is in tended for  encoding  *key* or * value* par ts of quer y componen t. We need  a custom
  1164    * method  because en codeURICom ponent is  too aggres sive and e ncodes stu ff that do esn't have  to be
  1165    * encoded  per http: //tools.ie tf.org/htm l/rfc3986:
  1166    *    quer y       =  *( pchar /  "/" / "?"  )
  1167    *    pcha r          = unreserv ed / pct-e ncoded / s ub-delims  / ":" / "@ "
  1168    *    unre served     = ALPHA /  DIGIT / "- " / "." /  "_" / "~"
  1169    *    pct- encoded    = "%" HEXD IG HEXDIG
  1170    *    sub- delims     = "!" / "$ " / "&" /  "'" / "("  / ")"
  1171    *                       / "*" /  "+" / ","  / ";" / " ="
  1172    */
  1173   function e ncodeUriQu ery(val, p ctEncodeSp aces) {
  1174     return e ncodeURICo mponent(va l).
  1175                 replace (/%40/gi,  '@').
  1176                 replace (/%3A/gi,  ':').
  1177                 replace (/%24/g, ' $').
  1178                 replace (/%2C/gi,  ',').
  1179                 replace (/%3B/gi,  ';').
  1180                 replace (/%20/g, ( pctEncodeS paces ? '% 20' : '+') );
  1181   }
  1182  
  1183   var ngAttr Prefixes =  ['ng-', ' data-ng-',  'ng:', 'x -ng-'];
  1184  
  1185   function g etNgAttrib ute(elemen t, ngAttr)  {
  1186     var attr , i, ii =  ngAttrPref ixes.lengt h;
  1187     element  = jqLite(e lement);
  1188     for (i =  0; i < ii ; ++i) {
  1189       attr =  ngAttrPre fixes[i] +  ngAttr;
  1190       if (is String(att r = elemen t.attr(att r))) {
  1191         retu rn attr;
  1192       }
  1193     }
  1194     return n ull;
  1195   }
  1196  
  1197   /**
  1198    * @ngdoc  directive
  1199    * @name n gApp
  1200    * @module  ng
  1201    *
  1202    * @elemen t ANY
  1203    * @param  {angular.M odule} ngA pp an opti onal appli cation
  1204    *   {@lin k angular. module mod ule} name  to load.
  1205    * @param  {boolean=}  ngStrictD i if this  attribute  is present  on the ap p element,  the injec tor will b e
  1206    *   creat ed in "str ict-di" mo de. This m eans that  the applic ation will  fail to i nvoke func tions whic h
  1207    *   do no t use expl icit funct ion annota tion (and  are thus u nsuitable  for minifi cation), a s describe d
  1208    *   in {@ link guide /di the De pendency I njection g uide}, and  useful de bugging in fo will as sist in
  1209    *   track ing down t he root of  these bug s.
  1210    *
  1211    * @descri ption
  1212    *
  1213    * Use thi s directiv e to **aut o-bootstra p** an Ang ularJS app lication.  The `ngApp ` directiv e
  1214    * designa tes the ** root eleme nt** of th e applicat ion and is  typically  placed ne ar the roo t element
  1215    * of the  page - e.g . on the ` <body>` or  `<html>`  tags.
  1216    *
  1217    * Only on e AngularJ S applicat ion can be  auto-boot strapped p er HTML do cument. Th e first `n gApp`
  1218    * found i n the docu ment will  be used to  define th e root ele ment to au to-bootstr ap as an
  1219    * applica tion. To r un multipl e applicat ions in an  HTML docu ment you m ust manual ly bootstr ap them us ing
  1220    * {@link  angular.bo otstrap} i nstead. An gularJS ap plications  cannot be  nested wi thin each  other.
  1221    *
  1222    * You can  specify a n **Angula rJS module ** to be u sed as the  root modu le for the  applicati on.  This
  1223    * module  will be lo aded into  the {@link  auto.$inj ector} whe n the appl ication is  bootstrap ped and
  1224    * should  contain th e applicat ion code n eeded or h ave depend encies on  other modu les that w ill
  1225    * contain  the code.  See {@lin k angular. module} fo r more inf ormation.
  1226    *
  1227    * In the  example be low if the  `ngApp` d irective w ere not pl aced on th e `html` e lement the n the
  1228    * documen t would no t be compi led, the ` AppControl ler` would  not be in stantiated  and the ` {{ a+b }}`
  1229    * would n ot be reso lved to `3 `.
  1230    *
  1231    * `ngApp`  is the ea siest, and  most comm on, way to  bootstrap  an applic ation.
  1232    *
  1233    <example  module="ng AppDemo">
  1234      <file n ame="index .html">
  1235      <div ng -controlle r="ngAppDe moControll er">
  1236        I can  add: {{a} } + {{b}}  =  {{ a+b  }}
  1237      </div>
  1238      </file>
  1239      <file n ame="scrip t.js">
  1240      angular .module('n gAppDemo',  []).contr oller('ngA ppDemoCont roller', f unction($s cope) {
  1241        $scop e.a = 1;
  1242        $scop e.b = 2;
  1243      });
  1244      </file>
  1245    </example >
  1246    *
  1247    * Using ` ngStrictDi `, you wou ld see som ething lik e this:
  1248    *
  1249    <example  ng-app-inc luded="tru e">
  1250      <file n ame="index .html">
  1251      <div ng -app="ngAp pStrictDem o" ng-stri ct-di>
  1252          <di v ng-contr oller="Goo dControlle r1">
  1253               I can add : {{a}} +  {{b}} =  { { a+b }}
  1254  
  1255               <p>This r enders bec ause the c ontroller  does not f ail to
  1256                  instan tiate, by  using expl icit annot ation styl e (see
  1257                  script .js for de tails)
  1258               </p>
  1259          </d iv>
  1260  
  1261          <di v ng-contr oller="Goo dControlle r2">
  1262               Name: <in put ng-mod el="name"> <br />
  1263               Hello, {{ name}}!
  1264  
  1265               <p>This r enders bec ause the c ontroller  does not f ail to
  1266                  instan tiate, by  using expl icit annot ation styl e
  1267                  (see s cript.js f or details )
  1268               </p>
  1269          </d iv>
  1270  
  1271          <di v ng-contr oller="Bad Controller ">
  1272               I can add : {{a}} +  {{b}} =  { { a+b }}
  1273  
  1274               <p>The co ntroller c ould not b e instanti ated, due  to relying
  1275                  on aut omatic fun ction anno tations (w hich are d isabled in
  1276                  strict  mode). As  such, the  content o f this sec tion is no t
  1277                  interp olated, an d there sh ould be an  error in  your web c onsole.
  1278               </p>
  1279          </d iv>
  1280      </div>
  1281      </file>
  1282      <file n ame="scrip t.js">
  1283      angular .module('n gAppStrict Demo', [])
  1284        // Ba dControlle r will fai l to insta ntiate, du e to relyi ng on auto matic func tion annot ation,
  1285        // ra ther than  an explici t annotati on
  1286        .cont roller('Ba dControlle r', functi on($scope)  {
  1287          $sc ope.a = 1;
  1288          $sc ope.b = 2;
  1289        })
  1290        // Un like BadCo ntroller,  GoodContro ller1 and  GoodContro ller2 will  not fail  to be inst antiated,
  1291        // du e to using  explicit  annotation s using th e array st yle and $i nject prop erty, resp ectively.
  1292        .cont roller('Go odControll er1', ['$s cope', fun ction($sco pe) {
  1293          $sc ope.a = 1;
  1294          $sc ope.b = 2;
  1295        }])
  1296        .cont roller('Go odControll er2', Good Controller 2);
  1297        funct ion GoodCo ntroller2( $scope) {
  1298          $sc ope.name =  "World";
  1299        }
  1300        GoodC ontroller2 .$inject =  ['$scope' ];
  1301      </file>
  1302      <file n ame="style .css">
  1303      div[ng- controller ] {
  1304          mar gin-bottom : 1em;
  1305          -we bkit-borde r-radius:  4px;
  1306          bor der-radius : 4px;
  1307          bor der: 1px s olid;
  1308          pad ding: .5em ;
  1309      }
  1310      div[ng- controller ^=Good] {
  1311          bor der-color:  #d6e9c6;
  1312          bac kground-co lor: #dff0 d8;
  1313          col or: #3c763 d;
  1314      }
  1315      div[ng- controller ^=Bad] {
  1316          bor der-color:  #ebccd1;
  1317          bac kground-co lor: #f2de de;
  1318          col or: #a9444 2;
  1319          mar gin-bottom : 0;
  1320      }
  1321      </file>
  1322    </example >
  1323    */
  1324   function a ngularInit (element,  bootstrap)  {
  1325     var appE lement,
  1326         modu le,
  1327         conf ig = {};
  1328  
  1329     // The e lement `el ement` has  priority  over any o ther eleme nt
  1330     forEach( ngAttrPref ixes, func tion(prefi x) {
  1331       var na me = prefi x + 'app';
  1332  
  1333       if (!a ppElement  && element .hasAttrib ute && ele ment.hasAt tribute(na me)) {
  1334         appE lement = e lement;
  1335         modu le = eleme nt.getAttr ibute(name );
  1336       }
  1337     });
  1338     forEach( ngAttrPref ixes, func tion(prefi x) {
  1339       var na me = prefi x + 'app';
  1340       var ca ndidate;
  1341  
  1342       if (!a ppElement  && (candid ate = elem ent.queryS elector('[ ' + name.r eplace(':' , '\\:') +  ']'))) {
  1343         appE lement = c andidate;
  1344         modu le = candi date.getAt tribute(na me);
  1345       }
  1346     });
  1347     if (appE lement) {
  1348       config .strictDi  = getNgAtt ribute(app Element, " strict-di" ) !== null ;
  1349       bootst rap(appEle ment, modu le ? [modu le] : [],  config);
  1350     }
  1351   }
  1352  
  1353   /**
  1354    * @ngdoc  function
  1355    * @name a ngular.boo tstrap
  1356    * @module  ng
  1357    * @descri ption
  1358    * Use thi s function  to manual ly start u p angular  applicatio n.
  1359    *
  1360    * See: {@ link guide /bootstrap  Bootstrap }
  1361    *
  1362    * Note th at Protrac tor based  end-to-end  tests can not use th is functio n to boots trap manua lly.
  1363    * They mu st use {@l ink ng.dir ective:ngA pp ngApp}.
  1364    *
  1365    * Angular  will dete ct if it h as been lo aded into  the browse r more tha n once and  only allo w the
  1366    * first l oaded scri pt to be b ootstrappe d and will  report a  warning to  the brows er console  for
  1367    * each of  the subse quent scri pts. This  prevents s trange res ults in ap plications , where ot herwise
  1368    * multipl e instance s of Angul ar try to  work on th e DOM.
  1369    *
  1370    * ```html
  1371    * <!docty pe html>
  1372    * <html>
  1373    * <body>
  1374    * <div ng -controlle r="Welcome Controller ">
  1375    *   {{gre eting}}
  1376    * </div>
  1377    *
  1378    * <script  src="angu lar.js"></ script>
  1379    * <script >
  1380    *   var a pp = angul ar.module( 'demo', [] )
  1381    *   .cont roller('We lcomeContr oller', fu nction($sc ope) {
  1382    *       $ scope.gree ting = 'We lcome!';
  1383    *   });
  1384    *   angul ar.bootstr ap(documen t, ['demo' ]);
  1385    * </scrip t>
  1386    * </body>
  1387    * </html>
  1388    * ```
  1389    *
  1390    * @param  {DOMElemen t} element  DOM eleme nt which i s the root  of angula r applicat ion.
  1391    * @param  {Array<Str ing|Functi on|Array>= } modules  an array o f modules  to load in to the app lication.
  1392    *     Eac h item in  the array  should be  the name o f a predef ined modul e or a (DI  annotated )
  1393    *     fun ction that  will be i nvoked by  the inject or as a ru n block.
  1394    *     See : {@link a ngular.mod ule module s}
  1395    * @param  {Object=}  config an  object for  defining  configurat ion option s for the  applicatio n. The
  1396    *     fol lowing key s are supp orted:
  1397    *
  1398    * * `stri ctDi` - di sable auto matic func tion annot ation for  the applic ation. Thi s is meant  to
  1399    *   assis t in findi ng bugs wh ich break  minified c ode. Defau lts to `fa lse`.
  1400    *
  1401    * @return s {auto.$i njector} R eturns the  newly cre ated injec tor for th is app.
  1402    */
  1403   function b ootstrap(e lement, mo dules, con fig) {
  1404     if (!isO bject(conf ig)) confi g = {};
  1405     var defa ultConfig  = {
  1406       strict Di: false
  1407     };
  1408     config =  extend(de faultConfi g, config) ;
  1409     var doBo otstrap =  function()  {
  1410       elemen t = jqLite (element);
  1411  
  1412       if (el ement.inje ctor()) {
  1413         var  tag = (ele ment[0] == = document ) ? 'docum ent' : sta rtingTag(e lement);
  1414         //En code angle  brackets  to prevent  input fro m being sa nitized to  empty str ing #8683
  1415         thro w ngMinErr (
  1416              'btstrpd',
  1417              "App Alrea dy Bootstr apped with  this Elem ent '{0}'" ,
  1418              tag.replac e(/</,'&lt ;').replac e(/>/,'&gt ;'));
  1419       }
  1420  
  1421       module s = module s || [];
  1422       module s.unshift( ['$provide ', functio n($provide ) {
  1423         $pro vide.value ('$rootEle ment', ele ment);
  1424       }]);
  1425  
  1426       if (co nfig.debug InfoEnable d) {
  1427         // P ushing so  that this  overrides  `debugInfo Enabled` s etting def ined in us er's `modu les`.
  1428         modu les.push([ '$compileP rovider',  function($ compilePro vider) {
  1429           $c ompileProv ider.debug InfoEnable d(true);
  1430         }]);
  1431       }
  1432  
  1433       module s.unshift( 'ng');
  1434       var in jector = c reateInjec tor(module s, config. strictDi);
  1435       inject or.invoke( ['$rootSco pe', '$roo tElement',  '$compile ', '$injec tor',
  1436          fun ction boot strapApply (scope, el ement, com pile, inje ctor) {
  1437           sc ope.$apply (function( ) {
  1438              element.da ta('$injec tor', inje ctor);
  1439              compile(el ement)(sco pe);
  1440           }) ;
  1441         }]
  1442       );
  1443       return  injector;
  1444     };
  1445  
  1446     var NG_E NABLE_DEBU G_INFO = / ^NG_ENABLE _DEBUG_INF O!/;
  1447     var NG_D EFER_BOOTS TRAP = /^N G_DEFER_BO OTSTRAP!/;
  1448  
  1449     if (wind ow && NG_E NABLE_DEBU G_INFO.tes t(window.n ame)) {
  1450       config .debugInfo Enabled =  true;
  1451       window .name = wi ndow.name. replace(NG _ENABLE_DE BUG_INFO,  '');
  1452     }
  1453  
  1454     if (wind ow && !NG_ DEFER_BOOT STRAP.test (window.na me)) {
  1455       return  doBootstr ap();
  1456     }
  1457  
  1458     window.n ame = wind ow.name.re place(NG_D EFER_BOOTS TRAP, '');
  1459     angular. resumeBoot strap = fu nction(ext raModules)  {
  1460       forEac h(extraMod ules, func tion(modul e) {
  1461         modu les.push(m odule);
  1462       });
  1463       doBoot strap();
  1464     };
  1465   }
  1466  
  1467   /**
  1468    * @ngdoc  function
  1469    * @name a ngular.rel oadWithDeb ugInfo
  1470    * @module  ng
  1471    * @descri ption
  1472    * Use thi s function  to reload  the curre nt applica tion with  debug info rmation tu rned on.
  1473    * This ta kes preced ence over  a call to  `$compileP rovider.de bugInfoEna bled(false )`.
  1474    *
  1475    * See {@l ink ng.$co mpileProvi der#debugI nfoEnabled } for more .
  1476    */
  1477   function r eloadWithD ebugInfo()  {
  1478     window.n ame = 'NG_ ENABLE_DEB UG_INFO!'  + window.n ame;
  1479     window.l ocation.re load();
  1480   }
  1481  
  1482   /**
  1483    * @name a ngular.get Testabilit y
  1484    * @module  ng
  1485    * @descri ption
  1486    * Get the  testabili ty service  for the i nstance of  Angular o n the give n
  1487    * element .
  1488    * @param  {DOMElemen t} element  DOM eleme nt which i s the root  of angula r applicat ion.
  1489    */
  1490   function g etTestabil ity(rootEl ement) {
  1491     return a ngular.ele ment(rootE lement).in jector().g et('$$test ability');
  1492   }
  1493  
  1494   var SNAKE_ CASE_REGEX P = /[A-Z] /g;
  1495   function s nake_case( name, sepa rator) {
  1496     separato r = separa tor || '_' ;
  1497     return n ame.replac e(SNAKE_CA SE_REGEXP,  function( letter, po s) {
  1498       return  (pos ? se parator :  '') + lett er.toLower Case();
  1499     });
  1500   }
  1501  
  1502   var bindJQ ueryFired  = false;
  1503   var skipDe stroyOnNex tJQueryCle anData;
  1504   function b indJQuery( ) {
  1505     var orig inalCleanD ata;
  1506  
  1507     if (bind JQueryFire d) {
  1508       return ;
  1509     }
  1510  
  1511     // bind  to jQuery  if present ;
  1512     jQuery =  window.jQ uery;
  1513     // Use j Query if i t exists w ith proper  functiona lity, othe rwise defa ult to us.
  1514     // Angul ar 1.2+ re quires jQu ery 1.7+ f or on()/of f() suppor t.
  1515     // Angul ar 1.3+ te chnically  requires a t least jQ uery 2.1+  but it may  work with  older
  1516     // versi ons. It wi ll not wor k for sure  with jQue ry <1.7, t hough.
  1517     if (jQue ry && jQue ry.fn.on)  {
  1518       jqLite  = jQuery;
  1519       extend (jQuery.fn , {
  1520         scop e: JQLiteP rototype.s cope,
  1521         isol ateScope:  JQLiteProt otype.isol ateScope,
  1522         cont roller: JQ LiteProtot ype.contro ller,
  1523         inje ctor: JQLi tePrototyp e.injector ,
  1524         inhe ritedData:  JQLitePro totype.inh eritedData
  1525       });
  1526  
  1527       // All  nodes rem oved from  the DOM vi a various  jQuery API s like .re move()
  1528       // are  passed th rough jQue ry.cleanDa ta. Monkey -patch thi s method t o fire
  1529       // the  $destroy  event on a ll removed  nodes.
  1530       origin alCleanDat a = jQuery .cleanData ;
  1531       jQuery .cleanData  = functio n(elems) {
  1532         var  events;
  1533         if ( !skipDestr oyOnNextJQ ueryCleanD ata) {
  1534           fo r (var i =  0, elem;  (elem = el ems[i]) !=  null; i++ ) {
  1535              events = j Query._dat a(elem, "e vents");
  1536              if (events  && events .$destroy)  {
  1537                jQuery(e lem).trigg erHandler( '$destroy' );
  1538              }
  1539           }
  1540         } el se {
  1541           sk ipDestroyO nNextJQuer yCleanData  = false;
  1542         }
  1543         orig inalCleanD ata(elems) ;
  1544       };
  1545     } else {
  1546       jqLite  = JQLite;
  1547     }
  1548  
  1549     angular. element =  jqLite;
  1550  
  1551     // Preve nt double- proxying.
  1552     bindJQue ryFired =  true;
  1553   }
  1554  
  1555   /**
  1556    * throw e rror if th e argument  is falsy.
  1557    */
  1558   function a ssertArg(a rg, name,  reason) {
  1559     if (!arg ) {
  1560       throw  ngMinErr(' areq', "Ar gument '{0 }' is {1}" , (name ||  '?'), (re ason || "r equired")) ;
  1561     }
  1562     return a rg;
  1563   }
  1564  
  1565   function a ssertArgFn (arg, name , acceptAr rayAnnotat ion) {
  1566     if (acce ptArrayAnn otation &&  isArray(a rg)) {
  1567         arg  = arg[arg. length - 1 ];
  1568     }
  1569  
  1570     assertAr g(isFuncti on(arg), n ame, 'not  a function , got ' +
  1571         (arg  && typeof  arg === ' object' ?  arg.constr uctor.name  || 'Objec t' : typeo f arg));
  1572     return a rg;
  1573   }
  1574  
  1575   /**
  1576    * throw e rror if th e name giv en is hasO wnProperty
  1577    * @param   {String}  name    th e name to  test
  1578    * @param   {String}  context th e context  in which t he name is  used, suc h as modul e or direc tive
  1579    */
  1580   function a ssertNotHa sOwnProper ty(name, c ontext) {
  1581     if (name  === 'hasO wnProperty ') {
  1582       throw  ngMinErr(' badname',  "hasOwnPro perty is n ot a valid  {0} name" , context) ;
  1583     }
  1584   }
  1585  
  1586   /**
  1587    * Return  the value  accessible  from the  object by  path. Any  undefined  traversals  are ignor ed
  1588    * @param  {Object} o bj startin g object
  1589    * @param  {String} p ath path t o traverse
  1590    * @param  {boolean}  [bindFnToS cope=true]
  1591    * @return s {Object}  value as  accessible  by path
  1592    */
  1593   //TODO(mis ko): this  function n eeds to be  removed
  1594   function g etter(obj,  path, bin dFnToScope ) {
  1595     if (!pat h) return  obj;
  1596     var keys  = path.sp lit('.');
  1597     var key;
  1598     var last Instance =  obj;
  1599     var len  = keys.len gth;
  1600  
  1601     for (var  i = 0; i  < len; i++ ) {
  1602       key =  keys[i];
  1603       if (ob j) {
  1604         obj  = (lastIns tance = ob j)[key];
  1605       }
  1606     }
  1607     if (!bin dFnToScope  && isFunc tion(obj))  {
  1608       return  bind(last Instance,  obj);
  1609     }
  1610     return o bj;
  1611   }
  1612  
  1613   /**
  1614    * Return  the DOM si blings bet ween the f irst and l ast node i n the give n array.
  1615    * @param  {Array} ar ray like o bject
  1616    * @return s {jqLite}  jqLite co llection c ontaining  the nodes
  1617    */
  1618   function g etBlockNod es(nodes)  {
  1619     // TODO( perf): jus t check if  all items  in `nodes ` are sibl ings and i f they are  return th e original
  1620     //              col lection, o therwise u pdate the  original c ollection.
  1621     var node  = nodes[0 ];
  1622     var endN ode = node s[nodes.le ngth - 1];
  1623     var bloc kNodes = [ node];
  1624  
  1625     do {
  1626       node =  node.next Sibling;
  1627       if (!n ode) break ;
  1628       blockN odes.push( node);
  1629     } while  (node !==  endNode);
  1630  
  1631     return j qLite(bloc kNodes);
  1632   }
  1633  
  1634  
  1635   /**
  1636    * Creates  a new obj ect withou t a protot ype. This  object is  useful for  lookup wi thout havi ng to
  1637    * guard a gainst pro totypicall y inherite d properti es via has OwnPropert y.
  1638    *
  1639    * Related  micro-ben chmarks:
  1640    * - http: //jsperf.c om/object- create2
  1641    * - http: //jsperf.c om/proto-m ap-lookup/ 2
  1642    * - http: //jsperf.c om/for-in- vs-object- keys2
  1643    *
  1644    * @return s {Object}
  1645    */
  1646   function c reateMap()  {
  1647     return O bject.crea te(null);
  1648   }
  1649  
  1650   var NODE_T YPE_ELEMEN T = 1;
  1651   var NODE_T YPE_TEXT =  3;
  1652   var NODE_T YPE_COMMEN T = 8;
  1653   var NODE_T YPE_DOCUME NT = 9;
  1654   var NODE_T YPE_DOCUME NT_FRAGMEN T = 11;
  1655  
  1656   /**
  1657    * @ngdoc  type
  1658    * @name a ngular.Mod ule
  1659    * @module  ng
  1660    * @descri ption
  1661    *
  1662    * Interfa ce for con figuring a ngular {@l ink angula r.module m odules}.
  1663    */
  1664  
  1665   function s etupModule Loader(win dow) {
  1666  
  1667     var $inj ectorMinEr r = minErr ('$injecto r');
  1668     var ngMi nErr = min Err('ng');
  1669  
  1670     function  ensure(ob j, name, f actory) {
  1671       return  obj[name]  || (obj[n ame] = fac tory());
  1672     }
  1673  
  1674     var angu lar = ensu re(window,  'angular' , Object);
  1675  
  1676     // We ne ed to expo se `angula r.$$minErr ` to modul es such as  `ngResour ce` that r eference i t during b ootstrap
  1677     angular. $$minErr =  angular.$ $minErr ||  minErr;
  1678  
  1679     return e nsure(angu lar, 'modu le', funct ion() {
  1680       /** @t ype {Objec t.<string,  angular.M odule>} */
  1681       var mo dules = {} ;
  1682  
  1683       /**
  1684        * @ng doc functi on
  1685        * @na me angular .module
  1686        * @mo dule ng
  1687        * @de scription
  1688        *
  1689        * The  `angular. module` is  a global  place for  creating,  registerin g and retr ieving Ang ular
  1690        * mod ules.
  1691        * All  modules ( angular co re or 3rd  party) tha t should b e availabl e to an ap plication  must be
  1692        * reg istered us ing this m echanism.
  1693        *
  1694        * Whe n passed t wo or more  arguments , a new mo dule is cr eated.  If  passed on ly one arg ument, an
  1695        * exi sting modu le (the na me passed  as the fir st argumen t to `modu le`) is re trieved.
  1696        *
  1697        *
  1698        * # M odule
  1699        *
  1700        * A m odule is a  collectio n of servi ces, direc tives, con trollers,  filters, a nd configu ration inf ormation.
  1701        * `an gular.modu le` is use d to confi gure the { @link auto .$injector  $injector }.
  1702        *
  1703        * ``` js
  1704        * //  Create a n ew module
  1705        * var  myModule  = angular. module('my Module', [ ]);
  1706        *
  1707        * //  register a  new servi ce
  1708        * myM odule.valu e('appName ', 'MyCool App');
  1709        *
  1710        * //  configure  existing s ervices in side initi alization  blocks.
  1711        * myM odule.conf ig(['$loca tionProvid er', funct ion($locat ionProvide r) {
  1712        *   / / Configur e existing  providers
  1713        *   $ locationPr ovider.has hPrefix('! ');
  1714        * }]) ;
  1715        * ```
  1716        *
  1717        * The n you can  create an  injector a nd load yo ur modules  like this :
  1718        *
  1719        * ``` js
  1720        * var  injector  = angular. injector([ 'ng', 'myM odule'])
  1721        * ```
  1722        *
  1723        * How ever it's  more likel y that you 'll just u se
  1724        * {@l ink ng.dir ective:ngA pp ngApp}  or
  1725        * {@l ink angula r.bootstra p} to simp lify this  process fo r you.
  1726        *
  1727        * @pa ram {!stri ng} name T he name of  the modul e to creat e or retri eve.
  1728        * @pa ram {!Arra y.<string> =} require s If speci fied then  new module  is being  created. I f
  1729        *         unspec ified then  the modul e is being  retrieved  for furth er configu ration.
  1730        * @pa ram {Funct ion=} conf igFn Optio nal config uration fu nction for  the modul e. Same as
  1731        *         {@link  angular.M odule#conf ig Module# config()}.
  1732        * @re turns {mod ule} new m odule with  the {@lin k angular. Module} ap i.
  1733        */
  1734       return  function  module(nam e, require s, configF n) {
  1735         var  assertNotH asOwnPrope rty = func tion(name,  context)  {
  1736           if  (name ===  'hasOwnPr operty') {
  1737              throw ngMi nErr('badn ame', 'has OwnPropert y is not a  valid {0}  name', co ntext);
  1738           }
  1739         };
  1740  
  1741         asse rtNotHasOw nProperty( name, 'mod ule');
  1742         if ( requires & & modules. hasOwnProp erty(name) ) {
  1743           mo dules[name ] = null;
  1744         }
  1745         retu rn ensure( modules, n ame, funct ion() {
  1746           if  (!require s) {
  1747              throw $inj ectorMinEr r('nomod',  "Module ' {0}' is no t availabl e! You eit her misspe lled " +
  1748                 "the mo dule name  or forgot  to load it . If regis tering a m odule ensu re that yo u " +
  1749                 "specif y the depe ndencies a s the seco nd argumen t.", name) ;
  1750           }
  1751  
  1752           /* * @type {! Array.<Arr ay.<*>>} * /
  1753           va r invokeQu eue = [];
  1754  
  1755           /* * @type {! Array.<Fun ction>} */
  1756           va r configBl ocks = [];
  1757  
  1758           /* * @type {! Array.<Fun ction>} */
  1759           va r runBlock s = [];
  1760  
  1761           va r config =  invokeLat er('$injec tor', 'inv oke', 'pus h', config Blocks);
  1762  
  1763           /* * @type {a ngular.Mod ule} */
  1764           va r moduleIn stance = {
  1765              // Private  state
  1766              _invokeQue ue: invoke Queue,
  1767              _configBlo cks: confi gBlocks,
  1768              _runBlocks : runBlock s,
  1769  
  1770              /**
  1771               * @ngdoc  property
  1772               * @name a ngular.Mod ule#requir es
  1773               * @module  ng
  1774               *
  1775               * @descri ption
  1776               * Holds t he list of  modules w hich the i njector wi ll load be fore the c urrent mod ule is
  1777               * loaded.
  1778               */
  1779              requires:  requires,
  1780  
  1781              /**
  1782               * @ngdoc  property
  1783               * @name a ngular.Mod ule#name
  1784               * @module  ng
  1785               *
  1786               * @descri ption
  1787               * Name of  the modul e.
  1788               */
  1789              name: name ,
  1790  
  1791  
  1792              /**
  1793               * @ngdoc  method
  1794               * @name a ngular.Mod ule#provid er
  1795               * @module  ng
  1796               * @param  {string} n ame servic e name
  1797               * @param  {Function}  providerT ype Constr uction fun ction for  creating n ew instanc e of the
  1798               *                                   servic e.
  1799               * @descri ption
  1800               * See {@l ink auto.$ provide#pr ovider $pr ovide.prov ider()}.
  1801               */
  1802              provider:  invokeLate r('$provid e', 'provi der'),
  1803  
  1804              /**
  1805               * @ngdoc  method
  1806               * @name a ngular.Mod ule#factor y
  1807               * @module  ng
  1808               * @param  {string} n ame servic e name
  1809               * @param  {Function}  providerF unction Fu nction for  creating  new instan ce of the  service.
  1810               * @descri ption
  1811               * See {@l ink auto.$ provide#fa ctory $pro vide.facto ry()}.
  1812               */
  1813              factory: i nvokeLater ('$provide ', 'factor y'),
  1814  
  1815              /**
  1816               * @ngdoc  method
  1817               * @name a ngular.Mod ule#servic e
  1818               * @module  ng
  1819               * @param  {string} n ame servic e name
  1820               * @param  {Function}  construct or A const ructor fun ction that  will be i nstantiate d.
  1821               * @descri ption
  1822               * See {@l ink auto.$ provide#se rvice $pro vide.servi ce()}.
  1823               */
  1824              service: i nvokeLater ('$provide ', 'servic e'),
  1825  
  1826              /**
  1827               * @ngdoc  method
  1828               * @name a ngular.Mod ule#value
  1829               * @module  ng
  1830               * @param  {string} n ame servic e name
  1831               * @param  {*} object  Service i nstance ob ject.
  1832               * @descri ption
  1833               * See {@l ink auto.$ provide#va lue $provi de.value() }.
  1834               */
  1835              value: inv okeLater(' $provide',  'value'),
  1836  
  1837              /**
  1838               * @ngdoc  method
  1839               * @name a ngular.Mod ule#consta nt
  1840               * @module  ng
  1841               * @param  {string} n ame consta nt name
  1842               * @param  {*} object  Constant  value.
  1843               * @descri ption
  1844               * Because  the const ant are fi xed, they  get applie d before o ther provi de methods .
  1845               * See {@l ink auto.$ provide#co nstant $pr ovide.cons tant()}.
  1846               */
  1847              constant:  invokeLate r('$provid e', 'const ant', 'uns hift'),
  1848  
  1849              /**
  1850               * @ngdoc  method
  1851               * @name a ngular.Mod ule#animat ion
  1852               * @module  ng
  1853               * @param  {string} n ame animat ion name
  1854               * @param  {Function}  animation Factory Fa ctory func tion for c reating ne w instance  of an
  1855               *                                       an imation.
  1856               * @descri ption
  1857               *
  1858               * **NOTE* *: animati ons take e ffect only  if the ** ngAnimate* * module i s loaded.
  1859               *
  1860               *
  1861               * Defines  an animat ion hook t hat can be  later use d with
  1862               * {@link  ngAnimate. $animate $ animate} s ervice and  directive s that use  this serv ice.
  1863               *
  1864               * ```js
  1865               * module. animation( '.animatio n-name', f unction($i nject1, $i nject2) {
  1866               *   retur n {
  1867               *     eve ntName : f unction(el ement, don e) {
  1868               *       / /code to r un the ani mation
  1869               *       / /once comp lete, then  run done( )
  1870               *       r eturn func tion cance llationFun ction(elem ent) {
  1871               *          //code to  cancel th e animatio n
  1872               *       }
  1873               *     }
  1874               *   }
  1875               * })
  1876               * ```
  1877               *
  1878               * See {@l ink ng.$an imateProvi der#regist er $animat eProvider. register() } and
  1879               * {@link  ngAnimate  ngAnimate  module} fo r more inf ormation.
  1880               */
  1881              animation:  invokeLat er('$anima teProvider ', 'regist er'),
  1882  
  1883              /**
  1884               * @ngdoc  method
  1885               * @name a ngular.Mod ule#filter
  1886               * @module  ng
  1887               * @param  {string} n ame Filter  name.
  1888               * @param  {Function}  filterFac tory Facto ry functio n for crea ting new i nstance of  filter.
  1889               * @descri ption
  1890               * See {@l ink ng.$fi lterProvid er#registe r $filterP rovider.re gister()}.
  1891               */
  1892              filter: in vokeLater( '$filterPr ovider', ' register') ,
  1893  
  1894              /**
  1895               * @ngdoc  method
  1896               * @name a ngular.Mod ule#contro ller
  1897               * @module  ng
  1898               * @param  {string|Ob ject} name  Controlle r name, or  an object  map of co ntrollers  where the
  1899               *    keys  are the n ames and t he values  are the co nstructors .
  1900               * @param  {Function}  construct or Control ler constr uctor func tion.
  1901               * @descri ption
  1902               * See {@l ink ng.$co ntrollerPr ovider#reg ister $con trollerPro vider.regi ster()}.
  1903               */
  1904              controller : invokeLa ter('$cont rollerProv ider', 're gister'),
  1905  
  1906              /**
  1907               * @ngdoc  method
  1908               * @name a ngular.Mod ule#direct ive
  1909               * @module  ng
  1910               * @param  {string|Ob ject} name  Directive  name, or  an object  map of dir ectives wh ere the
  1911               *    keys  are the n ames and t he values  are the fa ctories.
  1912               * @param  {Function}  directive Factory Fa ctory func tion for c reating ne w instance  of
  1913               * directi ves.
  1914               * @descri ption
  1915               * See {@l ink ng.$co mpileProvi der#direct ive $compi leProvider .directive ()}.
  1916               */
  1917              directive:  invokeLat er('$compi leProvider ', 'direct ive'),
  1918  
  1919              /**
  1920               * @ngdoc  method
  1921               * @name a ngular.Mod ule#config
  1922               * @module  ng
  1923               * @param  {Function}  configFn  Execute th is functio n on modul e load. Us eful for s ervice
  1924               *    conf iguration.
  1925               * @descri ption
  1926               * Use thi s method t o register  work whic h needs to  be perfor med on mod ule loadin g.
  1927               * For mor e about ho w to confi gure servi ces, see
  1928               * {@link  providers# provider-r ecipe Prov ider Recip e}.
  1929               */
  1930              config: co nfig,
  1931  
  1932              /**
  1933               * @ngdoc  method
  1934               * @name a ngular.Mod ule#run
  1935               * @module  ng
  1936               * @param  {Function}  initializ ationFn Ex ecute this  function  after inje ctor creat ion.
  1937               *    Usef ul for app lication i nitializat ion.
  1938               * @descri ption
  1939               * Use thi s method t o register  work whic h should b e performe d when the  injector  is done
  1940               * loading  all modul es.
  1941               */
  1942              run: funct ion(block)  {
  1943                runBlock s.push(blo ck);
  1944                return t his;
  1945              }
  1946           };
  1947  
  1948           if  (configFn ) {
  1949              config(con figFn);
  1950           }
  1951  
  1952           re turn modul eInstance;
  1953  
  1954           /* *
  1955            *  @param {s tring} pro vider
  1956            *  @param {s tring} met hod
  1957            *  @param {S tring=} in sertMethod
  1958            *  @returns  {angular.M odule}
  1959            * /
  1960           fu nction inv okeLater(p rovider, m ethod, ins ertMethod,  queue) {
  1961              if (!queue ) queue =  invokeQueu e;
  1962              return fun ction() {
  1963                queue[in sertMethod  || 'push' ]([provide r, method,  arguments ]);
  1964                return m oduleInsta nce;
  1965              };
  1966           }
  1967         });
  1968       };
  1969     });
  1970  
  1971   }
  1972  
  1973   /* global:  toDebugSt ring: true  */
  1974  
  1975   function s erializeOb ject(obj)  {
  1976     var seen  = [];
  1977  
  1978     return J SON.string ify(obj, f unction(ke y, val) {
  1979       val =  toJsonRepl acer(key,  val);
  1980       if (is Object(val )) {
  1981  
  1982         if ( seen.index Of(val) >=  0) return  '<<alread y seen>>';
  1983  
  1984         seen .push(val) ;
  1985       }
  1986       return  val;
  1987     });
  1988   }
  1989  
  1990   function t oDebugStri ng(obj) {
  1991     if (type of obj ===  'function ') {
  1992       return  obj.toStr ing().repl ace(/ \{[\ s\S]*$/, ' ');
  1993     } else i f (typeof  obj === 'u ndefined')  {
  1994       return  'undefine d';
  1995     } else i f (typeof  obj !== 's tring') {
  1996       return  serialize Object(obj );
  1997     }
  1998     return o bj;
  1999   }
  2000  
  2001   /* global  angularMod ule: true,
  2002     version:  true,
  2003  
  2004     $LocaleP rovider,
  2005     $Compile Provider,
  2006  
  2007     htmlAnch orDirectiv e,
  2008     inputDir ective,
  2009     inputDir ective,
  2010     formDire ctive,
  2011     scriptDi rective,
  2012     selectDi rective,
  2013     styleDir ective,
  2014     optionDi rective,
  2015     ngBindDi rective,
  2016     ngBindHt mlDirectiv e,
  2017     ngBindTe mplateDire ctive,
  2018     ngClassD irective,
  2019     ngClassE venDirecti ve,
  2020     ngClassO ddDirectiv e,
  2021     ngCspDir ective,
  2022     ngCloakD irective,
  2023     ngContro llerDirect ive,
  2024     ngFormDi rective,
  2025     ngHideDi rective,
  2026     ngIfDire ctive,
  2027     ngInclud eDirective ,
  2028     ngInclud eFillConte ntDirectiv e,
  2029     ngInitDi rective,
  2030     ngNonBin dableDirec tive,
  2031     ngPlural izeDirecti ve,
  2032     ngRepeat Directive,
  2033     ngShowDi rective,
  2034     ngStyleD irective,
  2035     ngSwitch Directive,
  2036     ngSwitch WhenDirect ive,
  2037     ngSwitch DefaultDir ective,
  2038     ngOption sDirective ,
  2039     ngTransc ludeDirect ive,
  2040     ngModelD irective,
  2041     ngListDi rective,
  2042     ngChange Directive,
  2043     patternD irective,
  2044     patternD irective,
  2045     required Directive,
  2046     required Directive,
  2047     minlengt hDirective ,
  2048     minlengt hDirective ,
  2049     maxlengt hDirective ,
  2050     maxlengt hDirective ,
  2051     ngValueD irective,
  2052     ngModelO ptionsDire ctive,
  2053     ngAttrib uteAliasDi rectives,
  2054     ngEventD irectives,
  2055  
  2056     $AnchorS crollProvi der,
  2057     $Animate Provider,
  2058     $Browser Provider,
  2059     $CacheFa ctoryProvi der,
  2060     $Control lerProvide r,
  2061     $Documen tProvider,
  2062     $Excepti onHandlerP rovider,
  2063     $FilterP rovider,
  2064     $Interpo lateProvid er,
  2065     $Interva lProvider,
  2066     $HttpPro vider,
  2067     $HttpBac kendProvid er,
  2068     $Locatio nProvider,
  2069     $LogProv ider,
  2070     $ParsePr ovider,
  2071     $RootSco peProvider ,
  2072     $QProvid er,
  2073     $$QProvi der,
  2074     $$Saniti zeUriProvi der,
  2075     $SceProv ider,
  2076     $SceDele gateProvid er,
  2077     $Sniffer Provider,
  2078     $Templat eCacheProv ider,
  2079     $Templat eRequestPr ovider,
  2080     $$Testab ilityProvi der,
  2081     $Timeout Provider,
  2082     $$RAFPro vider,
  2083     $$AsyncC allbackPro vider,
  2084     $WindowP rovider
  2085   */
  2086  
  2087  
  2088   /**
  2089    * @ngdoc  object
  2090    * @name a ngular.ver sion
  2091    * @module  ng
  2092    * @descri ption
  2093    * An obje ct that co ntains inf ormation a bout the c urrent Ang ularJS ver sion. This  object ha s the
  2094    * followi ng propert ies:
  2095    *
  2096    * - `full ` â€“ `{st ring}` â€“  Full vers ion string , such as  "0.9.18".
  2097    * - `majo r` â€“ `{n umber}` â€ “ Major ve rsion numb er, such a s "0".
  2098    * - `mino r` â€“ `{n umber}` â€ “ Minor ve rsion numb er, such a s "9".
  2099    * - `dot`  â€“ `{num ber}` â€“  Dot versio n number,  such as "1 8".
  2100    * - `code Name` â€“  `{string}`  â€“ Code  name of th e release,  such as " jiggling-a rmfat".
  2101    */
  2102   var versio n = {
  2103     full: '1 .3.5',     // all of  these plac eholder st rings will  be replac ed by grun t's
  2104     major: 1 ,    // pa ckage task
  2105     minor: 3 ,
  2106     dot: 5,
  2107     codeName : 'cyberne tic-mercan tilism'
  2108   };
  2109  
  2110  
  2111   function p ublishExte rnalAPI(an gular) {
  2112     extend(a ngular, {
  2113       'boots trap': boo tstrap,
  2114       'copy' : copy,
  2115       'exten d': extend ,
  2116       'equal s': equals ,
  2117       'eleme nt': jqLit e,
  2118       'forEa ch': forEa ch,
  2119       'injec tor': crea teInjector ,
  2120       'noop' : noop,
  2121       'bind' : bind,
  2122       'toJso n': toJson ,
  2123       'fromJ son': from Json,
  2124       'ident ity': iden tity,
  2125       'isUnd efined': i sUndefined ,
  2126       'isDef ined': isD efined,
  2127       'isStr ing': isSt ring,
  2128       'isFun ction': is Function,
  2129       'isObj ect': isOb ject,
  2130       'isNum ber': isNu mber,
  2131       'isEle ment': isE lement,
  2132       'isArr ay': isArr ay,
  2133       'versi on': versi on,
  2134       'isDat e': isDate ,
  2135       'lower case': low ercase,
  2136       'upper case': upp ercase,
  2137       'callb acks': {co unter: 0},
  2138       'getTe stability' : getTesta bility,
  2139       '$$min Err': minE rr,
  2140       '$$csp ': csp,
  2141       'reloa dWithDebug Info': rel oadWithDeb ugInfo
  2142     });
  2143  
  2144     angularM odule = se tupModuleL oader(wind ow);
  2145     try {
  2146       angula rModule('n gLocale');
  2147     } catch  (e) {
  2148       angula rModule('n gLocale',  []).provid er('$local e', $Local eProvider) ;
  2149     }
  2150  
  2151     angularM odule('ng' , ['ngLoca le'], ['$p rovide',
  2152       functi on ngModul e($provide ) {
  2153         // $ $sanitizeU riProvider  needs to  be before  $compilePr ovider as  it is used  by it.
  2154         $pro vide.provi der({
  2155           $$ sanitizeUr i: $$Sanit izeUriProv ider
  2156         });
  2157         $pro vide.provi der('$comp ile', $Com pileProvid er).
  2158           di rective({
  2159                a: htmlA nchorDirec tive,
  2160                input: i nputDirect ive,
  2161                textarea : inputDir ective,
  2162                form: fo rmDirectiv e,
  2163                script:  scriptDire ctive,
  2164                select:  selectDire ctive,
  2165                style: s tyleDirect ive,
  2166                option:  optionDire ctive,
  2167                ngBind:  ngBindDire ctive,
  2168                ngBindHt ml: ngBind HtmlDirect ive,
  2169                ngBindTe mplate: ng BindTempla teDirectiv e,
  2170                ngClass:  ngClassDi rective,
  2171                ngClassE ven: ngCla ssEvenDire ctive,
  2172                ngClassO dd: ngClas sOddDirect ive,
  2173                ngCloak:  ngCloakDi rective,
  2174                ngContro ller: ngCo ntrollerDi rective,
  2175                ngForm:  ngFormDire ctive,
  2176                ngHide:  ngHideDire ctive,
  2177                ngIf: ng IfDirectiv e,
  2178                ngInclud e: ngInclu deDirectiv e,
  2179                ngInit:  ngInitDire ctive,
  2180                ngNonBin dable: ngN onBindable Directive,
  2181                ngPlural ize: ngPlu ralizeDire ctive,
  2182                ngRepeat : ngRepeat Directive,
  2183                ngShow:  ngShowDire ctive,
  2184                ngStyle:  ngStyleDi rective,
  2185                ngSwitch : ngSwitch Directive,
  2186                ngSwitch When: ngSw itchWhenDi rective,
  2187                ngSwitch Default: n gSwitchDef aultDirect ive,
  2188                ngOption s: ngOptio nsDirectiv e,
  2189                ngTransc lude: ngTr anscludeDi rective,
  2190                ngModel:  ngModelDi rective,
  2191                ngList:  ngListDire ctive,
  2192                ngChange : ngChange Directive,
  2193                pattern:  patternDi rective,
  2194                ngPatter n: pattern Directive,
  2195                required : required Directive,
  2196                ngRequir ed: requir edDirectiv e,
  2197                minlengt h: minleng thDirectiv e,
  2198                ngMinlen gth: minle ngthDirect ive,
  2199                maxlengt h: maxleng thDirectiv e,
  2200                ngMaxlen gth: maxle ngthDirect ive,
  2201                ngValue:  ngValueDi rective,
  2202                ngModelO ptions: ng ModelOptio nsDirectiv e
  2203           }) .
  2204           di rective({
  2205              ngInclude:  ngInclude FillConten tDirective
  2206           }) .
  2207           di rective(ng AttributeA liasDirect ives).
  2208           di rective(ng EventDirec tives);
  2209         $pro vide.provi der({
  2210           $a nchorScrol l: $Anchor ScrollProv ider,
  2211           $a nimate: $A nimateProv ider,
  2212           $b rowser: $B rowserProv ider,
  2213           $c acheFactor y: $CacheF actoryProv ider,
  2214           $c ontroller:  $Controll erProvider ,
  2215           $d ocument: $ DocumentPr ovider,
  2216           $e xceptionHa ndler: $Ex ceptionHan dlerProvid er,
  2217           $f ilter: $Fi lterProvid er,
  2218           $i nterpolate : $Interpo lateProvid er,
  2219           $i nterval: $ IntervalPr ovider,
  2220           $h ttp: $Http Provider,
  2221           $h ttpBackend : $HttpBac kendProvid er,
  2222           $l ocation: $ LocationPr ovider,
  2223           $l og: $LogPr ovider,
  2224           $p arse: $Par seProvider ,
  2225           $r ootScope:  $RootScope Provider,
  2226           $q : $QProvid er,
  2227           $$ q: $$QProv ider,
  2228           $s ce: $ScePr ovider,
  2229           $s ceDelegate : $SceDele gateProvid er,
  2230           $s niffer: $S nifferProv ider,
  2231           $t emplateCac he: $Templ ateCachePr ovider,
  2232           $t emplateReq uest: $Tem plateReque stProvider ,
  2233           $$ testabilit y: $$Testa bilityProv ider,
  2234           $t imeout: $T imeoutProv ider,
  2235           $w indow: $Wi ndowProvid er,
  2236           $$ rAF: $$RAF Provider,
  2237           $$ asyncCallb ack: $$Asy ncCallback Provider
  2238         });
  2239       }
  2240     ]);
  2241   }
  2242  
  2243   /* global  JQLiteProt otype: tru e,
  2244     addEvent ListenerFn : true,
  2245     removeEv entListene rFn: true,
  2246     BOOLEAN_ ATTR: true ,
  2247     ALIASED_ ATTR: true ,
  2248   */
  2249  
  2250   ////////// ////////// ////////// ////
  2251   //JQLite
  2252   ////////// ////////// ////////// ////
  2253  
  2254   /**
  2255    * @ngdoc  function
  2256    * @name a ngular.ele ment
  2257    * @module  ng
  2258    * @kind f unction
  2259    *
  2260    * @descri ption
  2261    * Wraps a  raw DOM e lement or  HTML strin g as a [jQ uery](http ://jquery. com) eleme nt.
  2262    *
  2263    * If jQue ry is avai lable, `an gular.elem ent` is an  alias for  the
  2264    * [jQuery ](http://a pi.jquery. com/jQuery /) functio n. If jQue ry is not  available,  `angular. element`
  2265    * delegat es to Angu lar's buil t-in subse t of jQuer y, called  "jQuery li te" or "jq Lite."
  2266    *
  2267    * <div cl ass="alert  alert-suc cess">jqLi te is a ti ny, API-co mpatible s ubset of j Query that  allows
  2268    * Angular  to manipu late the D OM in a cr oss-browse r compatib le way. ** jqLite** i mplements  only the m ost
  2269    * commonl y needed f unctionali ty with th e goal of  having a v ery small  footprint. </div>
  2270    *
  2271    * To use  jQuery, si mply load  it before  `DOMConten tLoaded` e vent fired .
  2272    *
  2273    * <div cl ass="alert ">**Note:* * all elem ent refere nces in An gular are  always wra pped with  jQuery or
  2274    * jqLite;  they are  never raw  DOM refere nces.</div >
  2275    *
  2276    * ## Angu lar's jqLi te
  2277    * jqLite  provides o nly the fo llowing jQ uery metho ds:
  2278    *
  2279    * - [`add Class()`]( http://api .jquery.co m/addClass /)
  2280    * - [`aft er()`](htt p://api.jq uery.com/a fter/)
  2281    * - [`app end()`](ht tp://api.j query.com/ append/)
  2282    * - [`att r()`](http ://api.jqu ery.com/at tr/) - Doe s not supp ort functi ons as par ameters
  2283    * - [`bin d()`](http ://api.jqu ery.com/bi nd/) - Doe s not supp ort namesp aces, sele ctors or e ventData
  2284    * - [`chi ldren()`]( http://api .jquery.co m/children /) - Does  not suppor t selector s
  2285    * - [`clo ne()`](htt p://api.jq uery.com/c lone/)
  2286    * - [`con tents()`]( http://api .jquery.co m/contents /)
  2287    * - [`css ()`](http: //api.jque ry.com/css /) - Only  retrieves  inline-sty les, does  not call ` getCompute dStyle()`
  2288    * - [`dat a()`](http ://api.jqu ery.com/da ta/)
  2289    * - [`det ach()`](ht tp://api.j query.com/ detach/)
  2290    * - [`emp ty()`](htt p://api.jq uery.com/e mpty/)
  2291    * - [`eq( )`](http:/ /api.jquer y.com/eq/)
  2292    * - [`fin d()`](http ://api.jqu ery.com/fi nd/) - Lim ited to lo okups by t ag name
  2293    * - [`has Class()`]( http://api .jquery.co m/hasClass /)
  2294    * - [`htm l()`](http ://api.jqu ery.com/ht ml/)
  2295    * - [`nex t()`](http ://api.jqu ery.com/ne xt/) - Doe s not supp ort select ors
  2296    * - [`on( )`](http:/ /api.jquer y.com/on/)  - Does no t support  namespaces , selector s or event Data
  2297    * - [`off ()`](http: //api.jque ry.com/off /) - Does  not suppor t namespac es or sele ctors
  2298    * - [`one ()`](http: //api.jque ry.com/one /) - Does  not suppor t namespac es or sele ctors
  2299    * - [`par ent()`](ht tp://api.j query.com/ parent/) -  Does not  support se lectors
  2300    * - [`pre pend()`](h ttp://api. jquery.com /prepend/)
  2301    * - [`pro p()`](http ://api.jqu ery.com/pr op/)
  2302    * - [`rea dy()`](htt p://api.jq uery.com/r eady/)
  2303    * - [`rem ove()`](ht tp://api.j query.com/ remove/)
  2304    * - [`rem oveAttr()` ](http://a pi.jquery. com/remove Attr/)
  2305    * - [`rem oveClass() `](http:// api.jquery .com/remov eClass/)
  2306    * - [`rem oveData()` ](http://a pi.jquery. com/remove Data/)
  2307    * - [`rep laceWith() `](http:// api.jquery .com/repla ceWith/)
  2308    * - [`tex t()`](http ://api.jqu ery.com/te xt/)
  2309    * - [`tog gleClass() `](http:// api.jquery .com/toggl eClass/)
  2310    * - [`tri ggerHandle r()`](http ://api.jqu ery.com/tr iggerHandl er/) - Pas ses a dumm y event ob ject to ha ndlers.
  2311    * - [`unb ind()`](ht tp://api.j query.com/ unbind/) -  Does not  support na mespaces
  2312    * - [`val ()`](http: //api.jque ry.com/val /)
  2313    * - [`wra p()`](http ://api.jqu ery.com/wr ap/)
  2314    *
  2315    * ## jQue ry/jqLite  Extras
  2316    * Angular  also prov ides the f ollowing a dditional  methods an d events t o both jQu ery and jq Lite:
  2317    *
  2318    * ### Eve nts
  2319    * - `$des troy` - An gularJS in tercepts a ll jqLite/ jQuery's D OM destruc tion apis  and fires  this event
  2320    *    on a ll DOM nod es being r emoved.  T his can be  used to c lean up an y 3rd part y bindings  to the DO M
  2321    *    elem ent before  it is rem oved.
  2322    *
  2323    * ### Met hods
  2324    * - `cont roller(nam e)` - retr ieves the  controller  of the cu rrent elem ent or its  parent. B y default
  2325    *   retri eves contr oller asso ciated wit h the `ngC ontroller`  directive . If `name ` is provi ded as
  2326    *   camel Case direc tive name,  then the  controller  for this  directive  will be re trieved (e .g.
  2327    *   `'ngM odel'`).
  2328    * - `inje ctor()` -  retrieves  the inject or of the  current el ement or i ts parent.
  2329    * - `scop e()` - ret rieves the  {@link ng .$rootScop e.Scope sc ope} of th e current
  2330    *   eleme nt or its  parent. Re quires {@l ink guide/ production #disabling -debug-dat a Debug Da ta} to
  2331    *   be en abled.
  2332    * - `isol ateScope() ` - retrie ves an iso late {@lin k ng.$root Scope.Scop e scope} i f one is a ttached di rectly to  the
  2333    *   curre nt element . This get ter should  be used o nly on ele ments that  contain a  directive  which sta rts a new  isolate
  2334    *   scope . Calling  `scope()`  on this el ement alwa ys returns  the origi nal non-is olate scop e.
  2335    *   Requi res {@link  guide/pro duction#di sabling-de bug-data D ebug Data}  to be ena bled.
  2336    * - `inhe ritedData( )` - same  as `data() `, but wal ks up the  DOM until  a value is  found or  the top
  2337    *   paren t element  is reached .
  2338    *
  2339    * @param  {string|DO MElement}  element HT ML string  or DOMElem ent to be  wrapped in to jQuery.
  2340    * @return s {Object}  jQuery ob ject.
  2341    */
  2342  
  2343   JQLite.exp ando = 'ng 339';
  2344  
  2345   var jqCach e = JQLite .cache = { },
  2346       jqId =  1,
  2347       addEve ntListener Fn = funct ion(elemen t, type, f n) {
  2348         elem ent.addEve ntListener (type, fn,  false);
  2349       },
  2350       remove EventListe nerFn = fu nction(ele ment, type , fn) {
  2351         elem ent.remove EventListe ner(type,  fn, false) ;
  2352       };
  2353  
  2354   /*
  2355    * !!! Thi s is an un documented  "private"  function  !!!
  2356    */
  2357   JQLite._da ta = funct ion(node)  {
  2358     //jQuery  always re turns an o bject on c ache miss
  2359     return t his.cache[ node[this. expando]]  || {};
  2360   };
  2361  
  2362   function j qNextId()  { return + +jqId; }
  2363  
  2364  
  2365   var SPECIA L_CHARS_RE GEXP = /([ \:\-\_]+(. ))/g;
  2366   var MOZ_HA CK_REGEXP  = /^moz([A -Z])/;
  2367   var MOUSE_ EVENT_MAP=  { mousele ave: "mous eout", mou seenter: " mouseover" };
  2368   var jqLite MinErr = m inErr('jqL ite');
  2369  
  2370   /**
  2371    * Convert s snake_ca se to came lCase.
  2372    * Also th ere is spe cial case  for Moz pr efix start ing with u pper case  letter.
  2373    * @param  name Name  to normali ze
  2374    */
  2375   function c amelCase(n ame) {
  2376     return n ame.
  2377       replac e(SPECIAL_ CHARS_REGE XP, functi on(_, sepa rator, let ter, offse t) {
  2378         retu rn offset  ? letter.t oUpperCase () : lette r;
  2379       }).
  2380       replac e(MOZ_HACK _REGEXP, ' Moz$1');
  2381   }
  2382  
  2383   var SINGLE _TAG_REGEX P = /^<(\w +)\s*\/?>( ?:<\/\1>|) $/;
  2384   var HTML_R EGEXP = /< |&#?\w+;/;
  2385   var TAG_NA ME_REGEXP  = /<([\w:] +)/;
  2386   var XHTML_ TAG_REGEXP  = /<(?!ar ea|br|col| embed|hr|i mg|input|l ink|meta|p aram)(([\w :]+)[^>]*) \/>/gi;
  2387  
  2388   var wrapMa p = {
  2389     'option' : [1, '<se lect multi ple="multi ple">', '< /select>'] ,
  2390  
  2391     'thead':  [1, '<tab le>', '</t able>'],
  2392     'col': [ 2, '<table ><colgroup >', '</col group></ta ble>'],
  2393     'tr': [2 , '<table> <tbody>',  '</tbody>< /table>'],
  2394     'td': [3 , '<table> <tbody><tr >', '</tr> </tbody></ table>'],
  2395     '_defaul t': [0, "" , ""]
  2396   };
  2397  
  2398   wrapMap.op tgroup = w rapMap.opt ion;
  2399   wrapMap.tb ody = wrap Map.tfoot  = wrapMap. colgroup =  wrapMap.c aption = w rapMap.the ad;
  2400   wrapMap.th  = wrapMap .td;
  2401  
  2402  
  2403   function j qLiteIsTex tNode(html ) {
  2404     return ! HTML_REGEX P.test(htm l);
  2405   }
  2406  
  2407   function j qLiteAccep tsData(nod e) {
  2408     // The w indow obje ct can acc ept data b ut has no  nodeType
  2409     // Other wise we ar e only int erested in  elements  (1) and do cuments (9 )
  2410     var node Type = nod e.nodeType ;
  2411     return n odeType == = NODE_TYP E_ELEMENT  || !nodeTy pe || node Type === N ODE_TYPE_D OCUMENT;
  2412   }
  2413  
  2414   function j qLiteBuild Fragment(h tml, conte xt) {
  2415     var tmp,  tag, wrap ,
  2416         frag ment = con text.creat eDocumentF ragment(),
  2417         node s = [], i;
  2418  
  2419     if (jqLi teIsTextNo de(html))  {
  2420       // Con vert non-h tml into a  text node
  2421       nodes. push(conte xt.createT extNode(ht ml));
  2422     } else {
  2423       // Con vert html  into DOM n odes
  2424       tmp =  tmp || fra gment.appe ndChild(co ntext.crea teElement( "div"));
  2425       tag =  (TAG_NAME_ REGEXP.exe c(html) ||  ["", ""]) [1].toLowe rCase();
  2426       wrap =  wrapMap[t ag] || wra pMap._defa ult;
  2427       tmp.in nerHTML =  wrap[1] +  html.repla ce(XHTML_T AG_REGEXP,  "<$1></$2 >") + wrap [2];
  2428  
  2429       // Des cend throu gh wrapper s to the r ight conte nt
  2430       i = wr ap[0];
  2431       while  (i--) {
  2432         tmp  = tmp.last Child;
  2433       }
  2434  
  2435       nodes  = concat(n odes, tmp. childNodes );
  2436  
  2437       tmp =  fragment.f irstChild;
  2438       tmp.te xtContent  = "";
  2439     }
  2440  
  2441     // Remov e wrapper  from fragm ent
  2442     fragment .textConte nt = "";
  2443     fragment .innerHTML  = ""; //  Clear inne r HTML
  2444     forEach( nodes, fun ction(node ) {
  2445       fragme nt.appendC hild(node) ;
  2446     });
  2447  
  2448     return f ragment;
  2449   }
  2450  
  2451   function j qLiteParse HTML(html,  context)  {
  2452     context  = context  || documen t;
  2453     var pars ed;
  2454  
  2455     if ((par sed = SING LE_TAG_REG EXP.exec(h tml))) {
  2456       return  [context. createElem ent(parsed [1])];
  2457     }
  2458  
  2459     if ((par sed = jqLi teBuildFra gment(html , context) )) {
  2460       return  parsed.ch ildNodes;
  2461     }
  2462  
  2463     return [ ];
  2464   }
  2465  
  2466   ////////// ////////// ////////// ////////// /////
  2467   function J QLite(elem ent) {
  2468     if (elem ent instan ceof JQLit e) {
  2469       return  element;
  2470     }
  2471  
  2472     var argI sString;
  2473  
  2474     if (isSt ring(eleme nt)) {
  2475       elemen t = trim(e lement);
  2476       argIsS tring = tr ue;
  2477     }
  2478     if (!(th is instanc eof JQLite )) {
  2479       if (ar gIsString  && element .charAt(0)  != '<') {
  2480         thro w jqLiteMi nErr('nose l', 'Looki ng up elem ents via s electors i s not supp orted by j qLite! See : http://d ocs.angula rjs.org/ap i/angular. element');
  2481       }
  2482       return  new JQLit e(element) ;
  2483     }
  2484  
  2485     if (argI sString) {
  2486       jqLite AddNodes(t his, jqLit eParseHTML (element)) ;
  2487     } else {
  2488       jqLite AddNodes(t his, eleme nt);
  2489     }
  2490   }
  2491  
  2492   function j qLiteClone (element)  {
  2493     return e lement.clo neNode(tru e);
  2494   }
  2495  
  2496   function j qLiteDealo c(element,  onlyDesce ndants) {
  2497     if (!onl yDescendan ts) jqLite RemoveData (element);
  2498  
  2499     if (elem ent.queryS electorAll ) {
  2500       var de scendants  = element. querySelec torAll('*' );
  2501       for (v ar i = 0,  l = descen dants.leng th; i < l;  i++) {
  2502         jqLi teRemoveDa ta(descend ants[i]);
  2503       }
  2504     }
  2505   }
  2506  
  2507   function j qLiteOff(e lement, ty pe, fn, un supported)  {
  2508     if (isDe fined(unsu pported))  throw jqLi teMinErr(' offargs',  'jqLite#of f() does n ot support  the `sele ctor` argu ment');
  2509  
  2510     var expa ndoStore =  jqLiteExp andoStore( element);
  2511     var even ts = expan doStore &&  expandoSt ore.events ;
  2512     var hand le = expan doStore &&  expandoSt ore.handle ;
  2513  
  2514     if (!han dle) retur n; //no li steners re gistered
  2515  
  2516     if (!typ e) {
  2517       for (t ype in eve nts) {
  2518         if ( type !== ' $destroy')  {
  2519           re moveEventL istenerFn( element, t ype, handl e);
  2520         }
  2521         dele te events[ type];
  2522       }
  2523     } else {
  2524       forEac h(type.spl it(' '), f unction(ty pe) {
  2525         if ( isDefined( fn)) {
  2526           va r listener Fns = even ts[type];
  2527           ar rayRemove( listenerFn s || [], f n);
  2528           if  (listener Fns && lis tenerFns.l ength > 0)  {
  2529              return;
  2530           }
  2531         }
  2532  
  2533         remo veEventLis tenerFn(el ement, typ e, handle) ;
  2534         dele te events[ type];
  2535       });
  2536     }
  2537   }
  2538  
  2539   function j qLiteRemov eData(elem ent, name)  {
  2540     var expa ndoId = el ement.ng33 9;
  2541     var expa ndoStore =  expandoId  && jqCach e[expandoI d];
  2542  
  2543     if (expa ndoStore)  {
  2544       if (na me) {
  2545         dele te expando Store.data [name];
  2546         retu rn;
  2547       }
  2548  
  2549       if (ex pandoStore .handle) {
  2550         if ( expandoSto re.events. $destroy)  {
  2551           ex pandoStore .handle({} , '$destro y');
  2552         }
  2553         jqLi teOff(elem ent);
  2554       }
  2555       delete  jqCache[e xpandoId];
  2556       elemen t.ng339 =  undefined;  // don't  delete DOM  expandos.  IE and Ch rome don't  like it
  2557     }
  2558   }
  2559  
  2560  
  2561   function j qLiteExpan doStore(el ement, cre ateIfNeces sary) {
  2562     var expa ndoId = el ement.ng33 9,
  2563         expa ndoStore =  expandoId  && jqCach e[expandoI d];
  2564  
  2565     if (crea teIfNecess ary && !ex pandoStore ) {
  2566       elemen t.ng339 =  expandoId  = jqNextId ();
  2567       expand oStore = j qCache[exp andoId] =  {events: { }, data: { }, handle:  undefined };
  2568     }
  2569  
  2570     return e xpandoStor e;
  2571   }
  2572  
  2573  
  2574   function j qLiteData( element, k ey, value)  {
  2575     if (jqLi teAcceptsD ata(elemen t)) {
  2576  
  2577       var is SimpleSett er = isDef ined(value );
  2578       var is SimpleGett er = !isSi mpleSetter  && key &&  !isObject (key);
  2579       var ma ssGetter =  !key;
  2580       var ex pandoStore  = jqLiteE xpandoStor e(element,  !isSimple Getter);
  2581       var da ta = expan doStore &&  expandoSt ore.data;
  2582  
  2583       if (is SimpleSett er) { // d ata('key',  value)
  2584         data [key] = va lue;
  2585       } else  {
  2586         if ( massGetter ) {  // da ta()
  2587           re turn data;
  2588         } el se {
  2589           if  (isSimple Getter) {  // data('k ey')
  2590              // don't f orce creat ion of exp andoStore  if it does n't exist  yet
  2591              return dat a && data[ key];
  2592           }  else { //  mass-sette r: data({k ey1: val1,  key2: val 2})
  2593              extend(dat a, key);
  2594           }
  2595         }
  2596       }
  2597     }
  2598   }
  2599  
  2600   function j qLiteHasCl ass(elemen t, selecto r) {
  2601     if (!ele ment.getAt tribute) r eturn fals e;
  2602     return ( (" " + (el ement.getA ttribute(' class') ||  '') + " " ).replace( /[\n\t]/g,  " ").
  2603         inde xOf(" " +  selector +  " ") > -1 );
  2604   }
  2605  
  2606   function j qLiteRemov eClass(ele ment, cssC lasses) {
  2607     if (cssC lasses &&  element.se tAttribute ) {
  2608       forEac h(cssClass es.split('  '), funct ion(cssCla ss) {
  2609         elem ent.setAtt ribute('cl ass', trim (
  2610              (" " + (el ement.getA ttribute(' class') ||  '') + " " )
  2611              .replace(/ [\n\t]/g,  " ")
  2612              .replace("  " + trim( cssClass)  + " ", " " ))
  2613         );
  2614       });
  2615     }
  2616   }
  2617  
  2618   function j qLiteAddCl ass(elemen t, cssClas ses) {
  2619     if (cssC lasses &&  element.se tAttribute ) {
  2620       var ex istingClas ses = (' '  + (elemen t.getAttri bute('clas s') || '')  + ' ')
  2621                                 .r eplace(/[\ n\t]/g, "  ");
  2622  
  2623       forEac h(cssClass es.split('  '), funct ion(cssCla ss) {
  2624         cssC lass = tri m(cssClass );
  2625         if ( existingCl asses.inde xOf(' ' +  cssClass +  ' ') ===  -1) {
  2626           ex istingClas ses += css Class + '  ';
  2627         }
  2628       });
  2629  
  2630       elemen t.setAttri bute('clas s', trim(e xistingCla sses));
  2631     }
  2632   }
  2633  
  2634  
  2635   function j qLiteAddNo des(root,  elements)  {
  2636     // THIS  CODE IS VE RY HOT. Do n't make c hanges wit hout bench marking.
  2637  
  2638     if (elem ents) {
  2639  
  2640       // if  a Node (th e most com mon case)
  2641       if (el ements.nod eType) {
  2642         root [root.leng th++] = el ements;
  2643       } else  {
  2644         var  length = e lements.le ngth;
  2645  
  2646         // i f an Array  or NodeLi st and not  a Window
  2647         if ( typeof len gth === 'n umber' &&  elements.w indow !==  elements)  {
  2648           if  (length)  {
  2649              for (var i  = 0; i <  length; i+ +) {
  2650                root[roo t.length++ ] = elemen ts[i];
  2651              }
  2652           }
  2653         } el se {
  2654           ro ot[root.le ngth++] =  elements;
  2655         }
  2656       }
  2657     }
  2658   }
  2659  
  2660  
  2661   function j qLiteContr oller(elem ent, name)  {
  2662     return j qLiteInher itedData(e lement, '$ ' + (name  || 'ngCont roller') +  'Controll er');
  2663   }
  2664  
  2665   function j qLiteInher itedData(e lement, na me, value)  {
  2666     // if el ement is t he documen t object w ork with t he html el ement inst ead
  2667     // this  makes $(do cument).sc ope() poss ible
  2668     if (elem ent.nodeTy pe == NODE _TYPE_DOCU MENT) {
  2669       elemen t = elemen t.document Element;
  2670     }
  2671     var name s = isArra y(name) ?  name : [na me];
  2672  
  2673     while (e lement) {
  2674       for (v ar i = 0,  ii = names .length; i  < ii; i++ ) {
  2675         if ( (value = j qLite.data (element,  names[i]))  !== undef ined) retu rn value;
  2676       }
  2677  
  2678       // If  dealing wi th a docum ent fragme nt node wi th a host  element, a nd no pare nt, use th e host
  2679       // ele ment as th e parent.  This enabl es directi ves within  a Shadow  DOM or pol yfilled Sh adow DOM
  2680       // to  lookup par ent contro llers.
  2681       elemen t = elemen t.parentNo de || (ele ment.nodeT ype === NO DE_TYPE_DO CUMENT_FRA GMENT && e lement.hos t);
  2682     }
  2683   }
  2684  
  2685   function j qLiteEmpty (element)  {
  2686     jqLiteDe aloc(eleme nt, true);
  2687     while (e lement.fir stChild) {
  2688       elemen t.removeCh ild(elemen t.firstChi ld);
  2689     }
  2690   }
  2691  
  2692   function j qLiteRemov e(element,  keepData)  {
  2693     if (!kee pData) jqL iteDealoc( element);
  2694     var pare nt = eleme nt.parentN ode;
  2695     if (pare nt) parent .removeChi ld(element );
  2696   }
  2697  
  2698  
  2699   function j qLiteDocum entLoaded( action, wi n) {
  2700     win = wi n || windo w;
  2701     if (win. document.r eadyState  === 'compl ete') {
  2702       // For ce the act ion to be  run async  for consis tent behav iour
  2703       // fro m the acti on's point  of view
  2704       // i.e . it will  definitely  not be in  a $apply
  2705       win.se tTimeout(a ction);
  2706     } else {
  2707       // No  need to un bind this  handler as  load is o nly ever c alled once
  2708       jqLite (win).on(' load', act ion);
  2709     }
  2710   }
  2711  
  2712   ////////// ////////// ////////// ////////// //
  2713   // Functio ns which a re declare d directly .
  2714   ////////// ////////// ////////// ////////// //
  2715   var JQLite Prototype  = JQLite.p rototype =  {
  2716     ready: f unction(fn ) {
  2717       var fi red = fals e;
  2718  
  2719       functi on trigger () {
  2720         if ( fired) ret urn;
  2721         fire d = true;
  2722         fn() ;
  2723       }
  2724  
  2725       // che ck if docu ment is al ready load ed
  2726       if (do cument.rea dyState == = 'complet e') {
  2727         setT imeout(tri gger);
  2728       } else  {
  2729         this .on('DOMCo ntentLoade d', trigge r); // wor ks for mod ern browse rs and IE9
  2730         // w e can not  use jqLite  since we  are not do ne loading  and jQuer y could be  loaded la ter.
  2731         // j shint -W06 4
  2732         JQLi te(window) .on('load' , trigger) ; // fallb ack to win dow.onload  for other s
  2733         // j shint +W06 4
  2734       }
  2735     },
  2736     toString : function () {
  2737       var va lue = [];
  2738       forEac h(this, fu nction(e)  { value.pu sh('' + e) ;});
  2739       return  '[' + val ue.join(',  ') + ']';
  2740     },
  2741  
  2742     eq: func tion(index ) {
  2743         retu rn (index  >= 0) ? jq Lite(this[ index]) :  jqLite(thi s[this.len gth + inde x]);
  2744     },
  2745  
  2746     length:  0,
  2747     push: pu sh,
  2748     sort: [] .sort,
  2749     splice:  [].splice
  2750   };
  2751  
  2752   ////////// ////////// ////////// ////////// //
  2753   // Functio ns iterati ng getter/ setters.
  2754   // these f unctions r eturn self  on setter  and
  2755   // value o n get.
  2756   ////////// ////////// ////////// ////////// //
  2757   var BOOLEA N_ATTR = { };
  2758   forEach('m ultiple,se lected,che cked,disab led,readOn ly,require d,open'.sp lit(','),  function(v alue) {
  2759     BOOLEAN_ ATTR[lower case(value )] = value ;
  2760   });
  2761   var BOOLEA N_ELEMENTS  = {};
  2762   forEach('i nput,selec t,option,t extarea,bu tton,form, details'.s plit(','),  function( value) {
  2763     BOOLEAN_ ELEMENTS[v alue] = tr ue;
  2764   });
  2765   var ALIASE D_ATTR = {
  2766     'ngMinle ngth': 'mi nlength',
  2767     'ngMaxle ngth': 'ma xlength',
  2768     'ngMin':  'min',
  2769     'ngMax':  'max',
  2770     'ngPatte rn': 'patt ern'
  2771   };
  2772  
  2773   function g etBooleanA ttrName(el ement, nam e) {
  2774     // check  dom last  since we w ill most l ikely fail  on name
  2775     var bool eanAttr =  BOOLEAN_AT TR[name.to LowerCase( )];
  2776  
  2777     // boole anAttr is  here twice  to minimi ze DOM acc ess
  2778     return b ooleanAttr  && BOOLEA N_ELEMENTS [nodeName_ (element)]  && boolea nAttr;
  2779   }
  2780  
  2781   function g etAliasedA ttrName(el ement, nam e) {
  2782     var node Name = ele ment.nodeN ame;
  2783     return ( nodeName = == 'INPUT'  || nodeNa me === 'TE XTAREA') & & ALIASED_ ATTR[name] ;
  2784   }
  2785  
  2786   forEach({
  2787     data: jq LiteData,
  2788     removeDa ta: jqLite RemoveData
  2789   }, functio n(fn, name ) {
  2790     JQLite[n ame] = fn;
  2791   });
  2792  
  2793   forEach({
  2794     data: jq LiteData,
  2795     inherite dData: jqL iteInherit edData,
  2796  
  2797     scope: f unction(el ement) {
  2798       // Can 't use jqL iteData he re directl y so we st ay compati ble with j Query!
  2799       return  jqLite.da ta(element , '$scope' ) || jqLit eInherited Data(eleme nt.parentN ode || ele ment, ['$i solateScop e', '$scop e']);
  2800     },
  2801  
  2802     isolateS cope: func tion(eleme nt) {
  2803       // Can 't use jqL iteData he re directl y so we st ay compati ble with j Query!
  2804       return  jqLite.da ta(element , '$isolat eScope') | | jqLite.d ata(elemen t, '$isola teScopeNoT emplate');
  2805     },
  2806  
  2807     controll er: jqLite Controller ,
  2808  
  2809     injector : function (element)  {
  2810       return  jqLiteInh eritedData (element,  '$injector ');
  2811     },
  2812  
  2813     removeAt tr: functi on(element , name) {
  2814       elemen t.removeAt tribute(na me);
  2815     },
  2816  
  2817     hasClass : jqLiteHa sClass,
  2818  
  2819     css: fun ction(elem ent, name,  value) {
  2820       name =  camelCase (name);
  2821  
  2822       if (is Defined(va lue)) {
  2823         elem ent.style[ name] = va lue;
  2824       } else  {
  2825         retu rn element .style[nam e];
  2826       }
  2827     },
  2828  
  2829     attr: fu nction(ele ment, name , value) {
  2830       var lo wercasedNa me = lower case(name) ;
  2831       if (BO OLEAN_ATTR [lowercase dName]) {
  2832         if ( isDefined( value)) {
  2833           if  (!!value)  {
  2834              element[na me] = true ;
  2835              element.se tAttribute (name, low ercasedNam e);
  2836           }  else {
  2837              element[na me] = fals e;
  2838              element.re moveAttrib ute(lowerc asedName);
  2839           }
  2840         } el se {
  2841           re turn (elem ent[name]  ||
  2842                     (el ement.attr ibutes.get NamedItem( name) || n oop).speci fied)
  2843                   ? low ercasedNam e
  2844                   : und efined;
  2845         }
  2846       } else  if (isDef ined(value )) {
  2847         elem ent.setAtt ribute(nam e, value);
  2848       } else  if (eleme nt.getAttr ibute) {
  2849         // t he extra a rgument "2 " is to ge t the righ t thing fo r a.href i n IE, see  jQuery cod e
  2850         // s ome elemen ts (e.g. D ocument) d on't have  get attrib ute, so re turn undef ined
  2851         var  ret = elem ent.getAtt ribute(nam e, 2);
  2852         // n ormalize n on-existin g attribut es to unde fined (as  jQuery)
  2853         retu rn ret ===  null ? un defined :  ret;
  2854       }
  2855     },
  2856  
  2857     prop: fu nction(ele ment, name , value) {
  2858       if (is Defined(va lue)) {
  2859         elem ent[name]  = value;
  2860       } else  {
  2861         retu rn element [name];
  2862       }
  2863     },
  2864  
  2865     text: (f unction()  {
  2866       getTex t.$dv = '' ;
  2867       return  getText;
  2868  
  2869       functi on getText (element,  value) {
  2870         if ( isUndefine d(value))  {
  2871           va r nodeType  = element .nodeType;
  2872           re turn (node Type === N ODE_TYPE_E LEMENT ||  nodeType = == NODE_TY PE_TEXT) ?  element.t extContent  : '';
  2873         }
  2874         elem ent.textCo ntent = va lue;
  2875       }
  2876     })(),
  2877  
  2878     val: fun ction(elem ent, value ) {
  2879       if (is Undefined( value)) {
  2880         if ( element.mu ltiple &&  nodeName_( element) = == 'select ') {
  2881           va r result =  [];
  2882           fo rEach(elem ent.option s, functio n(option)  {
  2883              if (option .selected)  {
  2884                result.p ush(option .value ||  option.tex t);
  2885              }
  2886           }) ;
  2887           re turn resul t.length = == 0 ? nul l : result ;
  2888         }
  2889         retu rn element .value;
  2890       }
  2891       elemen t.value =  value;
  2892     },
  2893  
  2894     html: fu nction(ele ment, valu e) {
  2895       if (is Undefined( value)) {
  2896         retu rn element .innerHTML ;
  2897       }
  2898       jqLite Dealoc(ele ment, true );
  2899       elemen t.innerHTM L = value;
  2900     },
  2901  
  2902     empty: j qLiteEmpty
  2903   }, functio n(fn, name ) {
  2904     /**
  2905      * Prope rties: wri tes return  selection , reads re turn first  value
  2906      */
  2907     JQLite.p rototype[n ame] = fun ction(arg1 , arg2) {
  2908       var i,  key;
  2909       var no deCount =  this.lengt h;
  2910  
  2911       // jqL iteHasClas s has only  two argum ents, but  is a gette r-only fn,  so we nee d to speci al-case it
  2912       // in  a way that  survives  minificati on.
  2913       // jqL iteEmpty t akes no ar guments bu t is a set ter.
  2914       if (fn  !== jqLit eEmpty &&
  2915           (( (fn.length  == 2 && ( fn !== jqL iteHasClas s && fn != = jqLiteCo ntroller))  ? arg1 :  arg2) ===  undefined) ) {
  2916         if ( isObject(a rg1)) {
  2917  
  2918           //  we are a  write, but  the objec t properti es are the  key/value s
  2919           fo r (i = 0;  i < nodeCo unt; i++)  {
  2920              if (fn ===  jqLiteDat a) {
  2921                // data( ) takes th e whole ob ject in jQ uery
  2922                fn(this[ i], arg1);
  2923              } else {
  2924                for (key  in arg1)  {
  2925                  fn(thi s[i], key,  arg1[key] );
  2926                }
  2927              }
  2928           }
  2929           //  return se lf for cha ining
  2930           re turn this;
  2931         } el se {
  2932           //  we are a  read, so r ead the fi rst child.
  2933           //  TODO: do  we still n eed this?
  2934           va r value =  fn.$dv;
  2935           //  Only if w e have $dv  do we ite rate over  all, other wise it is  just the  first elem ent.
  2936           va r jj = (va lue === un defined) ?  Math.min( nodeCount,  1) : node Count;
  2937           fo r (var j =  0; j < jj ; j++) {
  2938              var nodeVa lue = fn(t his[j], ar g1, arg2);
  2939              value = va lue ? valu e + nodeVa lue : node Value;
  2940           }
  2941           re turn value ;
  2942         }
  2943       } else  {
  2944         // w e are a wr ite, so ap ply to all  children
  2945         for  (i = 0; i  < nodeCoun t; i++) {
  2946           fn (this[i],  arg1, arg2 );
  2947         }
  2948         // r eturn self  for chain ing
  2949         retu rn this;
  2950       }
  2951     };
  2952   });
  2953  
  2954   function c reateEvent Handler(el ement, eve nts) {
  2955     var even tHandler =  function( event, typ e) {
  2956       // jQu ery specif ic api
  2957       event. isDefaultP revented =  function( ) {
  2958         retu rn event.d efaultPrev ented;
  2959       };
  2960  
  2961       var ev entFns = e vents[type  || event. type];
  2962       var ev entFnsLeng th = event Fns ? even tFns.lengt h : 0;
  2963  
  2964       if (!e ventFnsLen gth) retur n;
  2965  
  2966       if (is Undefined( event.imme diatePropa gationStop ped)) {
  2967         var  originalSt opImmediat ePropagati on = event .stopImmed iatePropag ation;
  2968         even t.stopImme diatePropa gation = f unction()  {
  2969           ev ent.immedi atePropaga tionStoppe d = true;
  2970  
  2971           if  (event.st opPropagat ion) {
  2972              event.stop Propagatio n();
  2973           }
  2974  
  2975           if  (original StopImmedi atePropaga tion) {
  2976              originalSt opImmediat ePropagati on.call(ev ent);
  2977           }
  2978         };
  2979       }
  2980  
  2981       event. isImmediat ePropagati onStopped  = function () {
  2982         retu rn event.i mmediatePr opagationS topped ===  true;
  2983       };
  2984  
  2985       // Cop y event ha ndlers in  case event  handlers  array is m odified du ring execu tion.
  2986       if ((e ventFnsLen gth > 1))  {
  2987         even tFns = sha llowCopy(e ventFns);
  2988       }
  2989  
  2990       for (v ar i = 0;  i < eventF nsLength;  i++) {
  2991         if ( !event.isI mmediatePr opagationS topped())  {
  2992           ev entFns[i]. call(eleme nt, event) ;
  2993         }
  2994       }
  2995     };
  2996  
  2997     // TODO:  this is a  hack for  angularMoc ks/clearDa taCache th at makes i t possible  to deregi ster all
  2998     //        events on  `element`
  2999     eventHan dler.elem  = element;
  3000     return e ventHandle r;
  3001   }
  3002  
  3003   ////////// ////////// ////////// ////////// //
  3004   // Functio ns iterati ng travers al.
  3005   // These f unctions c hain resul ts into a  single
  3006   // selecto r.
  3007   ////////// ////////// ////////// ////////// //
  3008   forEach({
  3009     removeDa ta: jqLite RemoveData ,
  3010  
  3011     on: func tion jqLit eOn(elemen t, type, f n, unsuppo rted) {
  3012       if (is Defined(un supported) ) throw jq LiteMinErr ('onargs',  'jqLite#o n() does n ot support  the `sele ctor` or ` eventData`  parameter s');
  3013  
  3014       // Do  not add ev ent handle rs to non- elements b ecause the y will not  be cleane d up.
  3015       if (!j qLiteAccep tsData(ele ment)) {
  3016         retu rn;
  3017       }
  3018  
  3019       var ex pandoStore  = jqLiteE xpandoStor e(element,  true);
  3020       var ev ents = exp andoStore. events;
  3021       var ha ndle = exp andoStore. handle;
  3022  
  3023       if (!h andle) {
  3024         hand le = expan doStore.ha ndle = cre ateEventHa ndler(elem ent, event s);
  3025       }
  3026  
  3027       // htt p://jsperf .com/strin g-indexof- vs-split
  3028       var ty pes = type .indexOf('  ') >= 0 ?  type.spli t(' ') : [ type];
  3029       var i  = types.le ngth;
  3030  
  3031       while  (i--) {
  3032         type  = types[i ];
  3033         var  eventFns =  events[ty pe];
  3034  
  3035         if ( !eventFns)  {
  3036           ev ents[type]  = [];
  3037  
  3038           if  (type ===  'mouseent er' || typ e === 'mou seleave')  {
  3039              // Refer t o jQuery's  implement ation of m ouseenter  & mouselea ve
  3040              // Read ab out mousee nter and m ouseleave:
  3041              // http:// www.quirks mode.org/j s/events_m ouse.html# link8
  3042  
  3043              jqLiteOn(e lement, MO USE_EVENT_ MAP[type],  function( event) {
  3044                var targ et = this,  related =  event.rel atedTarget ;
  3045                // For m ousenter/l eave call  the handle r if relat ed is outs ide the ta rget.
  3046                // NB: N o relatedT arget if t he mouse l eft/entere d the brow ser window
  3047                if (!rel ated || (r elated !==  target &&  !target.c ontains(re lated))) {
  3048                  handle (event, ty pe);
  3049                }
  3050              });
  3051  
  3052           }  else {
  3053              if (type ! == '$destr oy') {
  3054                addEvent ListenerFn (element,  type, hand le);
  3055              }
  3056           }
  3057           ev entFns = e vents[type ];
  3058         }
  3059         even tFns.push( fn);
  3060       }
  3061     },
  3062  
  3063     off: jqL iteOff,
  3064  
  3065     one: fun ction(elem ent, type,  fn) {
  3066       elemen t = jqLite (element);
  3067  
  3068       //add  the listen er twice s o that whe n it is ca lled
  3069       //you  can remove  the origi nal functi on and sti ll be
  3070         //able to  call eleme nt.off(ev,  fn) n DNS     y
  3071       elemen t.on(type,  function  onFn() {
  3072         elem ent.off(ty pe, fn);
  3073         elem ent.off(ty pe, onFn);
  3074       });
  3075       elemen t.on(type,  fn);
  3076     },
  3077  
  3078     replaceW ith: funct ion(elemen t, replace Node) {
  3079       var in dex, paren t = elemen t.parentNo de;
  3080       jqLite Dealoc(ele ment);
  3081       forEac h(new JQLi te(replace Node), fun ction(node ) {
  3082         if ( index) {
  3083           pa rent.inser tBefore(no de, index. nextSiblin g);
  3084         } el se {
  3085           pa rent.repla ceChild(no de, elemen t);
  3086         }
  3087         inde x = node;
  3088       });
  3089     },
  3090  
  3091     children : function (element)  {
  3092       var ch ildren = [ ];
  3093       forEac h(element. childNodes , function (element)  {
  3094         if ( element.no deType ===  NODE_TYPE _ELEMENT)
  3095           ch ildren.pus h(element) ;
  3096       });
  3097       return  children;
  3098     },
  3099  
  3100     contents : function (element)  {
  3101       return  element.c ontentDocu ment || el ement.chil dNodes ||  [];
  3102     },
  3103  
  3104     append:  function(e lement, no de) {
  3105       var no deType = e lement.nod eType;
  3106       if (no deType !==  NODE_TYPE _ELEMENT & & nodeType  !== NODE_ TYPE_DOCUM ENT_FRAGME NT) return ;
  3107  
  3108       node =  new JQLit e(node);
  3109  
  3110       for (v ar i = 0,  ii = node. length; i  < ii; i++)  {
  3111         var  child = no de[i];
  3112         elem ent.append Child(chil d);
  3113       }
  3114     },
  3115  
  3116     prepend:  function( element, n ode) {
  3117       if (el ement.node Type === N ODE_TYPE_E LEMENT) {
  3118         var  index = el ement.firs tChild;
  3119         forE ach(new JQ Lite(node) , function (child) {
  3120           el ement.inse rtBefore(c hild, inde x);
  3121         });
  3122       }
  3123     },
  3124  
  3125     wrap: fu nction(ele ment, wrap Node) {
  3126       wrapNo de = jqLit e(wrapNode ).eq(0).cl one()[0];
  3127       var pa rent = ele ment.paren tNode;
  3128       if (pa rent) {
  3129         pare nt.replace Child(wrap Node, elem ent);
  3130       }
  3131       wrapNo de.appendC hild(eleme nt);
  3132     },
  3133  
  3134     remove:  jqLiteRemo ve,
  3135  
  3136     detach:  function(e lement) {
  3137       jqLite Remove(ele ment, true );
  3138     },
  3139  
  3140     after: f unction(el ement, new Element) {
  3141       var in dex = elem ent, paren t = elemen t.parentNo de;
  3142       newEle ment = new  JQLite(ne wElement);
  3143  
  3144       for (v ar i = 0,  ii = newEl ement.leng th; i < ii ; i++) {
  3145         var  node = new Element[i] ;
  3146         pare nt.insertB efore(node , index.ne xtSibling) ;
  3147         inde x = node;
  3148       }
  3149     },
  3150  
  3151     addClass : jqLiteAd dClass,
  3152     removeCl ass: jqLit eRemoveCla ss,
  3153  
  3154     toggleCl ass: funct ion(elemen t, selecto r, conditi on) {
  3155       if (se lector) {
  3156         forE ach(select or.split('  '), funct ion(classN ame) {
  3157           va r classCon dition = c ondition;
  3158           if  (isUndefi ned(classC ondition))  {
  3159              classCondi tion = !jq LiteHasCla ss(element , classNam e);
  3160           }
  3161           (c lassCondit ion ? jqLi teAddClass  : jqLiteR emoveClass )(element,  className );
  3162         });
  3163       }
  3164     },
  3165  
  3166     parent:  function(e lement) {
  3167       var pa rent = ele ment.paren tNode;
  3168       return  parent &&  parent.no deType !==  NODE_TYPE _DOCUMENT_ FRAGMENT ?  parent :  null;
  3169     },
  3170  
  3171     next: fu nction(ele ment) {
  3172       return  element.n extElement Sibling;
  3173     },
  3174  
  3175     find: fu nction(ele ment, sele ctor) {
  3176       if (el ement.getE lementsByT agName) {
  3177         retu rn element .getElemen tsByTagNam e(selector );
  3178       } else  {
  3179         retu rn [];
  3180       }
  3181     },
  3182  
  3183     clone: j qLiteClone ,
  3184  
  3185     triggerH andler: fu nction(ele ment, even t, extraPa rameters)  {
  3186  
  3187       var du mmyEvent,  eventFnsCo py, handle rArgs;
  3188       var ev entName =  event.type  || event;
  3189       var ex pandoStore  = jqLiteE xpandoStor e(element) ;
  3190       var ev ents = exp andoStore  && expando Store.even ts;
  3191       var ev entFns = e vents && e vents[even tName];
  3192  
  3193       if (ev entFns) {
  3194         // C reate a du mmy event  to pass to  the handl ers
  3195         dumm yEvent = {
  3196           pr eventDefau lt: functi on() { thi s.defaultP revented =  true; },
  3197           is DefaultPre vented: fu nction() {  return th is.default Prevented  === true;  },
  3198           st opImmediat ePropagati on: functi on() { thi s.immediat ePropagati onStopped  = true; },
  3199           is ImmediateP ropagation Stopped: f unction()  { return t his.immedi atePropaga tionStoppe d === true ; },
  3200           st opPropagat ion: noop,
  3201           ty pe: eventN ame,
  3202           ta rget: elem ent
  3203         };
  3204  
  3205         // I f a custom  event was  provided  then exten d our dumm y event wi th it
  3206         if ( event.type ) {
  3207           du mmyEvent =  extend(du mmyEvent,  event);
  3208         }
  3209  
  3210         // C opy event  handlers i n case eve nt handler s array is  modified  during exe cution.
  3211         even tFnsCopy =  shallowCo py(eventFn s);
  3212         hand lerArgs =  extraParam eters ? [d ummyEvent] .concat(ex traParamet ers) : [du mmyEvent];
  3213  
  3214         forE ach(eventF nsCopy, fu nction(fn)  {
  3215           if  (!dummyEv ent.isImme diatePropa gationStop ped()) {
  3216              fn.apply(e lement, ha ndlerArgs) ;
  3217           }
  3218         });
  3219       }
  3220     }
  3221   }, functio n(fn, name ) {
  3222     /**
  3223      * chain ing functi ons
  3224      */
  3225     JQLite.p rototype[n ame] = fun ction(arg1 , arg2, ar g3) {
  3226       var va lue;
  3227  
  3228       for (v ar i = 0,  ii = this. length; i  < ii; i++)  {
  3229         if ( isUndefine d(value))  {
  3230           va lue = fn(t his[i], ar g1, arg2,  arg3);
  3231           if  (isDefine d(value))  {
  3232              // any fun ction whic h returns  a value ne eds to be  wrapped
  3233              value = jq Lite(value );
  3234           }
  3235         } el se {
  3236           jq LiteAddNod es(value,  fn(this[i] , arg1, ar g2, arg3)) ;
  3237         }
  3238       }
  3239       return  isDefined (value) ?  value : th is;
  3240     };
  3241  
  3242     // bind  legacy bin d/unbind t o on/off
  3243     JQLite.p rototype.b ind = JQLi te.prototy pe.on;
  3244     JQLite.p rototype.u nbind = JQ Lite.proto type.off;
  3245   });
  3246  
  3247   /**
  3248    * Compute s a hash o f an 'obj' .
  3249    * Hash of  a:
  3250    *  string  is string
  3251    *  number  is number  as string
  3252    *  object  is either  result of  calling $ $hashKey f unction on  the objec t or uniqu ely genera ted id,
  3253    *          that is a lso assign ed to the  $$hashKey  property o f the obje ct.
  3254    *
  3255    * @param  obj
  3256    * @return s {string}  hash stri ng such th at the sam e input wi ll have th e same has h string.
  3257    *          The resul ting strin g key is i n 'type:ha shKey' for mat.
  3258    */
  3259   function h ashKey(obj , nextUidF n) {
  3260     var key  = obj && o bj.$$hashK ey;
  3261  
  3262     if (key)  {
  3263       if (ty peof key = == 'functi on') {
  3264         key  = obj.$$ha shKey();
  3265       }
  3266       return  key;
  3267     }
  3268  
  3269     var objT ype = type of obj;
  3270     if (objT ype == 'fu nction' ||  (objType  == 'object ' && obj ! == null))  {
  3271       key =  obj.$$hash Key = objT ype + ':'  + (nextUid Fn || next Uid)();
  3272     } else {
  3273       key =  objType +  ':' + obj;
  3274     }
  3275  
  3276     return k ey;
  3277   }
  3278  
  3279   /**
  3280    * HashMap  which can  use objec ts as keys
  3281    */
  3282   function H ashMap(arr ay, isolat edUid) {
  3283     if (isol atedUid) {
  3284       var ui d = 0;
  3285       this.n extUid = f unction()  {
  3286         retu rn ++uid;
  3287       };
  3288     }
  3289     forEach( array, thi s.put, thi s);
  3290   }
  3291   HashMap.pr ototype =  {
  3292     /**
  3293      * Store  key value  pair
  3294      * @para m key key  to store c an be any  type
  3295      * @para m value va lue to sto re can be  any type
  3296      */
  3297     put: fun ction(key,  value) {
  3298       this[h ashKey(key , this.nex tUid)] = v alue;
  3299     },
  3300  
  3301     /**
  3302      * @para m key
  3303      * @retu rns {Objec t} the val ue for the  key
  3304      */
  3305     get: fun ction(key)  {
  3306       return  this[hash Key(key, t his.nextUi d)];
  3307     },
  3308  
  3309     /**
  3310      * Remov e the key/ value pair
  3311      * @para m key
  3312      */
  3313     remove:  function(k ey) {
  3314       var va lue = this [key = has hKey(key,  this.nextU id)];
  3315       delete  this[key] ;
  3316       return  value;
  3317     }
  3318   };
  3319  
  3320   /**
  3321    * @ngdoc  function
  3322    * @module  ng
  3323    * @name a ngular.inj ector
  3324    * @kind f unction
  3325    *
  3326    * @descri ption
  3327    * Creates  an inject or object  that can b e used for  retrievin g services  as well a s for
  3328    * depende ncy inject ion (see { @link guid e/di depen dency inje ction}).
  3329    *
  3330    * @param  {Array.<st ring|Funct ion>} modu les A list  of module  functions  or their  aliases. S ee
  3331    *     {@l ink angula r.module}.  The `ng`  module mus t be expli citly adde d.
  3332    * @param  {boolean=}  [strictDi =false] Wh ether the  injector s hould be i n strict m ode, which
  3333    *     dis allows arg ument name  annotatio n inferenc e.
  3334    * @return s {injecto r} Injecto r object.  See {@link  auto.$inj ector $inj ector}.
  3335    *
  3336    * @exampl e
  3337    * Typical  usage
  3338    * ```js
  3339    *   // cr eate an in jector
  3340    *   var $ injector =  angular.i njector([' ng']);
  3341    *
  3342    *   // us e the inje ctor to ki ck off you r applicat ion
  3343    *   // us e the type  inference  to auto i nject argu ments, or  use implic it injecti on
  3344    *   $inje ctor.invok e(function ($rootScop e, $compil e, $docume nt) {
  3345    *     $co mpile($doc ument)($ro otScope);
  3346    *     $ro otScope.$d igest();
  3347    *   });
  3348    * ```
  3349    *
  3350    * Sometim es you wan t to get a ccess to t he injecto r of a cur rently run ning Angul ar app
  3351    * from ou tside Angu lar. Perha ps, you wa nt to inje ct and com pile some  markup aft er the
  3352    * applica tion has b een bootst rapped. Yo u can do t his using  the extra  `injector( )` added
  3353    * to JQue ry/jqLite  elements.  See {@link  angular.e lement}.
  3354    *
  3355    * *This i s fairly r are but co uld be the  case if a  third par ty library  is inject ing the
  3356    * markup. *
  3357    *
  3358    * In the  following  example a  new block  of HTML co ntaining a  `ng-contr oller`
  3359    * directi ve is adde d to the e nd of the  document b ody by JQu ery. We th en compile  and link
  3360    * it into  the curre nt Angular JS scope.
  3361    *
  3362    * ```js
  3363    * var $di v = $('<di v ng-contr oller="MyC trl">{{con tent.label }}</div>') ;
  3364    * $(docum ent.body). append($di v);
  3365    *
  3366    * angular .element(d ocument).i njector(). invoke(fun ction($com pile) {
  3367    *   var s cope = ang ular.eleme nt($div).s cope();
  3368    *   $comp ile($div)( scope);
  3369    * });
  3370    * ```
  3371    */
  3372  
  3373  
  3374   /**
  3375    * @ngdoc  module
  3376    * @name a uto
  3377    * @descri ption
  3378    *
  3379    * Implici t module w hich gets  automatica lly added  to each {@ link auto. $injector  $injector} .
  3380    */
  3381  
  3382   var FN_ARG S = /^func tion\s*[^\ (]*\(\s*([ ^\)]*)\)/m ;
  3383   var FN_ARG _SPLIT = / ,/;
  3384   var FN_ARG  = /^\s*(_ ?)(\S+?)\1 \s*$/;
  3385   var STRIP_ COMMENTS =  /((\/\/.* $)|(\/\*[\ s\S]*?\*\/ ))/mg;
  3386   var $injec torMinErr  = minErr(' $injector' );
  3387  
  3388   function a nonFn(fn)  {
  3389     // For a nonymous f unctions,  showing at  the very  least the  function s ignature c an help in
  3390     // debug ging.
  3391     var fnTe xt = fn.to String().r eplace(STR IP_COMMENT S, ''),
  3392         args  = fnText. match(FN_A RGS);
  3393     if (args ) {
  3394       return  'function (' + (args [1] || '') .replace(/ [\s\r\n]+/ , ' ') + ' )';
  3395     }
  3396     return ' fn';
  3397   }
  3398  
  3399   function a nnotate(fn , strictDi , name) {
  3400     var $inj ect,
  3401         fnTe xt,
  3402         argD ecl,
  3403         last ;
  3404  
  3405     if (type of fn ===  'function' ) {
  3406       if (!( $inject =  fn.$inject )) {
  3407         $inj ect = [];
  3408         if ( fn.length)  {
  3409           if  (strictDi ) {
  3410              if (!isStr ing(name)  || !name)  {
  3411                name = f n.name ||  anonFn(fn) ;
  3412              }
  3413              throw $inj ectorMinEr r('strictd i',
  3414                '{0} is  not using  explicit a nnotation  and cannot  be invoke d in stric t mode', n ame);
  3415           }
  3416           fn Text = fn. toString() .replace(S TRIP_COMME NTS, '');
  3417           ar gDecl = fn Text.match (FN_ARGS);
  3418           fo rEach(argD ecl[1].spl it(FN_ARG_ SPLIT), fu nction(arg ) {
  3419              arg.replac e(FN_ARG,  function(a ll, unders core, name ) {
  3420                $inject. push(name) ;
  3421              });
  3422           }) ;
  3423         }
  3424         fn.$ inject = $ inject;
  3425       }
  3426     } else i f (isArray (fn)) {
  3427       last =  fn.length  - 1;
  3428       assert ArgFn(fn[l ast], 'fn' );
  3429       $injec t = fn.sli ce(0, last );
  3430     } else {
  3431       assert ArgFn(fn,  'fn', true );
  3432     }
  3433     return $ inject;
  3434   }
  3435  
  3436   ////////// ////////// ////////// /////////
  3437  
  3438   /**
  3439    * @ngdoc  service
  3440    * @name $ injector
  3441    *
  3442    * @descri ption
  3443    *
  3444    * `$injec tor` is us ed to retr ieve objec t instance s as defin ed by
  3445    * {@link  auto.$prov ide provid er}, insta ntiate typ es, invoke  methods,
  3446    * and loa d modules.
  3447    *
  3448    * The fol lowing alw ays holds  true:
  3449    *
  3450    * ```js
  3451    *   var $ injector =  angular.i njector();
  3452    *   expec t($injecto r.get('$in jector')). toBe($inje ctor);
  3453    *   expec t($injecto r.invoke(f unction($i njector) {
  3454    *     ret urn $injec tor;
  3455    *   })).t oBe($injec tor);
  3456    * ```
  3457    *
  3458    * # Injec tion Funct ion Annota tion
  3459    *
  3460    * JavaScr ipt does n ot have an notations,  and annot ations are  needed fo r dependen cy injecti on. The
  3461    * followi ng are all  valid way s of annot ating func tion with  injection  arguments  and are eq uivalent.
  3462    *
  3463    * ```js
  3464    *   // in ferred (on ly works i f code not  minified/ obfuscated )
  3465    *   $inje ctor.invok e(function (serviceA) {});
  3466    *
  3467    *   // an notated
  3468    *   funct ion explic it(service A) {};
  3469    *   expli cit.$injec t = ['serv iceA'];
  3470    *   $inje ctor.invok e(explicit );
  3471    *
  3472    *   // in line
  3473    *   $inje ctor.invok e(['servic eA', funct ion(servic eA){}]);
  3474    * ```
  3475    *
  3476    * ## Infe rence
  3477    *
  3478    * In Java Script cal ling `toSt ring()` on  a functio n returns  the functi on definit ion. The d efinition
  3479    * can the n be parse d and the  function a rguments c an be extr acted. Thi s method o f discover ing
  3480    * annotat ions is di sallowed w hen the in jector is  in strict  mode.
  3481    * *NOTE:*  This does  not work  with minif ication, a nd obfusca tion tools  since the se tools c hange the
  3482    * argumen t names.
  3483    *
  3484    * ## `$in ject` Anno tation
  3485    * By addi ng an `$in ject` prop erty onto  a function  the injec tion param eters can  be specifi ed.
  3486    *
  3487    * ## Inli ne
  3488    * As an a rray of in jection na mes, where  the last  item in th e array is  the funct ion to cal l.
  3489    */
  3490  
  3491   /**
  3492    * @ngdoc  method
  3493    * @name $ injector#g et
  3494    *
  3495    * @descri ption
  3496    * Return  an instanc e of the s ervice.
  3497    *
  3498    * @param  {string} n ame The na me of the  instance t o retrieve .
  3499    * @return  {*} The i nstance.
  3500    */
  3501  
  3502   /**
  3503    * @ngdoc  method
  3504    * @name $ injector#i nvoke
  3505    *
  3506    * @descri ption
  3507    * Invoke  the method  and suppl y the meth od argumen ts from th e `$inject or`.
  3508    *
  3509    * @param  {!Function } fn The f unction to  invoke. F unction pa rameters a re injecte d accordin g to the
  3510    *   {@lin k guide/di  $inject A nnotation}  rules.
  3511    * @param  {Object=}  self The ` this` for  the invoke d method.
  3512    * @param  {Object=}  locals Opt ional obje ct. If pre set then a ny argumen t names ar e read fro m this
  3513    *                           obj ect first,  before th e `$inject or` is con sulted.
  3514    * @return s {*} the  value retu rned by th e invoked  `fn` funct ion.
  3515    */
  3516  
  3517   /**
  3518    * @ngdoc  method
  3519    * @name $ injector#h as
  3520    *
  3521    * @descri ption
  3522    * Allows  the user t o query if  the parti cular serv ice exists .
  3523    *
  3524    * @param  {string} n ame Name o f the serv ice to que ry.
  3525    * @return s {boolean } `true` i f injector  has given  service.
  3526    */
  3527  
  3528   /**
  3529    * @ngdoc  method
  3530    * @name $ injector#i nstantiate
  3531    * @descri ption
  3532    * Create  a new inst ance of JS  type. The  method ta kes a cons tructor fu nction, in vokes the  new
  3533    * operato r, and sup plies all  of the arg uments to  the constr uctor func tion as sp ecified by  the
  3534    * constru ctor annot ation.
  3535    *
  3536    * @param  {Function}  Type Anno tated cons tructor fu nction.
  3537    * @param  {Object=}  locals Opt ional obje ct. If pre set then a ny argumen t names ar e read fro m this
  3538    * object  first, bef ore the `$ injector`  is consult ed.
  3539    * @return s {Object}  new insta nce of `Ty pe`.
  3540    */
  3541  
  3542   /**
  3543    * @ngdoc  method
  3544    * @name $ injector#a nnotate
  3545    *
  3546    * @descri ption
  3547    * Returns  an array  of service  names whi ch the fun ction is r equesting  for inject ion. This  API is
  3548    * used by  the injec tor to det ermine whi ch service s need to  be injecte d into the  function  when the
  3549    * functio n is invok ed. There  are three  ways in wh ich the fu nction can  be annota ted with t he needed
  3550    * depende ncies.
  3551    *
  3552    * # Argum ent names
  3553    *
  3554    * The sim plest form  is to ext ract the d ependencie s from the  arguments  of the fu nction. Th is is done
  3555    * by conv erting the  function  into a str ing using  `toString( )` method  and extrac ting the a rgument
  3556    * names.
  3557    * ```js
  3558    *   // Gi ven
  3559    *   funct ion MyCont roller($sc ope, $rout e) {
  3560    *     //  ...
  3561    *   }
  3562    *
  3563    *   // Th en
  3564    *   expec t(injector .annotate( MyControll er)).toEqu al(['$scop e', '$rout e']);
  3565    * ```
  3566    *
  3567    * You can  disallow  this metho d by using  strict in jection mo de.
  3568    *
  3569    * This me thod does  not work w ith code m inificatio n / obfusc ation. For  this reas on the fol lowing
  3570    * annotat ion strate gies are s upported.
  3571    *
  3572    * # The ` $inject` p roperty
  3573    *
  3574    * If a fu nction has  an `$inje ct` proper ty and its  value is  an array o f strings,  then the  strings
  3575    * represe nt names o f services  to be inj ected into  the funct ion.
  3576    * ```js
  3577    *   // Gi ven
  3578    *   var M yControlle r = functi on(obfusca tedScope,  obfuscated Route) {
  3579    *     //  ...
  3580    *   }
  3581    *   // De fine funct ion depend encies
  3582    *   MyCon troller['$ inject'] =  ['$scope' , '$route' ];
  3583    *
  3584    *   // Th en
  3585    *   expec t(injector .annotate( MyControll er)).toEqu al(['$scop e', '$rout e']);
  3586    * ```
  3587    *
  3588    * # The a rray notat ion
  3589    *
  3590    * It is o ften desir able to in line Injec ted functi ons and th at's when  setting th e `$inject ` property
  3591    * is very  inconveni ent. In th ese situat ions using  the array  notation  to specify  the depen dencies in
  3592    * a way t hat surviv es minific ation is a  better ch oice:
  3593    *
  3594    * ```js
  3595    *   // We  wish to w rite this  (not minif ication /  obfuscatio n safe)
  3596    *   injec tor.invoke (function( $compile,  $rootScope ) {
  3597    *     //  ...
  3598    *   });
  3599    *
  3600    *   // We  are force d to write  break inl ining
  3601    *   var t mpFn = fun ction(obfu scatedComp ile, obfus catedRootS cope) {
  3602    *     //  ...
  3603    *   };
  3604    *   tmpFn .$inject =  ['$compil e', '$root Scope'];
  3605    *   injec tor.invoke (tmpFn);
  3606    *
  3607    *   // To  better su pport inli ne functio n the inli ne annotat ion is sup ported
  3608    *   injec tor.invoke (['$compil e', '$root Scope', fu nction(obf Compile, o bfRootScop e) {
  3609    *     //  ...
  3610    *   }]);
  3611    *
  3612    *   // Th erefore
  3613    *   expec t(injector .annotate(
  3614    *      [' $compile',  '$rootSco pe', funct ion(obfus_ $compile,  obfus_$roo tScope) {} ])
  3615    *    ).to Equal(['$c ompile', ' $rootScope ']);
  3616    * ```
  3617    *
  3618    * @param  {Function| Array.<str ing|Functi on>} fn Fu nction for  which dep endent ser vice names  need to
  3619    * be retr ieved as d escribed a bove.
  3620    *
  3621    * @param  {boolean=}  [strictDi =false] Di sallow arg ument name  annotatio n inferenc e.
  3622    *
  3623    * @return s {Array.< string>} T he names o f the serv ices which  the funct ion requir es.
  3624    */
  3625  
  3626  
  3627  
  3628  
  3629   /**
  3630    * @ngdoc  service
  3631    * @name $ provide
  3632    *
  3633    * @descri ption
  3634    *
  3635    * The {@l ink auto.$ provide $p rovide} se rvice has  a number o f methods  for regist ering comp onents
  3636    * with th e {@link a uto.$injec tor $injec tor}. Many  of these  functions  are also e xposed on
  3637    * {@link  angular.Mo dule}.
  3638    *
  3639    * An Angu lar **serv ice** is a  singleton  object cr eated by a  **service  factory** .  These * *service
  3640    * factori es** are f unctions w hich, in t urn, are c reated by  a **servic e provider **.
  3641    * The **s ervice pro viders** a re constru ctor funct ions. When  instantia ted they m ust contai n a
  3642    * propert y called ` $get`, whi ch holds t he **servi ce factory ** functio n.
  3643    *
  3644    * When yo u request  a service,  the {@lin k auto.$in jector $in jector} is  responsib le for fin ding the
  3645    * correct  **service  provider* *, instant iating it  and then c alling its  `$get` ** service fa ctory**
  3646    * functio n to get t he instanc e of the * *service** .
  3647    *
  3648    * Often s ervices ha ve no conf iguration  options an d there is  no need t o add meth ods to the  service
  3649    * provide r.  The pr ovider wil l be no mo re than a  constructo r function  with a `$ get` prope rty. For
  3650    * these c ases the { @link auto .$provide  $provide}  service ha s addition al helper  methods to  register
  3651    * service s without  specifying  a provide r.
  3652    *
  3653    * * {@lin k auto.$pr ovide#prov ider provi der(provid er)} - reg isters a * *service p rovider**  with the
  3654    *     {@l ink auto.$ injector $ injector}
  3655    * * {@lin k auto.$pr ovide#cons tant const ant(obj)}  - register s a value/ object tha t can be a ccessed by
  3656    *     pro viders and  services.
  3657    * * {@lin k auto.$pr ovide#valu e value(ob j)} - regi sters a va lue/object  that can  only be ac cessed by
  3658    *     ser vices, not  providers .
  3659    * * {@lin k auto.$pr ovide#fact ory factor y(fn)} - r egisters a  service * *factory f unction**,  `fn`,
  3660    *     tha t will be  wrapped in  a **servi ce provide r** object , whose `$ get` prope rty will c ontain the
  3661    *     giv en factory  function.
  3662    * * {@lin k auto.$pr ovide#serv ice servic e(class)}  - register s a **cons tructor fu nction**,  `class`
  3663    *     tha t will be  wrapped in  a **servi ce provide r** object , whose `$ get` prope rty will i nstantiate
  3664    *      a  new object  using the  given con structor f unction.
  3665    *
  3666    * See the  individua l methods  for more i nformation  and examp les.
  3667    */
  3668  
  3669   /**
  3670    * @ngdoc  method
  3671    * @name $ provide#pr ovider
  3672    * @descri ption
  3673    *
  3674    * Registe r a **prov ider funct ion** with  the {@lin k auto.$in jector $in jector}. P rovider fu nctions
  3675    * are con structor f unctions,  whose inst ances are  responsibl e for "pro viding" a  factory fo r a
  3676    * service .
  3677    *
  3678    * Service  provider  names star t with the  name of t he service  they prov ide follow ed by `Pro vider`.
  3679    * For exa mple, the  {@link ng. $log $log}  service h as a provi der called
  3680    * {@link  ng.$logPro vider $log Provider}.
  3681    *
  3682    * Service  provider  objects ca n have add itional me thods whic h allow co nfiguratio n of the p rovider
  3683    * and its  service.  Importantl y, you can  configure  what kind  of servic e is creat ed by the  `$get`
  3684    * method,  or how th at service  will act.  For examp le, the {@ link ng.$l ogProvider  $logProvi der} has a
  3685    * method  {@link ng. $logProvid er#debugEn abled debu gEnabled}
  3686    * which l ets you sp ecify whet her the {@ link ng.$l og $log} s ervice wil l log debu g messages  to the
  3687    * console  or not.
  3688    *
  3689    * @param  {string} n ame The na me of the  instance.  NOTE: the  provider w ill be ava ilable und er `name +
  3690                             'Provi der'` key.
  3691    * @param  {(Object|f unction()) } provider  If the pr ovider is:
  3692    *
  3693    *   - `Ob ject`: the n it shoul d have a ` $get` meth od. The `$ get` metho d will be  invoked us ing
  3694    *     {@l ink auto.$ injector#i nvoke $inj ector.invo ke()} when  an instan ce needs t o be creat ed.
  3695    *   - `Co nstructor` : a new in stance of  the provid er will be  created u sing
  3696    *     {@l ink auto.$ injector#i nstantiate  $injector .instantia te()}, the n treated  as `object `.
  3697    *
  3698    * @return s {Object}  registere d provider  instance
  3699  
  3700    * @exampl e
  3701    *
  3702    * The fol lowing exa mple shows  how to cr eate a sim ple event  tracking s ervice and  register  it using
  3703    * {@link  auto.$prov ide#provid er $provid e.provider ()}.
  3704    *
  3705    * ```js
  3706    *  // Def ine the ev entTracker  provider
  3707    *  functi on EventTr ackerProvi der() {
  3708    *    var  trackingUr l = '/trac k';
  3709    *
  3710    *    // A  provider  method for  configuri ng where t he tracked  events sh ould been  saved
  3711    *    this .setTracki ngUrl = fu nction(url ) {
  3712    *      tr ackingUrl  = url;
  3713    *    };
  3714    *
  3715    *    // T he service  factory f unction
  3716    *    this .$get = [' $http', fu nction($ht tp) {
  3717    *      va r trackedE vents = {} ;
  3718    *      re turn {
  3719    *         // Call th is to trac k an event
  3720    *         event: fun ction(even t) {
  3721    *           var coun t = tracke dEvents[ev ent] || 0;
  3722    *           count +=  1;
  3723    *           trackedE vents[even t] = count ;
  3724    *           return c ount;
  3725    *         },
  3726    *         // Call th is to save  the track ed events  to the tra ckingUrl
  3727    *         save: func tion() {
  3728    *           $http.po st(trackin gUrl, trac kedEvents) ;
  3729    *         }
  3730    *      };
  3731    *    }];
  3732    *  }
  3733    *
  3734    *  descri be('eventT racker', f unction()  {
  3735    *    var  postSpy;
  3736    *
  3737    *    befo reEach(mod ule(functi on($provid e) {
  3738    *      //  Register  the eventT racker pro vider
  3739    *      $p rovide.pro vider('eve ntTracker' , EventTra ckerProvid er);
  3740    *    }));
  3741    *
  3742    *    befo reEach(mod ule(functi on(eventTr ackerProvi der) {
  3743    *      //  Configure  eventTrac ker provid er
  3744    *      ev entTracker Provider.s etTracking Url('/cust om-track') ;
  3745    *    }));
  3746    *
  3747    *    it(' tracks eve nts', inje ct(functio n(eventTra cker) {
  3748    *      ex pect(event Tracker.ev ent('login ')).toEqua l(1);
  3749    *      ex pect(event Tracker.ev ent('login ')).toEqua l(2);
  3750    *    }));
  3751    *
  3752    *    it(' saves to t he trackin g url', in ject(funct ion(eventT racker, $h ttp) {
  3753    *      po stSpy = sp yOn($http,  'post');
  3754    *      ev entTracker .event('lo gin');
  3755    *      ev entTracker .save();
  3756    *      ex pect(postS py).toHave BeenCalled ();
  3757    *      ex pect(postS py.mostRec entCall.ar gs[0]).not .toEqual(' /track');
  3758    *      ex pect(postS py.mostRec entCall.ar gs[0]).toE qual('/cus tom-track' );
  3759    *      ex pect(postS py.mostRec entCall.ar gs[1]).toE qual({ 'lo gin': 1 }) ;
  3760    *    }));
  3761    *  });
  3762    * ```
  3763    */
  3764  
  3765   /**
  3766    * @ngdoc  method
  3767    * @name $ provide#fa ctory
  3768    * @descri ption
  3769    *
  3770    * Registe r a **serv ice factor y**, which  will be c alled to r eturn the  service in stance.
  3771    * This is  short for  registeri ng a servi ce where i ts provide r consists  of only a  `$get` pr operty,
  3772    * which i s the give n service  factory fu nction.
  3773    * You sho uld use {@ link auto. $provide#f actory $pr ovide.fact ory(getFn) } if you d o not need  to
  3774    * configu re your se rvice in a  provider.
  3775    *
  3776    * @param  {string} n ame The na me of the  instance.
  3777    * @param  {function( )} $getFn  The $getFn  for the i nstance cr eation. In ternally t his is a s hort hand
  3778    *                               for `$prov ide.provid er(name, { $get: $get Fn})`.
  3779    * @return s {Object}  registere d provider  instance
  3780    *
  3781    * @exampl e
  3782    * Here is  an exampl e of regis tering a s ervice
  3783    * ```js
  3784    *   $prov ide.factor y('ping',  ['$http',  function($ http) {
  3785    *     ret urn functi on ping()  {
  3786    *       r eturn $htt p.send('/p ing');
  3787    *     };
  3788    *   }]);
  3789    * ```
  3790    * You wou ld then in ject and u se this se rvice like  this:
  3791    * ```js
  3792    *   someM odule.cont roller('Ct rl', ['pin g', functi on(ping) {
  3793    *     pin g();
  3794    *   }]);
  3795    * ```
  3796    */
  3797  
  3798  
  3799   /**
  3800    * @ngdoc  method
  3801    * @name $ provide#se rvice
  3802    * @descri ption
  3803    *
  3804    * Registe r a **serv ice constr uctor**, w hich will  be invoked  with `new ` to creat e the serv ice
  3805    * instanc e.
  3806    * This is  short for  registeri ng a servi ce where i ts provide r's `$get`  property  is the ser vice
  3807    * constru ctor funct ion that w ill be use d to insta ntiate the  service i nstance.
  3808    *
  3809    * You sho uld use {@ link auto. $provide#s ervice $pr ovide.serv ice(class) } if you d efine your  service
  3810    * as a ty pe/class.
  3811    *
  3812    * @param  {string} n ame The na me of the  instance.
  3813    * @param  {Function}  construct or A class  (construc tor functi on) that w ill be ins tantiated.
  3814    * @return s {Object}  registere d provider  instance
  3815    *
  3816    * @exampl e
  3817    * Here is  an exampl e of regis tering a s ervice usi ng
  3818    * {@link  auto.$prov ide#servic e $provide .service(c lass)}.
  3819    * ```js
  3820    *   var P ing = func tion($http ) {
  3821    *     thi s.$http =  $http;
  3822    *   };
  3823    *
  3824    *   Ping. $inject =  ['$http'];
  3825    *
  3826    *   Ping. prototype. send = fun ction() {
  3827    *     ret urn this.$ http.get(' /ping');
  3828    *   };
  3829    *   $prov ide.servic e('ping',  Ping);
  3830    * ```
  3831    * You wou ld then in ject and u se this se rvice like  this:
  3832    * ```js
  3833    *   someM odule.cont roller('Ct rl', ['pin g', functi on(ping) {
  3834    *     pin g.send();
  3835    *   }]);
  3836    * ```
  3837    */
  3838  
  3839  
  3840   /**
  3841    * @ngdoc  method
  3842    * @name $ provide#va lue
  3843    * @descri ption
  3844    *
  3845    * Registe r a **valu e service* * with the  {@link au to.$inject or $inject or}, such  as a strin g, a
  3846    * number,  an array,  an object  or a func tion.  Thi s is short  for regis tering a s ervice whe re its
  3847    * provide r's `$get`  property  is a facto ry functio n that tak es no argu ments and  returns th e **value
  3848    * service **.
  3849    *
  3850    * Value s ervices ar e similar  to constan t services , except t hat they c annot be i njected in to a
  3851    * module  configurat ion functi on (see {@ link angul ar.Module# config}) b ut they ca n be overr idden by
  3852    * an Angu lar
  3853    * {@link  auto.$prov ide#decora tor decora tor}.
  3854    *
  3855    * @param  {string} n ame The na me of the  instance.
  3856    * @param  {*} value  The value.
  3857    * @return s {Object}  registere d provider  instance
  3858    *
  3859    * @exampl e
  3860    * Here ar e some exa mples of c reating va lue servic es.
  3861    * ```js
  3862    *   $prov ide.value( 'ADMIN_USE R', 'admin ');
  3863    *
  3864    *   $prov ide.value( 'RoleLooku p', { admi n: 0, writ er: 1, rea der: 2 });
  3865    *
  3866    *   $prov ide.value( 'halfOf',  function(v alue) {
  3867    *     ret urn value  / 2;
  3868    *   });
  3869    * ```
  3870    */
  3871  
  3872  
  3873   /**
  3874    * @ngdoc  method
  3875    * @name $ provide#co nstant
  3876    * @descri ption
  3877    *
  3878    * Registe r a **cons tant servi ce**, such  as a stri ng, a numb er, an arr ay, an obj ect or a f unction,
  3879    * with th e {@link a uto.$injec tor $injec tor}. Unli ke {@link  auto.$prov ide#value  value} it  can be
  3880    * injecte d into a m odule conf iguration  function ( see {@link  angular.M odule#conf ig}) and i t cannot
  3881    * be over ridden by  an Angular  {@link au to.$provid e#decorato r decorato r}.
  3882    *
  3883    * @param  {string} n ame The na me of the  constant.
  3884    * @param  {*} value  The consta nt value.
  3885    * @return s {Object}  registere d instance
  3886    *
  3887    * @exampl e
  3888    * Here a  some examp les of cre ating cons tants:
  3889    * ```js
  3890    *   $prov ide.consta nt('SHARD_ HEIGHT', 3 06);
  3891    *
  3892    *   $prov ide.consta nt('MY_COL OURS', ['r ed', 'blue ', 'grey'] );
  3893    *
  3894    *   $prov ide.consta nt('double ', functio n(value) {
  3895    *     ret urn value  * 2;
  3896    *   });
  3897    * ```
  3898    */
  3899  
  3900  
  3901   /**
  3902    * @ngdoc  method
  3903    * @name $ provide#de corator
  3904    * @descri ption
  3905    *
  3906    * Registe r a **serv ice decora tor** with  the {@lin k auto.$in jector $in jector}. A  service d ecorator
  3907    * interce pts the cr eation of  a service,  allowing  it to over ride or mo dify the b ehaviour o f the
  3908    * service . The obje ct returne d by the d ecorator m ay be the  original s ervice, or  a new ser vice
  3909    * object  which repl aces or wr aps and de legates to  the origi nal servic e.
  3910    *
  3911    * @param  {string} n ame The na me of the  service to  decorate.
  3912    * @param  {function( )} decorat or This fu nction wil l be invok ed when th e service  needs to b e
  3913    *    inst antiated a nd should  return the  decorated  service i nstance. T he functio n is calle d using
  3914    *    the  {@link aut o.$injecto r#invoke i njector.in voke} meth od and is  therefore  fully inje ctable.
  3915    *    Loca l injectio n argument s:
  3916    *
  3917    *    * `$ delegate`  - The orig inal servi ce instanc e, which c an be monk ey patched , configur ed,
  3918    *      de corated or  delegated  to.
  3919    *
  3920    * @exampl e
  3921    * Here we  decorate  the {@link  ng.$log $ log} servi ce to conv ert warnin gs to erro rs by inte rcepting
  3922    * calls t o {@link n g.$log#err or $log.wa rn()}.
  3923    * ```js
  3924    *   $prov ide.decora tor('$log' , ['$deleg ate', func tion($dele gate) {
  3925    *     $de legate.war n = $deleg ate.error;
  3926    *     ret urn $deleg ate;
  3927    *   }]);
  3928    * ```
  3929    */
  3930  
  3931  
  3932   function c reateInjec tor(module sToLoad, s trictDi) {
  3933     strictDi  = (strict Di === tru e);
  3934     var INST ANTIATING  = {},
  3935         prov iderSuffix  = 'Provid er',
  3936         path  = [],
  3937         load edModules  = new Hash Map([], tr ue),
  3938         prov iderCache  = {
  3939           $p rovide: {
  3940                provider : supportO bject(prov ider),
  3941                factory:  supportOb ject(facto ry),
  3942                service:  supportOb ject(servi ce),
  3943                value: s upportObje ct(value),
  3944                constant : supportO bject(cons tant),
  3945                decorato r: decorat or
  3946              }
  3947         },
  3948         prov iderInject or = (prov iderCache. $injector  =
  3949              createInte rnalInject or(provide rCache, fu nction() {
  3950                throw $i njectorMin Err('unpr' , "Unknown  provider:  {0}", pat h.join(' < - '));
  3951              })),
  3952         inst anceCache  = {},
  3953         inst anceInject or = (inst anceCache. $injector  =
  3954              createInte rnalInject or(instanc eCache, fu nction(ser vicename)  {
  3955                var prov ider = pro viderInjec tor.get(se rvicename  + provider Suffix);
  3956                return i nstanceInj ector.invo ke(provide r.$get, pr ovider, un defined, s ervicename );
  3957              }));
  3958  
  3959  
  3960     forEach( loadModule s(modulesT oLoad), fu nction(fn)  { instanc eInjector. invoke(fn  || noop);  });
  3961  
  3962     return i nstanceInj ector;
  3963  
  3964     //////// ////////// ////////// ////////
  3965     // $prov ider
  3966     //////// ////////// ////////// ////////
  3967  
  3968     function  supportOb ject(deleg ate) {
  3969       return  function( key, value ) {
  3970         if ( isObject(k ey)) {
  3971           fo rEach(key,  reversePa rams(deleg ate));
  3972         } el se {
  3973           re turn deleg ate(key, v alue);
  3974         }
  3975       };
  3976     }
  3977  
  3978     function  provider( name, prov ider_) {
  3979       assert NotHasOwnP roperty(na me, 'servi ce');
  3980       if (is Function(p rovider_)  || isArray (provider_ )) {
  3981         prov ider_ = pr oviderInje ctor.insta ntiate(pro vider_);
  3982       }
  3983       if (!p rovider_.$ get) {
  3984         thro w $injecto rMinErr('p get', "Pro vider '{0} ' must def ine $get f actory met hod.", nam e);
  3985       }
  3986       return  providerC ache[name  + provider Suffix] =  provider_;
  3987     }
  3988  
  3989     function  enforceRe turnValue( name, fact ory) {
  3990       return  function  enforcedRe turnValue( ) {
  3991         var  result = i nstanceInj ector.invo ke(factory , this, un defined, n ame);
  3992         if ( isUndefine d(result))  {
  3993           th row $injec torMinErr( 'undef', " Provider ' {0}' must  return a v alue from  $get facto ry method. ", name);
  3994         }
  3995         retu rn result;
  3996       };
  3997     }
  3998  
  3999     function  factory(n ame, facto ryFn, enfo rce) {
  4000       return  provider( name, {
  4001         $get : enforce  !== false  ? enforceR eturnValue (name, fac toryFn) :  factoryFn
  4002       });
  4003     }
  4004  
  4005     function  service(n ame, const ructor) {
  4006       return  factory(n ame, ['$in jector', f unction($i njector) {
  4007         retu rn $inject or.instant iate(const ructor);
  4008       }]);
  4009     }
  4010  
  4011     function  value(nam e, val) {  return fac tory(name,  valueFn(v al), false ); }
  4012  
  4013     function  constant( name, valu e) {
  4014       assert NotHasOwnP roperty(na me, 'const ant');
  4015       provid erCache[na me] = valu e;
  4016       instan ceCache[na me] = valu e;
  4017     }
  4018  
  4019     function  decorator (serviceNa me, decorF n) {
  4020       var or igProvider  = provide rInjector. get(servic eName + pr oviderSuff ix),
  4021           or ig$get = o rigProvide r.$get;
  4022  
  4023       origPr ovider.$ge t = functi on() {
  4024         var  origInstan ce = insta nceInjecto r.invoke(o rig$get, o rigProvide r);
  4025         retu rn instanc eInjector. invoke(dec orFn, null , {$delega te: origIn stance});
  4026       };
  4027     }
  4028  
  4029     //////// ////////// ////////// ////////
  4030     // Modul e Loading
  4031     //////// ////////// ////////// ////////
  4032     function  loadModul es(modules ToLoad) {
  4033       var ru nBlocks =  [], module Fn;
  4034       forEac h(modulesT oLoad, fun ction(modu le) {
  4035         if ( loadedModu les.get(mo dule)) ret urn;
  4036         load edModules. put(module , true);
  4037  
  4038         func tion runIn vokeQueue( queue) {
  4039           va r i, ii;
  4040           fo r (i = 0,  ii = queue .length; i  < ii; i++ ) {
  4041              var invoke Args = que ue[i],
  4042                  provid er = provi derInjecto r.get(invo keArgs[0]) ;
  4043  
  4044              provider[i nvokeArgs[ 1]].apply( provider,  invokeArgs [2]);
  4045           }
  4046         }
  4047  
  4048         try  {
  4049           if  (isString (module))  {
  4050              moduleFn =  angularMo dule(modul e);
  4051              runBlocks  = runBlock s.concat(l oadModules (moduleFn. requires)) .concat(mo duleFn._ru nBlocks);
  4052              runInvokeQ ueue(modul eFn._invok eQueue);
  4053              runInvokeQ ueue(modul eFn._confi gBlocks);
  4054           }  else if (i sFunction( module)) {
  4055                runBlock s.push(pro viderInjec tor.invoke (module));
  4056           }  else if (i sArray(mod ule)) {
  4057                runBlock s.push(pro viderInjec tor.invoke (module));
  4058           }  else {
  4059              assertArgF n(module,  'module');
  4060           }
  4061         } ca tch (e) {
  4062           if  (isArray( module)) {
  4063              module = m odule[modu le.length  - 1];
  4064           }
  4065           if  (e.messag e && e.sta ck && e.st ack.indexO f(e.messag e) == -1)  {
  4066              // Safari  & FF's sta ck traces  don't cont ain error. message co ntent
  4067              // unlike  those of C hrome and  IE
  4068              // So if s tack doesn 't contain  message,  we create  a new stri ng that co ntains bot h.
  4069              // Since e rror.stack  is read-o nly in Saf ari, I'm o verriding  e and not  e.stack he re.
  4070              /* jshint  -W022 */
  4071              e = e.mess age + '\n'  + e.stack ;
  4072           }
  4073           th row $injec torMinErr( 'modulerr' , "Failed  to instant iate modul e {0} due  to:\n{1}",
  4074                      mo dule, e.st ack || e.m essage ||  e);
  4075         }
  4076       });
  4077       return  runBlocks ;
  4078     }
  4079  
  4080     //////// ////////// ////////// ////////
  4081     // inter nal Inject or
  4082     //////// ////////// ////////// ////////
  4083  
  4084     function  createInt ernalInjec tor(cache,  factory)  {
  4085  
  4086       functi on getServ ice(servic eName) {
  4087         if ( cache.hasO wnProperty (serviceNa me)) {
  4088           if  (cache[se rviceName]  === INSTA NTIATING)  {
  4089              throw $inj ectorMinEr r('cdep',  'Circular  dependency  found: {0 }',
  4090                         serviceNam e + ' <- '  + path.jo in(' <- ') );
  4091           }
  4092           re turn cache [serviceNa me];
  4093         } el se {
  4094           tr y {
  4095              path.unshi ft(service Name);
  4096              cache[serv iceName] =  INSTANTIA TING;
  4097              return cac he[service Name] = fa ctory(serv iceName);
  4098           }  catch (err ) {
  4099              if (cache[ serviceNam e] === INS TANTIATING ) {
  4100                delete c ache[servi ceName];
  4101              }
  4102              throw err;
  4103           }  finally {
  4104              path.shift ();
  4105           }
  4106         }
  4107       }
  4108  
  4109       functi on invoke( fn, self,  locals, se rviceName)  {
  4110         if ( typeof loc als === 's tring') {
  4111           se rviceName  = locals;
  4112           lo cals = nul l;
  4113         }
  4114  
  4115         var  args = [],
  4116              $inject =  annotate(f n, strictD i, service Name),
  4117              length, i,
  4118              key;
  4119  
  4120         for  (i = 0, le ngth = $in ject.lengt h; i < len gth; i++)  {
  4121           ke y = $injec t[i];
  4122           if  (typeof k ey !== 'st ring') {
  4123              throw $inj ectorMinEr r('itkn',
  4124                      'I ncorrect i njection t oken! Expe cted servi ce name as  string, g ot {0}', k ey);
  4125           }
  4126           ar gs.push(
  4127              locals &&  locals.has OwnPropert y(key)
  4128              ? locals[k ey]
  4129              : getServi ce(key)
  4130           );
  4131         }
  4132         if ( isArray(fn )) {
  4133           fn  = fn[leng th];
  4134         }
  4135  
  4136         // h ttp://jspe rf.com/ang ularjs-inv oke-apply- vs-switch
  4137         // # 5388
  4138         retu rn fn.appl y(self, ar gs);
  4139       }
  4140  
  4141       functi on instant iate(Type,  locals, s erviceName ) {
  4142         // C heck if Ty pe is anno tated and  use just t he given f unction at  n-1 as pa rameter
  4143         // e .g. someMo dule.facto ry('greete r', ['$win dow', func tion(renam ed$window)  {}]);
  4144         // O bject crea tion: http ://jsperf. com/create -construct or/2
  4145         var  instance =  Object.cr eate((isAr ray(Type)  ? Type[Typ e.length -  1] : Type ).prototyp e);
  4146         var  returnedVa lue = invo ke(Type, i nstance, l ocals, ser viceName);
  4147  
  4148         retu rn isObjec t(returned Value) ||  isFunction (returnedV alue) ? re turnedValu e : instan ce;
  4149       }
  4150  
  4151       return  {
  4152         invo ke: invoke ,
  4153         inst antiate: i nstantiate ,
  4154         get:  getServic e,
  4155         anno tate: anno tate,
  4156         has:  function( name) {
  4157           re turn provi derCache.h asOwnPrope rty(name +  providerS uffix) ||  cache.hasO wnProperty (name);
  4158         }
  4159       };
  4160     }
  4161   }
  4162  
  4163   createInje ctor.$$ann otate = an notate;
  4164  
  4165   /**
  4166    * @ngdoc  provider
  4167    * @name $ anchorScro llProvider
  4168    *
  4169    * @descri ption
  4170    * Use `$a nchorScrol lProvider`  to disabl e automati c scrollin g whenever
  4171    * {@link  ng.$locati on#hash $l ocation.ha sh()} chan ges.
  4172    */
  4173   function $ AnchorScro llProvider () {
  4174  
  4175     var auto ScrollingE nabled = t rue;
  4176  
  4177     /**
  4178      * @ngdo c method
  4179      * @name  $anchorSc rollProvid er#disable AutoScroll ing
  4180      *
  4181      * @desc ription
  4182      * By de fault, {@l ink ng.$an chorScroll  $anchorSc roll()} wi ll automat ically det ect change s to
  4183      * {@lin k ng.$loca tion#hash  $location. hash()} an d scroll t o the elem ent matchi ng the new  hash.<br  />
  4184      * Use t his method  to disabl e automati c scrollin g.
  4185      *
  4186      * If au tomatic sc rolling is  disabled,  one must  explicitly  call
  4187      * {@lin k ng.$anch orScroll $ anchorScro ll()} in o rder to sc roll to th e element  related to  the
  4188      * curre nt hash.
  4189      */
  4190     this.dis ableAutoSc rolling =  function()  {
  4191       autoSc rollingEna bled = fal se;
  4192     };
  4193  
  4194     /**
  4195      * @ngdo c service
  4196      * @name  $anchorSc roll
  4197      * @kind  function
  4198      * @requ ires $wind ow
  4199      * @requ ires $loca tion
  4200      * @requ ires $root Scope
  4201      *
  4202      * @desc ription
  4203      * When  called, it  checks th e current  value of { @link ng.$ location#h ash $locat ion.hash() } and
  4204      * scrol ls to the  related el ement, acc ording to  the rules  specified  in the
  4205      * [Html 5 spec](ht tp://dev.w 3.org/html 5/spec/Ove rview.html #the-indic ated-part- of-the-doc ument).
  4206      *
  4207      * It al so watches  the {@lin k ng.$loca tion#hash  $location. hash()} an d automati cally scro lls to
  4208      * match  any ancho r whenever  it change s. This ca n be disab led by cal ling
  4209      * {@lin k ng.$anch orScrollPr ovider#dis ableAutoSc rolling $a nchorScrol lProvider. disableAut oScrolling ()}.
  4210      *
  4211      * Addit ionally, y ou can use  its {@lin k ng.$anch orScroll#y Offset yOf fset} prop erty to sp ecify a
  4212      * verti cal scroll -offset (e ither fixe d or dynam ic).
  4213      *
  4214      * @prop erty {(num ber|functi on|jqLite) } yOffset
  4215      * If se t, specifi es a verti cal scroll -offset. T his is oft en useful  when there  are fixed
  4216      * posit ioned elem ents at th e top of t he page, s uch as nav bars, head ers etc.
  4217      *
  4218      * `yOff set` can b e specifie d in vario us ways:
  4219      * - **n umber**: A  fixed num ber of pix els to be  used as of fset.<br / ><br />
  4220      * - **f unction**:  A getter  function c alled ever ytime `$an chorScroll ()` is exe cuted. Mus t return
  4221      *   a n umber repr esenting t he offset  (in pixels ).<br /><b r />
  4222      * - **j qLite**: A  jqLite/jQ uery eleme nt to be u sed for sp ecifying t he offset.  The dista nce from
  4223      *   the  top of th e page to  the elemen t's bottom  will be u sed as off set.<br />
  4224      *   **N ote**: The  element w ill be tak en into ac count only  as long a s its `pos ition` is  set to
  4225      *   `fi xed`. This  option is  useful, w hen dealin g with res ponsive na vbars/head ers that a djust
  4226      *   the ir height  and/or pos itioning a ccording t o the view port's siz e.
  4227      *
  4228      * <br / >
  4229      * <div  class="ale rt alert-w arning">
  4230      * In or der for `y Offset` to  work prop erly, scro lling shou ld take pl ace on the  document' s root and
  4231      * not s ome child  element.
  4232      * </div >
  4233      *
  4234      * @exam ple
  4235        <exam ple module ="anchorSc rollExampl e">
  4236          <fi le name="i ndex.html" >
  4237            < div id="sc rollArea"  ng-control ler="Scrol lControlle r">
  4238               <a ng-cli ck="gotoBo ttom()">Go  to bottom </a>
  4239               <a id="bo ttom"></a>  You're at  the botto m!
  4240            < /div>
  4241          </f ile>
  4242          <fi le name="s cript.js">
  4243            a ngular.mod ule('ancho rScrollExa mple', [])
  4244               .controll er('Scroll Controller ', ['$scop e', '$loca tion', '$a nchorScrol l',
  4245                 functio n ($scope,  $location , $anchorS croll) {
  4246                   $scop e.gotoBott om = funct ion() {
  4247                     //  set the lo cation.has h to the i d of
  4248                     //  the elemen t you wish  to scroll  to.
  4249                     $lo cation.has h('bottom' );
  4250  
  4251                     //  call $anch orScroll()
  4252                     $an chorScroll ();
  4253                   };
  4254                 }]);
  4255          </f ile>
  4256          <fi le name="s tyle.css">
  4257            # scrollArea  {
  4258               height: 2 80px;
  4259               overflow:  auto;
  4260            }
  4261  
  4262            # bottom {
  4263               display:  block;
  4264               margin-to p: 2000px;
  4265            }
  4266          </f ile>
  4267        </exa mple>
  4268      *
  4269      * <hr / >
  4270      * The e xample bel ow illustr ates the u se of a ve rtical scr oll-offset  (specifie d as a fix ed value).
  4271      * See { @link ng.$ anchorScro ll#yOffset  $anchorSc roll.yOffs et} for mo re details .
  4272      *
  4273      * @exam ple
  4274        <exam ple module ="anchorSc rollOffset Example">
  4275          <fi le name="i ndex.html" >
  4276            < div class= "fixed-hea der" ng-co ntroller=" headerCtrl ">
  4277               <a href=" " ng-click ="gotoAnch or(x)" ng- repeat="x  in [1,2,3, 4,5]">
  4278                 Go to a nchor {{x} }
  4279               </a>
  4280            < /div>
  4281            < div id="an chor{{x}}"  class="an chor" ng-r epeat="x i n [1,2,3,4 ,5]">
  4282               Anchor {{ x}} of 5
  4283            < /div>
  4284          </f ile>
  4285          <fi le name="s cript.js">
  4286            a ngular.mod ule('ancho rScrollOff setExample ', [])
  4287               .run(['$a nchorScrol l', functi on($anchor Scroll) {
  4288                 $anchor Scroll.yOf fset = 50;    // alwa ys scroll  by 50 extr a pixels
  4289               }])
  4290               .controll er('header Ctrl', ['$ anchorScro ll', '$loc ation', '$ scope',
  4291                 functio n ($anchor Scroll, $l ocation, $ scope) {
  4292                   $scop e.gotoAnch or = funct ion(x) {
  4293                     var  newHash =  'anchor'  + x;
  4294                     if  ($location .hash() != = newHash)  {
  4295                       / / set the  $location. hash to `n ewHash` an d
  4296                       / / $anchorS croll will  automatic ally scrol l to it
  4297                       $ location.h ash('ancho r' + x);
  4298                     } e lse {
  4299                       / / call $an chorScroll () explici tly,
  4300                       / / since $l ocation.ha sh hasn't  changed
  4301                       $ anchorScro ll();
  4302                     }
  4303                   };
  4304                 }
  4305               ]);
  4306          </f ile>
  4307          <fi le name="s tyle.css">
  4308            b ody {
  4309               padding-t op: 50px;
  4310            }
  4311  
  4312            . anchor {
  4313               border: 2 px dashed  DarkOrchid ;
  4314               padding:  10px 10px  200px 10px ;
  4315            }
  4316  
  4317            . fixed-head er {
  4318               backgroun d-color: r gba(0, 0,  0, 0.2);
  4319               height: 5 0px;
  4320               position:  fixed;
  4321               top: 0; l eft: 0; ri ght: 0;
  4322            }
  4323  
  4324            . fixed-head er > a {
  4325               display:  inline-blo ck;
  4326               margin: 5 px 15px;
  4327            }
  4328          </f ile>
  4329        </exa mple>
  4330      */
  4331     this.$ge t = ['$win dow', '$lo cation', ' $rootScope ', functio n($window,  $location , $rootSco pe) {
  4332       var do cument = $ window.doc ument;
  4333  
  4334       // Hel per functi on to get  first anch or from a  NodeList
  4335       // (us ing `Array #some()` i nstead of  `angular#f orEach()`  since it's  more perf ormant
  4336       //  an d working  in all sup ported bro wsers.)
  4337       functi on getFirs tAnchor(li st) {
  4338         var  result = n ull;
  4339         Arra y.prototyp e.some.cal l(list, fu nction(ele ment) {
  4340           if  (nodeName _(element)  === 'a')  {
  4341              result = e lement;
  4342              return tru e;
  4343           }
  4344         });
  4345         retu rn result;
  4346       }
  4347  
  4348       functi on getYOff set() {
  4349  
  4350         var  offset = s croll.yOff set;
  4351  
  4352         if ( isFunction (offset))  {
  4353           of fset = off set();
  4354         } el se if (isE lement(off set)) {
  4355           va r elem = o ffset[0];
  4356           va r style =  $window.ge tComputedS tyle(elem) ;
  4357           if  (style.po sition !==  'fixed')  {
  4358              offset = 0 ;
  4359           }  else {
  4360              offset = e lem.getBou ndingClien tRect().bo ttom;
  4361           }
  4362         } el se if (!is Number(off set)) {
  4363           of fset = 0;
  4364         }
  4365  
  4366         retu rn offset;
  4367       }
  4368  
  4369       functi on scrollT o(elem) {
  4370         if ( elem) {
  4371           el em.scrollI ntoView();
  4372  
  4373           va r offset =  getYOffse t();
  4374  
  4375           if  (offset)  {
  4376              // `offset ` is the n umber of p ixels we s hould scro ll UP in o rder to al ign `elem`  properly.
  4377              // This is  true ONLY  if the ca ll to `ele m.scrollIn toView()`  initially  aligns `el em` at the
  4378              // top of  the viewpo rt.
  4379              //
  4380              // IF the  number of  pixels fro m the top  of `elem`  to the end  of the pa ge's conte nt is less
  4381              // than th e height o f the view port, then  `elem.scr ollIntoVie w()` will  align the  `elem` som e
  4382              // way dow n the page .
  4383              //
  4384              // This is  often the  case for  elements n ear the bo ttom of th e page.
  4385              //
  4386              // In such  cases we  do not nee d to scrol l the whol e `offset`  up, just  the differ ence betwe en
  4387              // the top  of the el ement and  the offset , which is  enough to  align the  top of `e lem` at th e
  4388              // desired  position.
  4389              var elemTo p = elem.g etBounding ClientRect ().top;
  4390              $window.sc rollBy(0,  elemTop -  offset);
  4391           }
  4392         } el se {
  4393           $w indow.scro llTo(0, 0) ;
  4394         }
  4395       }
  4396  
  4397       functi on scroll( ) {
  4398         var  hash = $lo cation.has h(), elm;
  4399  
  4400         // e mpty hash,  scroll to  the top o f the page
  4401         if ( !hash) scr ollTo(null );
  4402  
  4403         // e lement wit h given id
  4404         else  if ((elm  = document .getElemen tById(hash ))) scroll To(elm);
  4405  
  4406         // f irst ancho r with giv en name :- D
  4407         else  if ((elm  = getFirst Anchor(doc ument.getE lementsByN ame(hash)) )) scrollT o(elm);
  4408  
  4409         // n o element  and hash = = 'top', s croll to t he top of  the page
  4410         else  if (hash  === 'top')  scrollTo( null);
  4411       }
  4412  
  4413       // doe s not scro ll when us er clicks  on anchor  link that  is current ly on
  4414       // (no  url chang e, no $loc ation.hash () change) , browser  native doe s scroll
  4415       if (au toScrollin gEnabled)  {
  4416         $roo tScope.$wa tch(functi on autoScr ollWatch()  {return $ location.h ash();},
  4417           fu nction aut oScrollWat chAction(n ewVal, old Val) {
  4418              // skip th e initial  scroll if  $location. hash is em pty
  4419              if (newVal  === oldVa l && newVa l === '')  return;
  4420  
  4421              jqLiteDocu mentLoaded (function( ) {
  4422                  $rootScope .$e DNS    ync(scroll );
  4423              });
  4424           }) ;
  4425       }
  4426  
  4427       return  scroll;
  4428     }];
  4429   }
  4430  
  4431   var $anima teMinErr =  minErr('$ animate');
  4432  
  4433   /**
  4434    * @ngdoc  provider
  4435    * @name $ animatePro vider
  4436    *
  4437    * @descri ption
  4438    * Default  implement ation of $ animate th at doesn't  perform a ny animati ons, inste ad just
  4439    * synchro nously per forms DOM
  4440    * updates  and calls  done() ca llbacks.
  4441    *
  4442    * In orde r to enabl e animatio ns the ngA nimate mod ule has to  be loaded .
  4443    *
  4444    * To see  the functi onal imple mentation  check out  src/ngAnim ate/animat e.js
  4445    */
  4446   var $Anima teProvider  = ['$prov ide', func tion($prov ide) {
  4447  
  4448  
  4449     this.$$s electors =  {};
  4450  
  4451  
  4452     /**
  4453      * @ngdo c method
  4454      * @name  $animateP rovider#re gister
  4455      *
  4456      * @desc ription
  4457      * Regis ters a new  injectabl e animatio n factory  function.  The factor y function  produces  the
  4458      * anima tion objec t which co ntains cal lback func tions for  each event  that is e xpected to  be
  4459      * anima ted.
  4460      *
  4461      *   * ` eventFn`:  `function( Element, d oneFunctio n)` The el ement to a nimate, th e `doneFun ction`
  4462      *   mus t be calle d once the  element a nimation i s complete . If a fun ction is r eturned th en the
  4463      *   ani mation ser vice will  use this f unction to  cancel th e animatio n whenever  a cancel  event is
  4464      *   tri ggered.
  4465      *
  4466      *
  4467      * ```js
  4468      *   ret urn {
  4469        *      eventFn :  function( element, d one) {
  4470        *        //code  to run the  animation
  4471        *        //once  complete,  then run d one()
  4472        *        return  function c ancellatio nFunction( ) {
  4473        *          //cod e to cance l the anim ation
  4474        *        }
  4475        *      }
  4476        *   }
  4477      * ```
  4478      *
  4479      * @para m {string}  name The  name of th e animatio n.
  4480      * @para m {Functio n} factory  The facto ry functio n that wil l be execu ted to ret urn the an imation
  4481      *                              object.
  4482      */
  4483     this.reg ister = fu nction(nam e, factory ) {
  4484       var ke y = name +  '-animati on';
  4485       if (na me && name .charAt(0)  != '.') t hrow $anim ateMinErr( 'notcsel',
  4486           "E xpecting c lass selec tor starti ng with '. ' got '{0} '.", name) ;
  4487       this.$ $selectors [name.subs tr(1)] = k ey;
  4488       $provi de.factory (key, fact ory);
  4489     };
  4490  
  4491     /**
  4492      * @ngdo c method
  4493      * @name  $animateP rovider#cl assNameFil ter
  4494      *
  4495      * @desc ription
  4496      * Sets  and/or ret urns the C SS class r egular exp ression th at is chec ked when p erforming
  4497      * an an imation. U pon bootst rap the cl assNameFil ter value  is not set  at all an d will
  4498      * there fore enabl e $animate  to attemp t to perfo rm an anim ation on a ny element .
  4499      * When  setting th e classNam eFilter va lue, anima tions will  only be p erformed o n elements
  4500      * that  successful ly match t he filter  expression . This in  turn can b oost perfo rmance
  4501      * for l ow-powered  devices a s well as  applicatio ns contain ing a lot  of structu ral operat ions.
  4502      * @para m {RegExp= } expressi on The cla ssName exp ression wh ich will b e checked  against al l animatio ns
  4503      * @retu rn {RegExp } The curr ent CSS cl assName ex pression v alue. If n ull then t here is no  expressio n value
  4504      */
  4505     this.cla ssNameFilt er = funct ion(expres sion) {
  4506       if (ar guments.le ngth === 1 ) {
  4507         this .$$classNa meFilter =  (expressi on instanc eof RegExp ) ? expres sion : nul l;
  4508       }
  4509       return  this.$$cl assNameFil ter;
  4510     };
  4511  
  4512     this.$ge t = ['$$q' , '$$async Callback',  '$rootSco pe', funct ion($$q, $ $asyncCall back, $roo tScope) {
  4513  
  4514       var cu rrentDefer ;
  4515  
  4516       functi on runAnim ationPostD igest(fn)  {
  4517         var  cancelFn,  defer = $$ q.defer();
  4518         defe r.promise. $$cancelFn  = functio n ngAnimat eMaybeCanc el() {
  4519           ca ncelFn &&  cancelFn() ;
  4520         };
  4521  
  4522         $roo tScope.$$p ostDigest( function n gAnimatePo stDigest()  {
  4523           ca ncelFn = f n(function  ngAnimate NotifyComp lete() {
  4524              defer.reso lve();
  4525           }) ;
  4526         });
  4527  
  4528         retu rn defer.p romise;
  4529       }
  4530  
  4531       functi on resolve ElementCla sses(eleme nt, classe s) {
  4532         var  toAdd = [] , toRemove  = [];
  4533  
  4534         var  hasClasses  = createM ap();
  4535         forE ach((eleme nt.attr('c lass') ||  '').split( /\s+/), fu nction(cla ssName) {
  4536           ha sClasses[c lassName]  = true;
  4537         });
  4538  
  4539         forE ach(classe s, functio n(status,  className)  {
  4540           va r hasClass  = hasClas ses[classN ame];
  4541  
  4542           //  If the mo st recent  class mani pulation ( via $anima te) was to  remove th e class, a nd the
  4543           //  element c urrently h as the cla ss, the cl ass is sch eduled for  removal.  Otherwise,  if
  4544           //  the most  recent cla ss manipul ation (via  $animate)  was to ad d the clas s, and the
  4545           //  element d oes not cu rrently ha ve the cla ss, the cl ass is sch eduled to  be added.
  4546           if  (status = == false & & hasClass ) {
  4547              toRemove.p ush(classN ame);
  4548           }  else if (s tatus ===  true && !h asClass) {
  4549              toAdd.push (className );
  4550           }
  4551         });
  4552  
  4553         retu rn (toAdd. length + t oRemove.le ngth) > 0  &&
  4554           [t oAdd.lengt h ? toAdd  : null, to Remove.len gth ? toRe move : nul l];
  4555       }
  4556  
  4557       functi on cachedC lassManipu lation(cac he, classe s, op) {
  4558         for  (var i=0,  ii = class es.length;  i < ii; + +i) {
  4559           va r classNam e = classe s[i];
  4560           ca che[classN ame] = op;
  4561         }
  4562       }
  4563  
  4564       functi on asyncPr omise() {
  4565         // o nly serve  one instan ce of a pr omise in o rder to sa ve CPU cyc les
  4566         if ( !currentDe fer) {
  4567           cu rrentDefer  = $$q.def er();
  4568           $$ asyncCallb ack(functi on() {
  4569              currentDef er.resolve ();
  4570              currentDef er = null;
  4571           }) ;
  4572         }
  4573         retu rn current Defer.prom ise;
  4574       }
  4575  
  4576       functi on applySt yles(eleme nt, option s) {
  4577         if ( angular.is Object(opt ions)) {
  4578           va r styles =  extend(op tions.from  || {}, op tions.to | | {});
  4579           el ement.css( styles);
  4580         }
  4581       }
  4582  
  4583       /**
  4584        *
  4585        * @ng doc servic e
  4586        * @na me $animat e
  4587        * @de scription  The $anima te service  provides  rudimentar y DOM mani pulation f unctions t o
  4588        * ins ert, remov e and move  elements  within the  DOM, as w ell as add ing and re moving cla sses.
  4589        * Thi s service  is the cor e service  used by th e ngAnimat e $animato r service  which prov ides
  4590        * hig h-level an imation ho oks for CS S and Java Script.
  4591        *
  4592        * $an imate is a vailable i n the Angu larJS core , however,  the ngAni mate modul e must be  included
  4593        * to  enable ful l out anim ation supp ort. Other wise, $ani mate will  only perfo rm simple  DOM
  4594        * man ipulation  operations .
  4595        *
  4596        * To  learn more  about ena bling anim ation supp ort, click  here to v isit the { @link ngAn imate
  4597        * ngA nimate mod ule page}  as well as  the {@lin k ngAnimat e.$animate  ngAnimate  $animate  service
  4598        * pag e}.
  4599        */
  4600       return  {
  4601         anim ate: funct ion(elemen t, from, t o) {
  4602           ap plyStyles( element, {  from: fro m, to: to  });
  4603           re turn async Promise();
  4604         },
  4605  
  4606         /**
  4607          *
  4608          * @ ngdoc meth od
  4609          * @ name $anim ate#enter
  4610          * @ kind funct ion
  4611          * @ descriptio n Inserts  the elemen t into the  DOM eithe r after th e `after`  element or
  4612          * a s the firs t child wi thin the ` parent` el ement. Whe n the func tion is ca lled a pro mise
  4613          * i s returned  that will  be resolv ed at a la ter time.
  4614          * @ param {DOM Element} e lement the  element w hich will  be inserte d into the  DOM
  4615          * @ param {DOM Element} p arent the  parent ele ment which  will appe nd the ele ment as
  4616          *    a child ( if the aft er element  is not pr esent)
  4617          * @ param {DOM Element} a fter the s ibling ele ment which  will appe nd the ele ment
  4618          *    after its elf
  4619          * @ param {obj ect=} opti ons an opt ional coll ection of  styles tha t will be  applied to  the eleme nt.
  4620          * @ return {Pr omise} the  animation  callback  promise
  4621          */
  4622         ente r: functio n(element,  parent, a fter, opti ons) {
  4623           ap plyStyles( element, o ptions);
  4624           af ter ? afte r.after(el ement)
  4625                  : pare nt.prepend (element);
  4626           re turn async Promise();
  4627         },
  4628  
  4629         /**
  4630          *
  4631          * @ ngdoc meth od
  4632          * @ name $anim ate#leave
  4633          * @ kind funct ion
  4634          * @ descriptio n Removes  the elemen t from the  DOM. When  the funct ion is cal led a prom ise
  4635          * i s returned  that will  be resolv ed at a la ter time.
  4636          * @ param {DOM Element} e lement the  element w hich will  be removed  from the  DOM
  4637          * @ param {obj ect=} opti ons an opt ional coll ection of  options th at will be  applied t o the elem ent.
  4638          * @ return {Pr omise} the  animation  callback  promise
  4639          */
  4640         leav e: functio n(element,  options)  {
  4641           el ement.remo ve();
  4642           re turn async Promise();
  4643         },
  4644  
  4645         /**
  4646          *
  4647          * @ ngdoc meth od
  4648          * @ name $anim ate#move
  4649          * @ kind funct ion
  4650          * @ descriptio n Moves th e position  of the pr ovided ele ment withi n the DOM  to be plac ed
  4651          * e ither afte r the `aft er` elemen t or insid e of the ` parent` el ement. Whe n the func tion
  4652          * i s called a  promise i s returned  that will  be resolv ed at a la ter time.
  4653          *
  4654          * @ param {DOM Element} e lement the  element w hich will  be moved a round with in the
  4655          *    DOM
  4656          * @ param {DOM Element} p arent the  parent ele ment where  the eleme nt will be
  4657          *    inserted  into (if t he after e lement is  not presen t)
  4658          * @ param {DOM Element} a fter the s ibling ele ment where  the eleme nt will be
  4659          *    positione d next to
  4660          * @ param {obj ect=} opti ons an opt ional coll ection of  options th at will be  applied t o the elem ent.
  4661          * @ return {Pr omise} the  animation  callback  promise
  4662          */
  4663         move : function (element,  parent, af ter, optio ns) {
  4664           //  Do not re move eleme nt before  insert. Re moving wil l cause da ta associa ted with t he
  4665           //  element t o be dropp ed. Insert  will impl icitly do  the remove .
  4666           re turn this. enter(elem ent, paren t, after,  options);
  4667         },
  4668  
  4669         /**
  4670          *
  4671          * @ ngdoc meth od
  4672          * @ name $anim ate#addCla ss
  4673          * @ kind funct ion
  4674          * @ descriptio n Adds the  provided  className  CSS class  value to t he provide d element.
  4675          * W hen the fu nction is  called a p romise is  returned t hat will b e resolved  at a late r time.
  4676          * @ param {DOM Element} e lement the  element w hich will  have the c lassName v alue
  4677          *    added to  it
  4678          * @ param {str ing} class Name the C SS class w hich will  be added t o the elem ent
  4679          * @ param {obj ect=} opti ons an opt ional coll ection of  options th at will be  applied t o the elem ent.
  4680          * @ return {Pr omise} the  animation  callback  promise
  4681          */
  4682         addC lass: func tion(eleme nt, classN ame, optio ns) {
  4683           re turn this. setClass(e lement, cl assName, [ ], options );
  4684         },
  4685  
  4686         $$ad dClassImme diately: f unction(el ement, cla ssName, op tions) {
  4687           el ement = jq Lite(eleme nt);
  4688           cl assName =  !isString( className)
  4689                             ? (isA rray(class Name) ? cl assName.jo in(' ') :  '')
  4690                             : clas sName;
  4691           fo rEach(elem ent, funct ion(elemen t) {
  4692              jqLiteAddC lass(eleme nt, classN ame);
  4693           }) ;
  4694           ap plyStyles( element, o ptions);
  4695           re turn async Promise();
  4696         },
  4697  
  4698         /**
  4699          *
  4700          * @ ngdoc meth od
  4701          * @ name $anim ate#remove Class
  4702          * @ kind funct ion
  4703          * @ descriptio n Removes  the provid ed classNa me CSS cla ss value f rom the pr ovided ele ment.
  4704          * W hen the fu nction is  called a p romise is  returned t hat will b e resolved  at a late r time.
  4705          * @ param {DOM Element} e lement the  element w hich will  have the c lassName v alue
  4706          *    removed f rom it
  4707          * @ param {str ing} class Name the C SS class w hich will  be removed  from the  element
  4708          * @ param {obj ect=} opti ons an opt ional coll ection of  options th at will be  applied t o the elem ent.
  4709          * @ return {Pr omise} the  animation  callback  promise
  4710          */
  4711         remo veClass: f unction(el ement, cla ssName, op tions) {
  4712           re turn this. setClass(e lement, [] , classNam e, options );
  4713         },
  4714  
  4715         $$re moveClassI mmediately : function (element,  className,  options)  {
  4716           el ement = jq Lite(eleme nt);
  4717           cl assName =  !isString( className)
  4718                             ? (isA rray(class Name) ? cl assName.jo in(' ') :  '')
  4719                             : clas sName;
  4720           fo rEach(elem ent, funct ion(elemen t) {
  4721              jqLiteRemo veClass(el ement, cla ssName);
  4722           }) ;
  4723           ap plyStyles( element, o ptions);
  4724           re turn async Promise();
  4725         },
  4726  
  4727         /**
  4728          *
  4729          * @ ngdoc meth od
  4730          * @ name $anim ate#setCla ss
  4731          * @ kind funct ion
  4732          * @ descriptio n Adds and /or remove s the give n CSS clas ses to and  from the  element.
  4733          * W hen the fu nction is  called a p romise is  returned t hat will b e resolved  at a late r time.
  4734          * @ param {DOM Element} e lement the  element w hich will  have its C SS classes  changed
  4735          *    removed f rom it
  4736          * @ param {str ing} add t he CSS cla sses which  will be a dded to th e element
  4737          * @ param {str ing} remov e the CSS  class whic h will be  removed fr om the ele ment
  4738          * @ param {obj ect=} opti ons an opt ional coll ection of  options th at will be  applied t o the elem ent.
  4739          * @ return {Pr omise} the  animation  callback  promise
  4740          */
  4741         setC lass: func tion(eleme nt, add, r emove, opt ions) {
  4742           va r self = t his;
  4743           va r STORAGE_ KEY = '$$a nimateClas ses';
  4744           va r createdC ache = fal se;
  4745           el ement = jq Lite(eleme nt);
  4746  
  4747           va r cache =  element.da ta(STORAGE _KEY);
  4748           if  (!cache)  {
  4749              cache = {
  4750                classes:  {},
  4751                options:  options
  4752              };
  4753              createdCac he = true;
  4754           }  else if (o ptions &&  cache.opti ons) {
  4755              cache.opti ons = angu lar.extend (cache.opt ions || {} , options) ;
  4756           }
  4757  
  4758           va r classes  = cache.cl asses;
  4759  
  4760           ad d = isArra y(add) ? a dd : add.s plit(' ');
  4761           re move = isA rray(remov e) ? remov e : remove .split(' ' );
  4762           ca chedClassM anipulatio n(classes,  add, true );
  4763           ca chedClassM anipulatio n(classes,  remove, f alse);
  4764  
  4765           if  (createdC ache) {
  4766              cache.prom ise = runA nimationPo stDigest(f unction(do ne) {
  4767                var cach e = elemen t.data(STO RAGE_KEY);
  4768                element. removeData (STORAGE_K EY);
  4769  
  4770                // in th e event th at the ele ment is re moved befo re postDig est
  4771                // is ru n then the  cache wil l be undef ined and t here will  be
  4772                // no ne ed anymore  to add or  remove an d of the e lement cla sses
  4773                if (cach e) {
  4774                  var cl asses = re solveEleme ntClasses( element, c ache.class es);
  4775                  if (cl asses) {
  4776                    self .$$setClas sImmediate ly(element , classes[ 0], classe s[1], cach e.options) ;
  4777                  }
  4778                }
  4779  
  4780                done();
  4781              });
  4782              element.da ta(STORAGE _KEY, cach e);
  4783           }
  4784  
  4785           re turn cache .promise;
  4786         },
  4787  
  4788         $$se tClassImme diately: f unction(el ement, add , remove,  options) {
  4789           ad d && this. $$addClass Immediatel y(element,  add);
  4790           re move && th is.$$remov eClassImme diately(el ement, rem ove);
  4791           ap plyStyles( element, o ptions);
  4792           re turn async Promise();
  4793         },
  4794  
  4795         enab led: noop,
  4796         canc el: noop
  4797       };
  4798     }];
  4799   }];
  4800  
  4801   function $ $AsyncCall backProvid er() {
  4802     this.$ge t = ['$$rA F', '$time out', func tion($$rAF , $timeout ) {
  4803       return  $$rAF.sup ported
  4804         ? fu nction(fn)  { return  $$rAF(fn);  }
  4805         : fu nction(fn)  {
  4806           re turn $time out(fn, 0,  false);
  4807         };
  4808     }];
  4809   }
  4810  
  4811   /* global  stripHash:  true */
  4812  
  4813   /**
  4814    * ! This  is a priva te undocum ented serv ice !
  4815    *
  4816    * @name $ browser
  4817    * @requir es $log
  4818    * @descri ption
  4819    * This ob ject has t wo goals:
  4820    *
  4821    * - hide  all the gl obal state  in the br owser caus ed by the  window obj ect
  4822    * - abstr act away a ll the bro wser speci fic featur es and inc onsistenci es
  4823    *
  4824    * For tes ts we prov ide {@link  ngMock.$b rowser moc k implemen tation} of  the `$bro wser`
  4825    * service , which ca n be used  for conven ient testi ng of the  applicatio n without  the intera ction with
  4826    * the rea l browser  apis.
  4827    */
  4828   /**
  4829    * @param  {object} w indow The  global win dow object .
  4830    * @param  {object} d ocument jQ uery wrapp ed documen t.
  4831    * @param  {object} $ log window .console o r an objec t with the  same inte rface.
  4832    * @param  {object} $ sniffer $s niffer ser vice
  4833    */
  4834   function B rowser(win dow, docum ent, $log,  $sniffer)  {
  4835     var self  = this,
  4836         rawD ocument =  document[0 ],
  4837         loca tion = win dow.locati on,
  4838         hist ory = wind ow.history ,
  4839         setT imeout = w indow.setT imeout,
  4840         clea rTimeout =  window.cl earTimeout ,
  4841         pend ingDeferId s = {};
  4842  
  4843     self.isM ock = fals e;
  4844  
  4845     var outs tandingReq uestCount  = 0;
  4846     var outs tandingReq uestCallba cks = [];
  4847  
  4848     // TODO( vojta): re move this  temporary  api
  4849     self.$$c ompleteOut standingRe quest = co mpleteOuts tandingReq uest;
  4850     self.$$i ncOutstand ingRequest Count = fu nction() {  outstandi ngRequestC ount++; };
  4851  
  4852     /**
  4853      * Execu tes the `f n` functio n(supports  currying)  and decre ments the  `outstandi ngRequestC allbacks`
  4854      * count er. If the  counter r eaches 0,  all the `o utstanding RequestCal lbacks` ar e executed .
  4855      */
  4856     function  completeO utstanding Request(fn ) {
  4857       try {
  4858         fn.a pply(null,  sliceArgs (arguments , 1));
  4859       } fina lly {
  4860         outs tandingReq uestCount- -;
  4861         if ( outstandin gRequestCo unt === 0)  {
  4862           wh ile (outst andingRequ estCallbac ks.length)  {
  4863              try {
  4864                outstand ingRequest Callbacks. pop()();
  4865              } catch (e ) {
  4866                $log.err or(e);
  4867              }
  4868           }
  4869         }
  4870       }
  4871     }
  4872  
  4873     /**
  4874      * @priv ate
  4875      * Note:  this meth od is used  only by s cenario ru nner
  4876      * TODO( vojta): pr efix this  method wit h $$ ?
  4877      * @para m {functio n()} callb ack Functi on that wi ll be call ed when no  outstandi ng request
  4878      */
  4879     self.not ifyWhenNoO utstanding Requests =  function( callback)  {
  4880       // for ce browser  to execut e all poll Fns - this  is needed  so that c ookies and  other pol lers fire
  4881       // at  some deter ministic t ime in res pect to th e test run ner's acti ons. Leavi ng things  up to the
  4882       // reg ular polle r would re sult in fl aky tests.
  4883       forEac h(pollFns,  function( pollFn) {  pollFn();  });
  4884  
  4885       if (ou tstandingR equestCoun t === 0) {
  4886         call back();
  4887       } else  {
  4888         outs tandingReq uestCallba cks.push(c allback);
  4889       }
  4890     };
  4891  
  4892     //////// ////////// ////////// ////////// ////////// ////////// ////
  4893     // Poll  Watcher AP I
  4894     //////// ////////// ////////// ////////// ////////// ////////// ////
  4895     var poll Fns = [],
  4896         poll Timeout;
  4897  
  4898     /**
  4899      * @name  $browser# addPollFn
  4900      *
  4901      * @para m {functio n()} fn Po ll functio n to add
  4902      *
  4903      * @desc ription
  4904      * Adds  a function  to the li st of func tions that  poller pe riodically  executes,
  4905      * and s tarts poll ing if not  started y et.
  4906      *
  4907      * @retu rns {funct ion()} the  added fun ction
  4908      */
  4909     self.add PollFn = f unction(fn ) {
  4910       if (is Undefined( pollTimeou t)) startP oller(100,  setTimeou t);
  4911       pollFn s.push(fn) ;
  4912       return  fn;
  4913     };
  4914  
  4915     /**
  4916      * @para m {number}  interval  How often  should bro wser call  poll funct ions (ms)
  4917      * @para m {functio n()} setTi meout Refe rence to a  real or f ake `setTi meout` fun ction.
  4918      *
  4919      * @desc ription
  4920      * Confi gures the  poller to  run in the  specified  intervals , using th e specifie d
  4921      * setTi meout fn a nd kicks i t off.
  4922      */
  4923     function  startPoll er(interva l, setTime out) {
  4924       (funct ion check( ) {
  4925         forE ach(pollFn s, functio n(pollFn)  { pollFn() ; });
  4926         poll Timeout =  setTimeout (check, in terval);
  4927       })();
  4928     }
  4929  
  4930     //////// ////////// ////////// ////////// ////////// ////////// ////
  4931     // URL A PI
  4932     //////// ////////// ////////// ////////// ////////// ////////// ////
  4933  
  4934     var cach edState, l astHistory State,
  4935         last BrowserUrl  = locatio n.href,
  4936         base Element =  document.f ind('base' ),
  4937         relo adLocation  = null;
  4938  
  4939     cacheSta te();
  4940     lastHist oryState =  cachedSta te;
  4941  
  4942     /**
  4943      * @name  $browser# url
  4944      *
  4945      * @desc ription
  4946      * GETTE R:
  4947      * Witho ut any arg ument, thi s method j ust return s current  value of l ocation.hr ef.
  4948      *
  4949      * SETTE R:
  4950      * With  at least o ne argumen t, this me thod sets  url to new  value.
  4951      * If ht ml5 histor y api supp orted, pus hState/rep laceState  is used, o therwise
  4952      * locat ion.href/l ocation.re place is u sed.
  4953      * Retur ns its own  instance  to allow c haining
  4954      *
  4955      * NOTE:  this api  is intende d for use  only by th e $locatio n service.  Please us e the
  4956      * {@lin k ng.$loca tion $loca tion servi ce} to cha nge url.
  4957      *
  4958      * @para m {string}  url New u rl (when u sed as set ter)
  4959      * @para m {boolean =} replace  Should ne w url repl ace curren t history  record?
  4960      * @para m {object= } state ob ject to us e with pus hState/rep laceState
  4961      */
  4962     self.url  = functio n(url, rep lace, stat e) {
  4963       // In  modern bro wsers `his tory.state ` is `null ` by defau lt; treati ng it sepa rately
  4964       // fro m `undefin ed` would  cause `$br owser.url( '/foo')` t o change ` history.st ate`
  4965       // to  undefined  via `pushS tate`. Ins tead, let' s change ` undefined`  to `null`  here.
  4966       if (is Undefined( state)) {
  4967         stat e = null;
  4968       }
  4969  
  4970       // And roid Brows er BFCache  causes lo cation, hi story refe rence to b ecome stal e.
  4971       if (lo cation !==  window.lo cation) lo cation = w indow.loca tion;
  4972       if (hi story !==  window.his tory) hist ory = wind ow.history ;
  4973  
  4974       // set ter
  4975       if (ur l) {
  4976         var  sameState  = lastHist oryState = == state;
  4977  
  4978         // D on't chang e anything  if previo us and cur rent URLs  and states  match. Th is also pr events
  4979         // I E<10 from  getting in to redirec t loop whe n in Locat ionHashban gInHtml5Ur l mode.
  4980         // S ee https:/ /github.co m/angular/ angular.js /commit/ff b2701
  4981         if ( lastBrowse rUrl === u rl && (!$s niffer.his tory || sa meState))  {
  4982           re turn self;
  4983         }
  4984         var  sameBase =  lastBrows erUrl && s tripHash(l astBrowser Url) === s tripHash(u rl);
  4985         last BrowserUrl  = url;
  4986         last HistorySta te = state ;
  4987         // D on't use h istory API  if only t he hash ch anged
  4988         // d ue to a bu g in IE10/ IE11 which  leads
  4989         // t o not firi ng a `hash change` no r `popstat e` event
  4990         // i n some cas es (see #9 143).
  4991         if ( $sniffer.h istory &&  (!sameBase  || !sameS tate)) {
  4992           hi story[repl ace ? 'rep laceState'  : 'pushSt ate'](stat e, '', url );
  4993           ca cheState() ;
  4994           //  Do the as signment a gain so th at those t wo variabl es are ref erentially  identical .
  4995           la stHistoryS tate = cac hedState;
  4996         } el se {
  4997           if  (!sameBas e) {
  4998              reloadLoca tion = url ;
  4999           }
  5000           if  (replace)  {
  5001              location.r eplace(url );
  5002           }  else {
  5003              location.h ref = url;
  5004           }
  5005         }
  5006         retu rn self;
  5007       // get ter
  5008       } else  {
  5009         // -  reloadLoc ation is n eeded as b rowsers do n't allow  to read ou t
  5010         //    the new l ocation.hr ef if a re load happe ned.
  5011         // -  the repla cement is  a workarou nd for htt ps://bugzi lla.mozill a.org/show _bug.cgi?i d=407172
  5012         retu rn reloadL ocation ||  location. href.repla ce(/%27/g, "'");
  5013       }
  5014     };
  5015  
  5016     /**
  5017      * @name  $browser# state
  5018      *
  5019      * @desc ription
  5020      * This  method is  a getter.
  5021      *
  5022      * Retur n history. state or n ull if his tory.state  is undefi ned.
  5023      *
  5024      * @retu rns {objec t} state
  5025      */
  5026     self.sta te = funct ion() {
  5027       return  cachedSta te;
  5028     };
  5029  
  5030     var urlC hangeListe ners = [],
  5031         urlC hangeInit  = false;
  5032  
  5033     function  cacheStat eAndFireUr lChange()  {
  5034       cacheS tate();
  5035       fireUr lChange();
  5036     }
  5037  
  5038     // This  variable s hould be u sed *only*  inside th e cacheSta te functio n.
  5039     var last CachedStat e = null;
  5040     function  cacheStat e() {
  5041       // Thi s should b e the only  place in  $browser w here `hist ory.state`  is read.
  5042       cached State = wi ndow.histo ry.state;
  5043       cached State = is Undefined( cachedStat e) ? null  : cachedSt ate;
  5044  
  5045       // Pre vent callb acks fo fi re twice i f both has hchange &  popstate w ere fired.
  5046       if (eq uals(cache dState, la stCachedSt ate)) {
  5047         cach edState =  lastCached State;
  5048       }
  5049       lastCa chedState  = cachedSt ate;
  5050     }
  5051  
  5052     function  fireUrlCh ange() {
  5053       if (la stBrowserU rl === sel f.url() &&  lastHisto ryState == = cachedSt ate) {
  5054         retu rn;
  5055       }
  5056  
  5057       lastBr owserUrl =  self.url( );
  5058       lastHi storyState  = cachedS tate;
  5059       forEac h(urlChang eListeners , function (listener)  {
  5060         list ener(self. url(), cac hedState);
  5061       });
  5062     }
  5063  
  5064     /**
  5065      * @name  $browser# onUrlChang e
  5066      *
  5067      * @desc ription
  5068      * Regis ter callba ck functio n that wil l be calle d, when ur l changes.
  5069      *
  5070      * It's  only calle d when the  url is ch anged from  outside o f angular:
  5071      * - use r types di fferent ur l into add ress bar
  5072      * - use r clicks o n history  (forward/b ack) butto n
  5073      * - use r clicks o n a link
  5074      *
  5075      * It's  not called  when url  is changed  by $brows er.url() m ethod
  5076      *
  5077      * The l istener ge ts called  with new u rl as para meter.
  5078      *
  5079      * NOTE:  this api  is intende d for use  only by th e $locatio n service.  Please us e the
  5080      * {@lin k ng.$loca tion $loca tion servi ce} to mon itor url c hanges in  angular ap ps.
  5081      *
  5082      * @para m {functio n(string)}  listener  Listener f unction to  be called  when url  changes.
  5083      * @retu rn {functi on(string) } Returns  the regist ered liste ner fn - h andy if th e fn is an onymous.
  5084      */
  5085     self.onU rlChange =  function( callback)  {
  5086       // TOD O(vojta):  refactor t o use node 's syntax  for events
  5087       if (!u rlChangeIn it) {
  5088         // W e listen o n both (ha shchange/p opstate) w hen availa ble, as so me browser s (e.g. Op era)
  5089         // d on't fire  popstate w hen user c hange the  address ba r and don' t fire has hchange wh en url
  5090         // c hanged by  push/repla ceState
  5091  
  5092         // h tml5 histo ry api - p opstate ev ent
  5093         if ( $sniffer.h istory) jq Lite(windo w).on('pop state', ca cheStateAn dFireUrlCh ange);
  5094         // h ashchange  event
  5095         jqLi te(window) .on('hashc hange', ca cheStateAn dFireUrlCh ange);
  5096  
  5097         urlC hangeInit  = true;
  5098       }
  5099  
  5100       urlCha ngeListene rs.push(ca llback);
  5101       return  callback;
  5102     };
  5103  
  5104     /**
  5105      * Check s whether  the url ha s changed  outside of  Angular.
  5106      * Needs  to be exp orted to b e able to  check for  changes th at have be en done in  sync,
  5107      * as ha shchange/p opstate ev ents fire  in async.
  5108      */
  5109     self.$$c heckUrlCha nge = fire UrlChange;
  5110  
  5111     //////// ////////// ////////// ////////// ////////// ////////// ////
  5112     // Misc  API
  5113     //////// ////////// ////////// ////////// ////////// ////////// ////
  5114  
  5115     /**
  5116      * @name  $browser# baseHref
  5117      *
  5118      * @desc ription
  5119      * Retur ns current  <base hre f>
  5120      * (alwa ys relativ e - withou t domain)
  5121      *
  5122      * @retu rns {strin g} The cur rent base  href
  5123      */
  5124     self.bas eHref = fu nction() {
  5125       var hr ef = baseE lement.att r('href');
  5126       return  href ? hr ef.replace (/^(https? \:)?\/\/[^ \/]*/, '')  : '';
  5127     };
  5128  
  5129     //////// ////////// ////////// ////////// ////////// ////////// ////
  5130     // Cooki es API
  5131     //////// ////////// ////////// ////////// ////////// ////////// ////
  5132     var last Cookies =  {};
  5133     var last CookieStri ng = '';
  5134     var cook iePath = s elf.baseHr ef();
  5135  
  5136     function  safeDecod eURICompon ent(str) {
  5137       try {
  5138         retu rn decodeU RIComponen t(str);
  5139       } catc h (e) {
  5140         retu rn str;
  5141       }
  5142     }
  5143  
  5144     /**
  5145      * @name  $browser# cookies
  5146      *
  5147      * @para m {string= } name Coo kie name
  5148      * @para m {string= } value Co okie value
  5149      *
  5150      * @desc ription
  5151      * The c ookies met hod provid es a 'priv ate' low l evel acces s to brows er cookies .
  5152      * It is  not meant  to be use d directly , use the  $cookie se rvice inst ead.
  5153      *
  5154      * The r eturn valu es vary de pending on  the argum ents that  the method  was calle d with as  follows:
  5155      *
  5156      * - coo kies() ->  hash of al l cookies,  this is N OT a copy  of the int ernal stat e, so do n ot modify
  5157      *   it
  5158      * - coo kies(name,  value) ->  set name  to value,  if value i s undefine d delete t he cookie
  5159      * - coo kies(name)  -> the sa me as (nam e, undefin ed) == DEL ETES (no o ne calls i t right no w that
  5160      *   way )
  5161      *
  5162      * @retu rns {Objec t} Hash of  all cooki es (if cal led withou t any para meter)
  5163      */
  5164     self.coo kies = fun ction(name , value) {
  5165       var co okieLength , cookieAr ray, cooki e, i, inde x;
  5166  
  5167       if (na me) {
  5168         if ( value ===  undefined)  {
  5169           ra wDocument. cookie = e ncodeURICo mponent(na me) + "=;p ath=" + co okiePath +
  5170                                      ";expire s=Thu, 01  Jan 1970 0 0:00:00 GM T";
  5171         } el se {
  5172           if  (isString (value)) {
  5173              cookieLeng th = (rawD ocument.co okie = enc odeURIComp onent(name ) + '=' +  encodeURIC omponent(v alue) +
  5174                                      ';path='  + cookieP ath).lengt h + 1;
  5175  
  5176              // per htt p://www.ie tf.org/rfc /rfc2109.t xt browser  must allo w at minim um:
  5177              // - 300 c ookies
  5178              // - 20 co okies per  unique dom ain
  5179              // - 4096  bytes per  cookie
  5180              if (cookie Length > 4 096) {
  5181                $log.war n("Cookie  '" + name  +
  5182                  "' pos sibly not  set or ove rflowed be cause it w as too lar ge (" +
  5183                  cookie Length + "  > 4096 by tes)!");
  5184              }
  5185           }
  5186         }
  5187       } else  {
  5188         if ( rawDocumen t.cookie ! == lastCoo kieString)  {
  5189           la stCookieSt ring = raw Document.c ookie;
  5190           co okieArray  = lastCook ieString.s plit("; ") ;
  5191           la stCookies  = {};
  5192  
  5193           fo r (i = 0;  i < cookie Array.leng th; i++) {
  5194              cookie = c ookieArray [i];
  5195              index = co okie.index Of('=');
  5196              if (index  > 0) { //i gnore name less cooki es
  5197                name = s afeDecodeU RIComponen t(cookie.s ubstring(0 , index));
  5198                // the f irst value  that is s een for a  cookie is  the most
  5199                // speci fic one.   values for  the same  cookie nam e that
  5200                // follo w are for  less speci fic paths.
  5201                if (last Cookies[na me] === un defined) {
  5202                  lastCo okies[name ] = safeDe codeURICom ponent(coo kie.substr ing(index  + 1));
  5203                }
  5204              }
  5205           }
  5206         }
  5207         retu rn lastCoo kies;
  5208       }
  5209     };
  5210  
  5211  
  5212     /**
  5213      * @name  $browser# defer
  5214      * @para m {functio n()} fn A  function,  who's exec ution shou ld be defe rred.
  5215      * @para m {number= } [delay=0 ] of milli seconds to  defer the  function  execution.
  5216      * @retu rns {*} De ferId that  can be us ed to canc el the tas k via `$br owser.defe r.cancel() `.
  5217      *
  5218      * @desc ription
  5219      * Execu tes a fn a synchronou sly via `s etTimeout( fn, delay) `.
  5220      *
  5221      * Unlik e when cal ling `setT imeout` di rectly, in  test this  function  is mocked  and instea d of using
  5222      * `setT imeout` in  tests, th e fns are  queued in  an array,  which can  be program matically  flushed
  5223      * via ` $browser.d efer.flush ()`.
  5224      *
  5225      */
  5226     self.def er = funct ion(fn, de lay) {
  5227       var ti meoutId;
  5228       outsta ndingReque stCount++;
  5229       timeou tId = setT imeout(fun ction() {
  5230         dele te pending DeferIds[t imeoutId];
  5231         comp leteOutsta ndingReque st(fn);
  5232       }, del ay || 0);
  5233       pendin gDeferIds[ timeoutId]  = true;
  5234       return  timeoutId ;
  5235     };
  5236  
  5237  
  5238     /**
  5239      * @name  $browser# defer.canc el
  5240      *
  5241      * @desc ription
  5242      * Cance ls a defer red task i dentified  with `defe rId`.
  5243      *
  5244      * @para m {*} defe rId Token  returned b y the `$br owser.defe r` functio n.
  5245      * @retu rns {boole an} Return s `true` i f the task  hasn't ex ecuted yet  and was s uccessfull y
  5246      *                      cancel ed.
  5247      */
  5248     self.def er.cancel  = function (deferId)  {
  5249       if (pe ndingDefer Ids[deferI d]) {
  5250         dele te pending DeferIds[d eferId];
  5251         clea rTimeout(d eferId);
  5252         comp leteOutsta ndingReque st(noop);
  5253         retu rn true;
  5254       }
  5255       return  false;
  5256     };
  5257  
  5258   }
  5259  
  5260   function $ BrowserPro vider() {
  5261     this.$ge t = ['$win dow', '$lo g', '$snif fer', '$do cument',
  5262         func tion($wind ow, $log,  $sniffer,  $document)  {
  5263           re turn new B rowser($wi ndow, $doc ument, $lo g, $sniffe r);
  5264         }];
  5265   }
  5266  
  5267   /**
  5268    * @ngdoc  service
  5269    * @name $ cacheFacto ry
  5270    *
  5271    * @descri ption
  5272    * Factory  that cons tructs {@l ink $cache Factory.Ca che Cache}  objects a nd gives a ccess to
  5273    * them.
  5274    *
  5275    * ```js
  5276    *
  5277    *  var ca che = $cac heFactory( 'cacheId') ;
  5278    *  expect ($cacheFac tory.get(' cacheId')) .toBe(cach e);
  5279    *  expect ($cacheFac tory.get(' noSuchCach eId')).not .toBeDefin ed();
  5280    *
  5281    *  cache. put("key",  "value");
  5282    *  cache. put("anoth er key", " another va lue");
  5283    *
  5284    *  // We' ve specifi ed no opti ons on cre ation
  5285    *  expect (cache.inf o()).toEqu al({id: 'c acheId', s ize: 2});
  5286    *
  5287    * ```
  5288    *
  5289    *
  5290    * @param  {string} c acheId Nam e or id of  the newly  created c ache.
  5291    * @param  {object=}  options Op tions obje ct that sp ecifies th e cache be havior. Pr operties:
  5292    *
  5293    *   - `{n umber=}` ` capacity`  — turns  the cache  into LRU c ache.
  5294    *
  5295    * @return s {object}  Newly cre ated cache  object wi th the fol lowing set  of method s:
  5296    *
  5297    * - `{obj ect}` `inf o()` â€” R eturns id,  size, and  options o f cache.
  5298    * - `{{*} }` `put({s tring} key , {*} valu e)` â€” Pu ts a new k ey-value p air into t he cache a nd returns
  5299    *   it.
  5300    * - `{{*} }` `get({s tring} key )` â€” Ret urns cache d value fo r `key` or  undefined  for cache  miss.
  5301    * - `{voi d}` `remov e({string}  key)` â€”  Removes a  key-value  pair from  the cache .
  5302    * - `{voi d}` `remov eAll()` â€ ” Removes  all cached  values.
  5303    * - `{voi d}` `destr oy()` â€”  Removes re ferences t o this cac he from $c acheFactor y.
  5304    *
  5305    * @exampl e
  5306      <exampl e module=" cacheExamp leApp">
  5307        <file  name="ind ex.html">
  5308          <di v ng-contr oller="Cac heControll er">
  5309            < input ng-m odel="newC acheKey" p laceholder ="Key">
  5310            < input ng-m odel="newC acheValue"  placehold er="Value" >
  5311            < button ng- click="put (newCacheK ey, newCac heValue)"> Cache</but ton>
  5312  
  5313            < p ng-if="k eys.length ">Cached V alues</p>
  5314            < div ng-rep eat="key i n keys">
  5315               <span ng- bind="key" ></span>
  5316               <span>: < /span>
  5317               <b ng-bin d="cache.g et(key)">< /b>
  5318            < /div>
  5319  
  5320            < p>Cache In fo</p>
  5321            < div ng-rep eat="(key,  value) in  cache.inf o()">
  5322               <span ng- bind="key" ></span>
  5323               <span>: < /span>
  5324               <b ng-bin d="value"> </b>
  5325            < /div>
  5326          </d iv>
  5327        </fil e>
  5328        <file  name="scr ipt.js">
  5329          ang ular.modul e('cacheEx ampleApp',  []).
  5330            c ontroller( 'CacheCont roller', [ '$scope',  '$cacheFac tory', fun ction($sco pe, $cache Factory) {
  5331               $scope.ke ys = [];
  5332               $scope.ca che = $cac heFactory( 'cacheId') ;
  5333               $scope.pu t = functi on(key, va lue) {
  5334                 if ($sc ope.cache. get(key) = == undefin ed) {
  5335                   $scop e.keys.pus h(key);
  5336                 }
  5337                 $scope. cache.put( key, value  === undef ined ? nul l : value) ;
  5338               };
  5339            } ]);
  5340        </fil e>
  5341        <file  name="sty le.css">
  5342          p {
  5343            m argin: 10p x 0 3px;
  5344          }
  5345        </fil e>
  5346      </examp le>
  5347    */
  5348   function $ CacheFacto ryProvider () {
  5349  
  5350     this.$ge t = functi on() {
  5351       var ca ches = {};
  5352  
  5353       functi on cacheFa ctory(cach eId, optio ns) {
  5354         if ( cacheId in  caches) {
  5355           th row minErr ('$cacheFa ctory')('i id', "Cach eId '{0}'  is already  taken!",  cacheId);
  5356         }
  5357  
  5358         var  size = 0,
  5359              stats = ex tend({}, o ptions, {i d: cacheId }),
  5360              data = {},
  5361              capacity =  (options  && options .capacity)  || Number .MAX_VALUE ,
  5362              lruHash =  {},
  5363              freshEnd =  null,
  5364              staleEnd =  null;
  5365  
  5366         /**
  5367          * @ ngdoc type
  5368          * @ name $cach eFactory.C ache
  5369          *
  5370          * @ descriptio n
  5371          * A  cache obj ect used t o store an d retrieve  data, pri marily use d by
  5372          * { @link $htt p $http} a nd the {@l ink ng.dir ective:scr ipt script } directiv e to cache
  5373          * t emplates a nd other d ata.
  5374          *
  5375          * ` ``js
  5376          *   angular.mo dule('supe rCache')
  5377          *     .factory ('superCac he', ['$ca cheFactory ', functio n($cacheFa ctory) {
  5378          *       return  $cacheFac tory('supe r-cache');
  5379          *     }]);
  5380          * ` ``
  5381          *
  5382          * E xample tes t:
  5383          *
  5384          * ` ``js
  5385          *   it('should  behave li ke a cache ', inject( function(s uperCache)  {
  5386          *     superCac he.put('ke y', 'value ');
  5387          *     superCac he.put('an other key' , 'another  value');
  5388          *
  5389          *     expect(s uperCache. info()).to Equal({
  5390          *       id: 's uper-cache ',
  5391          *       size:  2
  5392          *     });
  5393          *
  5394          *     superCac he.remove( 'another k ey');
  5395          *     expect(s uperCache. get('anoth er key')). toBeUndefi ned();
  5396          *
  5397          *     superCac he.removeA ll();
  5398          *     expect(s uperCache. info()).to Equal({
  5399          *       id: 's uper-cache ',
  5400          *       size:  0
  5401          *     });
  5402          *   }));
  5403          * ` ``
  5404          */
  5405         retu rn caches[ cacheId] =  {
  5406  
  5407           /* *
  5408            *  @ngdoc me thod
  5409            *  @name $ca cheFactory .Cache#put
  5410            *  @kind fun ction
  5411            *
  5412            *  @descript ion
  5413            *  Inserts a  named ent ry into th e {@link $ cacheFacto ry.Cache C ache} obje ct to be
  5414            *  retrieved  later, an d incremen ting the s ize of the  cache if  the key wa s not alre ady
  5415            *  present i n the cach e. If beha ving like  an LRU cac he, it wil l also rem ove stale
  5416            *  entries f rom the se t.
  5417            *
  5418            *  It will n ot insert  undefined  values int o the cach e.
  5419            *
  5420            *  @param {s tring} key  the key u nder which  the cache d data is  stored.
  5421            *  @param {* } value th e value to  store alo ngside the  key. If i t is undef ined, the  key
  5422            *     will n ot be stor ed.
  5423            *  @returns  {*} the va lue stored .
  5424            * /
  5425           pu t: functio n(key, val ue) {
  5426              if (capaci ty < Numbe r.MAX_VALU E) {
  5427                var lruE ntry = lru Hash[key]  || (lruHas h[key] = { key: key}) ;
  5428  
  5429                refresh( lruEntry);
  5430              }
  5431  
  5432              if (isUnde fined(valu e)) return ;
  5433              if (!(key  in data))  size++;
  5434              data[key]  = value;
  5435  
  5436              if (size >  capacity)  {
  5437                this.rem ove(staleE nd.key);
  5438              }
  5439  
  5440              return val ue;
  5441           },
  5442  
  5443           /* *
  5444            *  @ngdoc me thod
  5445            *  @name $ca cheFactory .Cache#get
  5446            *  @kind fun ction
  5447            *
  5448            *  @descript ion
  5449            *  Retrieves  named dat a stored i n the {@li nk $cacheF actory.Cac he Cache}  object.
  5450            *
  5451            *  @param {s tring} key  the key o f the data  to be ret rieved
  5452            *  @returns  {*} the va lue stored .
  5453            * /
  5454           ge t: functio n(key) {
  5455              if (capaci ty < Numbe r.MAX_VALU E) {
  5456                var lruE ntry = lru Hash[key];
  5457  
  5458                if (!lru Entry) ret urn;
  5459  
  5460                refresh( lruEntry);
  5461              }
  5462  
  5463              return dat a[key];
  5464           },
  5465  
  5466  
  5467           /* *
  5468            *  @ngdoc me thod
  5469            *  @name $ca cheFactory .Cache#rem ove
  5470            *  @kind fun ction
  5471            *
  5472            *  @descript ion
  5473            *  Removes a n entry fr om the {@l ink $cache Factory.Ca che Cache}  object.
  5474            *
  5475            *  @param {s tring} key  the key o f the entr y to be re moved
  5476            * /
  5477           re move: func tion(key)  {
  5478              if (capaci ty < Numbe r.MAX_VALU E) {
  5479                var lruE ntry = lru Hash[key];
  5480  
  5481                if (!lru Entry) ret urn;
  5482  
  5483                if (lruE ntry == fr eshEnd) fr eshEnd = l ruEntry.p;
  5484                if (lruE ntry == st aleEnd) st aleEnd = l ruEntry.n;
  5485                link(lru Entry.n,lr uEntry.p);
  5486  
  5487                delete l ruHash[key ];
  5488              }
  5489  
  5490              delete dat a[key];
  5491              size--;
  5492           },
  5493  
  5494  
  5495           /* *
  5496            *  @ngdoc me thod
  5497            *  @name $ca cheFactory .Cache#rem oveAll
  5498            *  @kind fun ction
  5499            *
  5500            *  @descript ion
  5501            *  Clears th e cache ob ject of an y entries.
  5502            * /
  5503           re moveAll: f unction()  {
  5504              data = {};
  5505              size = 0;
  5506              lruHash =  {};
  5507              freshEnd =  staleEnd  = null;
  5508           },
  5509  
  5510  
  5511           /* *
  5512            *  @ngdoc me thod
  5513            *  @name $ca cheFactory .Cache#des troy
  5514            *  @kind fun ction
  5515            *
  5516            *  @descript ion
  5517            *  Destroys  the {@link  $cacheFac tory.Cache  Cache} ob ject entir ely,
  5518            *  removing  it from th e {@link $ cacheFacto ry $cacheF actory} se t.
  5519            * /
  5520           de stroy: fun ction() {
  5521              data = nul l;
  5522              stats = nu ll;
  5523              lruHash =  null;
  5524              delete cac hes[cacheI d];
  5525           },
  5526  
  5527  
  5528           /* *
  5529            *  @ngdoc me thod
  5530            *  @name $ca cheFactory .Cache#inf o
  5531            *  @kind fun ction
  5532            *
  5533            *  @descript ion
  5534            *  Retrieve  informatio n regardin g a partic ular {@lin k $cacheFa ctory.Cach e Cache}.
  5535            *
  5536            *  @returns  {object} a n object w ith the fo llowing pr operties:
  5537            *    <ul>
  5538            *      <li>* *id**: the  id of the  cache ins tance</li>
  5539            *      <li>* *size**: t he number  of entries  kept in t he cache i nstance</l i>
  5540            *      <li>* *...**: an y addition al propert ies from t he options  object wh en creatin g the
  5541            *        cac he.</li>
  5542            *    </ul>
  5543            * /
  5544           in fo: functi on() {
  5545              return ext end({}, st ats, {size : size});
  5546           }
  5547         };
  5548  
  5549  
  5550         /**
  5551          * m akes the ` entry` the  freshEnd  of the LRU  linked li st
  5552          */
  5553         func tion refre sh(entry)  {
  5554           if  (entry !=  freshEnd)  {
  5555              if (!stale End) {
  5556                staleEnd  = entry;
  5557              } else if  (staleEnd  == entry)  {
  5558                staleEnd  = entry.n ;
  5559              }
  5560  
  5561              link(entry .n, entry. p);
  5562              link(entry , freshEnd );
  5563              freshEnd =  entry;
  5564              freshEnd.n  = null;
  5565           }
  5566         }
  5567  
  5568  
  5569         /**
  5570          * b idirection ally links  two entri es of the  LRU linked  list
  5571          */
  5572         func tion link( nextEntry,  prevEntry ) {
  5573           if  (nextEntr y != prevE ntry) {
  5574              if (nextEn try) nextE ntry.p = p revEntry;  //p stands  for previ ous, 'prev ' didn't m inify
  5575              if (prevEn try) prevE ntry.n = n extEntry;  //n stands  for next,  'next' di dn't minif y
  5576           }
  5577         }
  5578       }
  5579  
  5580  
  5581     /**
  5582      * @ngdo c method
  5583      * @name  $cacheFac tory#info
  5584      *
  5585      * @desc ription
  5586      * Get i nformation  about all  the cache s that hav e been cre ated
  5587      *
  5588      * @retu rns {Objec t} - key-v alue map o f `cacheId ` to the r esult of c alling `ca che#info`
  5589      */
  5590       cacheF actory.inf o = functi on() {
  5591         var  info = {};
  5592         forE ach(caches , function (cache, ca cheId) {
  5593           in fo[cacheId ] = cache. info();
  5594         });
  5595         retu rn info;
  5596       };
  5597  
  5598  
  5599     /**
  5600      * @ngdo c method
  5601      * @name  $cacheFac tory#get
  5602      *
  5603      * @desc ription
  5604      * Get a ccess to a  cache obj ect by the  `cacheId`  used when  it was cr eated.
  5605      *
  5606      * @para m {string}  cacheId N ame or id  of a cache  to access .
  5607      * @retu rns {objec t} Cache o bject iden tified by  the cacheI d or undef ined if no  such cach e.
  5608      */
  5609       cacheF actory.get  = functio n(cacheId)  {
  5610         retu rn caches[ cacheId];
  5611       };
  5612  
  5613  
  5614       return  cacheFact ory;
  5615     };
  5616   }
  5617  
  5618   /**
  5619    * @ngdoc  service
  5620    * @name $ templateCa che
  5621    *
  5622    * @descri ption
  5623    * The fir st time a  template i s used, it  is loaded  in the te mplate cac he for qui ck retriev al. You
  5624    * can loa d template s directly  into the  cache in a  `script`  tag, or by  consuming  the
  5625    * `$templ ateCache`  service di rectly.
  5626    *
  5627    * Adding  via the `s cript` tag :
  5628    *
  5629    * ```html
  5630    *   <scri pt type="t ext/ng-tem plate" id= "templateI d.html">
  5631    *     <p> This is th e content  of the tem plate</p>
  5632    *   </scr ipt>
  5633    * ```
  5634    *
  5635    * **Note: ** the `sc ript` tag  containing  the templ ate does n ot need to  be includ ed in the  `head` of
  5636    * the doc ument, but  it must b e a descen dent of th e {@link n g.$rootEle ment $root Element} ( IE,
  5637    * element  with ng-a pp attribu te), other wise the t emplate wi ll be igno red.
  5638    *
  5639    * Adding  via the $t emplateCac he service :
  5640    *
  5641    * ```js
  5642    * var myA pp = angul ar.module( 'myApp', [ ]);
  5643    * myApp.r un(functio n($templat eCache) {
  5644    *   $temp lateCache. put('templ ateId.html ', 'This i s the cont ent of the  template' );
  5645    * });
  5646    * ```
  5647    *
  5648    * To retr ieve the t emplate la ter, simpl y use it i n your HTM L:
  5649    * ```html
  5650    * <div ng -include="  'template Id.html' " ></div>
  5651    * ```
  5652    *
  5653    * or get  it via Jav ascript:
  5654    * ```js
  5655    * $templa teCache.ge t('templat eId.html')
  5656    * ```
  5657    *
  5658    * See {@l ink ng.$ca cheFactory  $cacheFac tory}.
  5659    *
  5660    */
  5661   function $ TemplateCa cheProvide r() {
  5662     this.$ge t = ['$cac heFactory' , function ($cacheFac tory) {
  5663       return  $cacheFac tory('temp lates');
  5664     }];
  5665   }
  5666  
  5667   /* ! VARIA BLE/FUNCTI ON NAMING  CONVENTION S THAT APP LY TO THIS  FILE!
  5668    *
  5669    * DOM-rel ated varia bles:
  5670    *
  5671    * - "node " - DOM No de
  5672    * - "elem ent" - DOM  Element o r Node
  5673    * - "$nod e" or "$el ement" - j qLite-wrap ped node o r element
  5674    *
  5675    *
  5676    * Compile r related  stuff:
  5677    *
  5678    * - "link Fn" - link ing fn of  a single d irective
  5679    * - "node LinkFn" -  function t hat aggreg ates all l inking fns  for a par ticular no de
  5680    * - "chil dLinkFn" -   function  that aggr egates all  linking f ns for chi ld nodes o f a partic ular node
  5681    * - "comp ositeLinkF n" - funct ion that a ggregates  all linkin g fns for  a compilat ion root ( nodeList)
  5682    */
  5683  
  5684  
  5685   /**
  5686    * @ngdoc  service
  5687    * @name $ compile
  5688    * @kind f unction
  5689    *
  5690    * @descri ption
  5691    * Compile s an HTML  string or  DOM into a  template  and produc es a templ ate functi on, which
  5692    * can the n be used  to link {@ link ng.$r ootScope.S cope `scop e`} and th e template  together.
  5693    *
  5694    * The com pilation i s a proces s of walki ng the DOM  tree and  matching D OM element s to
  5695    * {@link  ng.$compil eProvider# directive  directives }.
  5696    *
  5697    * <div cl ass="alert  alert-war ning">
  5698    * **Note: ** This do cument is  an in-dept h referenc e of all d irective o ptions.
  5699    * For a g entle intr oduction t o directiv es with ex amples of  common use  cases,
  5700    * see the  {@link gu ide/direct ive direct ive guide} .
  5701    * </div>
  5702    *
  5703    * ## Comp rehensive  Directive  API
  5704    *
  5705    * There a re many di fferent op tions for  a directiv e.
  5706    *
  5707    * The dif ference re sides in t he return  value of t he factory  function.
  5708    * You can  either re turn a "Di rective De finition O bject" (se e below) t hat define s the dire ctive prop erties,
  5709    * or just  the `post Link` func tion (all  other prop erties wil l have the  default v alues).
  5710    *
  5711    * <div cl ass="alert  alert-suc cess">
  5712    * **Best  Practice:* * It's rec ommended t o use the  "directive  definitio n object"  form.
  5713    * </div>
  5714    *
  5715    * Here's  an example  directive  declared  with a Dir ective Def inition Ob ject:
  5716    *
  5717    * ```js
  5718    *   var m yModule =  angular.mo dule(...);
  5719    *
  5720    *   myMod ule.direct ive('direc tiveName',  function  factory(in jectables)  {
  5721    *     var  directive Definition Object = {
  5722    *       p riority: 0 ,
  5723    *       t emplate: ' <div></div >', // or  // functio n(tElement , tAttrs)  { ... },
  5724    *       / / or
  5725    *       / / template Url: 'dire ctive.html ', // or / / function (tElement,  tAttrs) {  ... },
  5726    *       t ransclude:  false,
  5727    *       r estrict: ' A',
  5728    *       t emplateNam espace: 'h tml',
  5729    *       s cope: fals e,
  5730    *       c ontroller:  function( $scope, $e lement, $a ttrs, $tra nsclude, o therInject ables) { . .. },
  5731    *       c ontrollerA s: 'string Alias',
  5732    *       r equire: 's iblingDire ctiveName' , // or //  ['^parent DirectiveN ame', '?op tionalDire ctiveName' , '?^optio nalParent' ],
  5733    *       c ompile: fu nction com pile(tElem ent, tAttr s, transcl ude) {
  5734    *          return {
  5735    *            pre: fu nction pre Link(scope , iElement , iAttrs,  controller ) { ... },
  5736    *            post: f unction po stLink(sco pe, iEleme nt, iAttrs , controll er) { ...  }
  5737    *          }
  5738    *          // or
  5739    *          // return  function  postLink(  ... ) { .. . }
  5740    *       } ,
  5741    *       / / or
  5742    *       / / link: {
  5743    *       / /  pre: fu nction pre Link(scope , iElement , iAttrs,  controller ) { ... },
  5744    *       / /  post: f unction po stLink(sco pe, iEleme nt, iAttrs , controll er) { ...  }
  5745    *       / / }
  5746    *       / / or
  5747    *       / / link: fu nction pos tLink( ...  ) { ... }
  5748    *     };
  5749    *     ret urn direct iveDefinit ionObject;
  5750    *   });
  5751    * ```
  5752    *
  5753    * <div cl ass="alert  alert-war ning">
  5754    * **Note: ** Any uns pecified o ptions wil l use the  default va lue. You c an see the  default v alues belo w.
  5755    * </div>
  5756    *
  5757    * Therefo re the abo ve can be  simplified  as:
  5758    *
  5759    * ```js
  5760    *   var m yModule =  angular.mo dule(...);
  5761    *
  5762    *   myMod ule.direct ive('direc tiveName',  function  factory(in jectables)  {
  5763    *     var  directive Definition Object = {
  5764    *       l ink: funct ion postLi nk(scope,  iElement,  iAttrs) {  ... }
  5765    *     };
  5766    *     ret urn direct iveDefinit ionObject;
  5767    *     //  or
  5768    *     //  return fun ction post Link(scope , iElement , iAttrs)  { ... }
  5769    *   });
  5770    * ```
  5771    *
  5772    *
  5773    *
  5774    * ### Dir ective Def inition Ob ject
  5775    *
  5776    * The dir ective def inition ob ject provi des instru ctions to  the {@link  ng.$compi le
  5777    * compile r}. The at tributes a re:
  5778    *
  5779    * #### `m ultiElemen t`
  5780    * When th is propert y is set t o true, th e HTML com piler will  collect D OM nodes b etween
  5781    * nodes w ith the at tributes ` directive- name-start ` and `dir ective-nam e-end`, an d group th em
  5782    * togethe r as the d irective e lements. I t is recom ended that  this feat ure be use d on direc tives
  5783    * which a re not str ictly beha vioural (s uch as {@l ink ngClic k}), and w hich
  5784    * do not  manipulate  or replac e child no des (such  as {@link  ngInclude} ).
  5785    *
  5786    * #### `p riority`
  5787    * When th ere are mu ltiple dir ectives de fined on a  single DO M element,  sometimes  it
  5788    * is nece ssary to s pecify the  order in  which the  directives  are appli ed. The `p riority` i s used
  5789    * to sort  the direc tives befo re their ` compile` f unctions g et called.  Priority  is defined  as a
  5790    * number.  Directive s with gre ater numer ical `prio rity` are  compiled f irst. Pre- link funct ions
  5791    * are als o run in p riority or der, but p ost-link f unctions a re run in  reverse or der. The o rder
  5792    * of dire ctives wit h the same  priority  is undefin ed. The de fault prio rity is `0 `.
  5793    *
  5794    * #### `t erminal`
  5795    * If set  to true th en the cur rent `prio rity` will  be the la st set of  directives
  5796    * which w ill execut e (any dir ectives at  the curre nt priorit y will sti ll execute
  5797    * as the  order of e xecution o n same `pr iority` is  undefined ). Note th at express ions
  5798    * and oth er directi ves used i n the dire ctive's te mplate wil l also be  excluded f rom execut ion.
  5799    *
  5800    * #### `s cope`
  5801    * **If se t to `true `,** then  a new scop e will be  created fo r this dir ective. If  multiple  directives  on the
  5802    * same el ement requ est a new  scope, onl y one new  scope is c reated. Th e new scop e rule doe s not
  5803    * apply f or the roo t of the t emplate si nce the ro ot of the  template a lways gets  a new sco pe.
  5804    *
  5805    * **If se t to `{}`  (object ha sh),** the n a new "i solate" sc ope is cre ated. The  'isolate'  scope diff ers from
  5806    * normal  scope in t hat it doe s not prot otypically  inherit f rom the pa rent scope . This is  useful
  5807    * when cr eating reu sable comp onents, wh ich should  not accid entally re ad or modi fy data in  the
  5808    * parent  scope.
  5809    *
  5810    * The 'is olate' sco pe takes a n object h ash which  defines a  set of loc al scope p roperties
  5811    * derived  from the  parent sco pe. These  local prop erties are  useful fo r aliasing  values fo r
  5812    * templat es. Locals  definitio n is a has h of local  scope pro perty to i ts source:
  5813    *
  5814    * * `@` o r `@attr`  - bind a l ocal scope  property  to the val ue of DOM  attribute.  The resul t is
  5815    *   alway s a string  since DOM  attribute s are stri ngs. If no  `attr` na me is spec ified  the n the
  5816    *   attri bute name  is assumed  to be the  same as t he local n ame.
  5817    *   Given  `<widget  my-attr="h ello {{nam e}}">` and  widget de finition
  5818    *   of `s cope: { lo calName:'@ myAttr' }` , then wid get scope  property ` localName`  will refl ect
  5819    *   the i nterpolate d value of  `hello {{ name}}`. A s the `nam e` attribu te changes  so will t he
  5820    *   `loca lName` pro perty on t he widget  scope. The  `name` is  read from  the paren t scope (n ot
  5821    *   compo nent scope ).
  5822    *
  5823    * * `=` o r `=attr`  - set up b i-directio nal bindin g between  a local sc ope proper ty and the
  5824    *   paren t scope pr operty of  name defin ed via the  value of  the `attr`  attribute . If no `a ttr`
  5825    *   name  is specifi ed then th e attribut e name is  assumed to  be the sa me as the  local name .
  5826    *   Given  `<widget  my-attr="p arentModel ">` and wi dget defin ition of
  5827    *   `scop e: { local Model:'=my Attr' }`,  then widge t scope pr operty `lo calModel`  will refle ct the
  5828    *   value  of `paren tModel` on  the paren t scope. A ny changes  to `paren tModel` wi ll be refl ected
  5829    *   in `l ocalModel`  and any c hanges in  `localMode l` will re flect in ` parentMode l`. If the  parent
  5830    *   scope  property  doesn't ex ist, it wi ll throw a  NON_ASSIG NABLE_MODE L_EXPRESSI ON excepti on. You
  5831    *   can a void this  behavior u sing `=?`  or `=?attr ` in order  to flag t he propert y as optio nal. If
  5832    *   you w ant to sha llow watch  for chang es (i.e. $ watchColle ction inst ead of $wa tch) you c an use
  5833    *   `=*`  or `=*attr ` (`=*?` o r `=*?attr ` if the p roperty is  optional) .
  5834    *
  5835    * * `&` o r `&attr`  - provides  a way to  execute an  expressio n in the c ontext of  the parent  scope.
  5836    *   If no  `attr` na me is spec ified then  the attri bute name  is assumed  to be the  same as t he
  5837    *   local  name. Giv en `<widge t my-attr= "count = c ount + val ue">` and  widget def inition of
  5838    *   `scop e: { local Fn:'&myAtt r' }`, the n isolate  scope prop erty `loca lFn` will  point to
  5839    *   a fun ction wrap per for th e `count =  count + v alue` expr ession. Of ten it's d esirable t o
  5840    *   pass  data from  the isolat ed scope v ia an expr ession to  the parent  scope, th is can be
  5841    *   done  by passing  a map of  local vari able names  and value s into the  expressio n wrapper  fn.
  5842    *   For e xample, if  the expre ssion is ` increment( amount)` t hen we can  specify t he amount  value
  5843    *   by ca lling the  `localFn`  as `localF n({amount:  22})`.
  5844    *
  5845    *
  5846    * #### `b indToContr oller`
  5847    * When an  isolate s cope is us ed for a c omponent ( see above) , and `con trollerAs`  is used,  `bindToCon troller: t rue` will
  5848    * allow a  component  to have i ts propert ies bound  to the con troller, r ather than  to scope.  When the  controller
  5849    * is inst antiated,  the initia l values o f the isol ate scope  bindings a re already  available .
  5850    *
  5851    * #### `c ontroller`
  5852    * Control ler constr uctor func tion. The  controller  is instan tiated bef ore the
  5853    * pre-lin king phase  and it is  shared wi th other d irectives  (see
  5854    * `requir e` attribu te). This  allows the  directive s to commu nicate wit h each oth er and aug ment
  5855    * each ot her's beha vior. The  controller  is inject able (and  supports b racket not ation) wit h the foll owing loca ls:
  5856    *
  5857    * * `$sco pe` - Curr ent scope  associated  with the  element
  5858    * * `$ele ment` - Cu rrent elem ent
  5859    * * `$att rs` - Curr ent attrib utes objec t for the  element
  5860    * * `$tra nsclude` -  A transcl ude linkin g function  pre-bound  to the co rrect tran sclusion s cope:
  5861    *   `func tion([scop e], cloneL inkingFn,  futurePare ntElement) `.
  5862    *    * `s cope`: opt ional argu ment to ov erride the  scope.
  5863    *    * `c loneLinkin gFn`: opti onal argum ent to cre ate clones  of the or iginal tra nscluded c ontent.
  5864    *    * `f utureParen tElement`:
  5865    *         * defines  the parent  to which  the `clone LinkingFn`  will add  the cloned  elements.
  5866    *         * default:  `$element .parent()`  resp. `$e lement` fo r `transcl ude:'eleme nt'` resp.  `transclu de:true`.
  5867    *         * only nee ded for tr anscludes  that are a llowed to  contain no n html ele ments (e.g . SVG elem ents)
  5868    *           and when  the `clon eLinkinFn`  is passed ,
  5869    *           as those  elements  need to cr eated and  cloned in  a special  way when t hey are de fined outs ide their
  5870    *           usual co ntainers ( e.g. like  `<svg>`).
  5871    *         * See also  the `dire ctive.temp lateNamesp ace` prope rty.
  5872    *
  5873    *
  5874    * #### `r equire`
  5875    * Require  another d irective a nd inject  its contro ller as th e fourth a rgument to  the linki ng functio n. The
  5876    * `requir e` takes a  string na me (or arr ay of stri ngs) of th e directiv e(s) to pa ss in. If  an array i s used, th e
  5877    * injecte d argument  will be a n array in  correspon ding order . If no su ch directi ve can be
  5878    * found,  or if the  directive  does not h ave a cont roller, th en an erro r is raise d. The nam e can be p refixed wi th:
  5879    *
  5880    * * (no p refix) - L ocate the  required c ontroller  on the cur rent eleme nt. Throw  an error i f not foun d.
  5881    * * `?` -  Attempt t o locate t he require d controll er or pass  `null` to  the `link ` fn if no t found.
  5882    * * `^` -  Locate th e required  controlle r by searc hing the e lement and  its paren ts. Throw  an error i f not foun d.
  5883    * * `^^`  - Locate t he require d controll er by sear ching the  element's  parents. T hrow an er ror if not  found.
  5884    * * `?^`  - Attempt  to locate  the requir ed control ler by sea rching the  element a nd its par ents or pa ss
  5885    *   `null ` to the ` link` fn i f not foun d.
  5886    * * `?^^`  - Attempt  to locate  the requi red contro ller by se arching th e element' s parents,  or pass
  5887    *   `null ` to the ` link` fn i f not foun d.
  5888    *
  5889    *
  5890    * #### `c ontrollerA s`
  5891    * Control ler alias  at the dir ective sco pe. An ali as for the  controlle r so it
  5892    * can be  referenced  at the di rective te mplate. Th e directiv e needs to  define a  scope for  this
  5893    * configu ration to  be used. U seful in t he case wh en directi ve is used  as compon ent.
  5894    *
  5895    *
  5896    * #### `r estrict`
  5897    * String  of subset  of `EACM`  which rest ricts the  directive  to a speci fic direct ive
  5898    * declara tion style . If omitt ed, the de faults (el ements and  attribute s) are use d.
  5899    *
  5900    * * `E` -  Element n ame (defau lt): `<my- directive> </my-direc tive>`
  5901    * * `A` -  Attribute  (default) : `<div my -directive ="exp"></d iv>`
  5902    * * `C` -  Class: `< div class= "my-direct ive: exp;" ></div>`
  5903    * * `M` -  Comment:  `<!-- dire ctive: my- directive  exp -->`
  5904    *
  5905    *
  5906    * #### `t emplateNam espace`
  5907    * String  representi ng the doc ument type  used by t he markup  in the tem plate.
  5908    * Angular JS needs t his inform ation as t hose eleme nts need t o be creat ed and clo ned
  5909    * in a sp ecial way  when they  are define d outside  their usua l containe rs like `< svg>` and  `<math>`.
  5910    *
  5911    * * `html ` - All ro ot nodes i n the temp late are H TML. Root  nodes may  also be
  5912    *   top-l evel eleme nts such a s `<svg>`  or `<math> `.
  5913    * * `svg`  - The roo t nodes in  the templ ate are SV G elements  (excludin g `<math>` ).
  5914    * * `math ` - The ro ot nodes i n the temp late are M athML elem ents (excl uding `<sv g>`).
  5915    *
  5916    * If no ` templateNa mespace` i s specifie d, then th e namespac e is consi dered to b e `html`.
  5917    *
  5918    * #### `t emplate`
  5919    * HTML ma rkup that  may:
  5920    * * Repla ce the con tents of t he directi ve's eleme nt (defaul t).
  5921    * * Repla ce the dir ective's e lement its elf (if `r eplace` is  true - DE PRECATED).
  5922    * * Wrap  the conten ts of the  directive' s element  (if `trans clude` is  true).
  5923    *
  5924    * Value m ay be:
  5925    *
  5926    * * A str ing. For e xample `<d iv red-on- hover>{{de lete_str}} </div>`.
  5927    * * A fun ction whic h takes tw o argument s `tElemen t` and `tA ttrs` (des cribed in  the `compi le`
  5928    *   funct ion api be low) and r eturns a s tring valu e.
  5929    *
  5930    *
  5931    * #### `t emplateUrl `
  5932    * This is  similar t o `templat e` but the  template  is loaded  from the s pecified U RL, asynch ronously.
  5933    *
  5934    * Because  template  loading is  asynchron ous the co mpiler wil l suspend  compilatio n of direc tives on t hat elemen t
  5935    * for lat er when th e template  has been  resolved.   In the me antime it  will conti nue to com pile and l ink
  5936    * sibling  and paren t elements  as though  this elem ent had no t containe d any dire ctives.
  5937    *
  5938    * The com piler does  not suspe nd the ent ire compil ation to w ait for te mplates to  be loaded  because t his
  5939    * would r esult in t he whole a pp "stalli ng" until  all templa tes are lo aded async hronously  - even in  the
  5940    * case wh en only on e deeply n ested dire ctive has  `templateU rl`.
  5941    *
  5942    * Templat e loading  is asynchr onous even  if the te mplate has  been prel oaded into  the {@lin k $templat eCache}
  5943    *
  5944    * You can  specify ` templateUr l` as a st ring repre senting th e URL or a s a functi on which t akes two
  5945    * argumen ts `tEleme nt` and `t Attrs` (de scribed in  the `comp ile` funct ion api be low) and r eturns
  5946    * a strin g value re presenting  the url.   In either  case, the  template  URL is pas sed throug h {@link
  5947    * $sce#ge tTrustedRe sourceUrl  $sce.getTr ustedResou rceUrl}.
  5948    *
  5949    *
  5950    * #### `r eplace` ([ *DEPRECATE D*!], will  be remove d in next  major rele ase - i.e.  v2.0)
  5951    * specify  what the  template s hould repl ace. Defau lts to `fa lse`.
  5952    *
  5953    * * `true ` - the te mplate wil l replace  the direct ive's elem ent.
  5954    * * `fals e` - the t emplate wi ll replace  the conte nts of the  directive 's element .
  5955    *
  5956    * The rep lacement p rocess mig rates all  of the att ributes /  classes fr om the old  element t o the new
  5957    * one. Se e the {@li nk guide/d irective#t emplate-ex panding-di rective
  5958    * Directi ves Guide}  for an ex ample.
  5959    *
  5960    * There a re very fe w scenario s where el ement repl acement is  required  for the ap plication  function,
  5961    * the mai n one bein g reusable  custom co mponents t hat are us ed within  SVG contex ts
  5962    * (becaus e SVG does n't work w ith custom  elements  in the DOM  tree).
  5963    *
  5964    * #### `t ransclude`
  5965    * Extract  the conte nts of the  element w here the d irective a ppears and  make it a vailable t o the dire ctive.
  5966    * The con tents are  compiled a nd provide d to the d irective a s a **tran sclusion f unction**.  See the
  5967    * {@link  $compile#t ransclusio n Transclu sion} sect ion below.
  5968    *
  5969    * There a re two kin ds of tran sclusion d epending u pon whethe r you want  to transc lude just  the conten ts of the
  5970    * directi ve's eleme nt or the  entire ele ment:
  5971    *
  5972    * * `true ` - transc lude the c ontent (i. e. the chi ld nodes)  of the dir ective's e lement.
  5973    * * `'ele ment'` - t ransclude  the whole  of the dir ective's e lement inc luding any  directive s on this
  5974    *   eleme nt that de fined at a  lower pri ority than  this dire ctive. Whe n used, th e `templat e`
  5975    *   prope rty is ign ored.
  5976    *
  5977    *
  5978    * #### `c ompile`
  5979    *
  5980    * ```js
  5981    *   funct ion compil e(tElement , tAttrs,  transclude ) { ... }
  5982    * ```
  5983    *
  5984    * The com pile funct ion deals  with trans forming th e template  DOM. Sinc e most dir ectives do  not do
  5985    * templat e transfor mation, it  is not us ed often.  The compil e function  takes the  following  arguments :
  5986    *
  5987    *   * `tE lement` -  template e lement - T he element  where the  directive  has been  declared.  It is
  5988    *     saf e to do te mplate tra nsformatio n on the e lement and  child ele ments only .
  5989    *
  5990    *   * `tA ttrs` - te mplate att ributes -  Normalized  list of a ttributes  declared o n this ele ment share d
  5991    *     bet ween all d irective c ompile fun ctions.
  5992    *
  5993    *   * `tr ansclude`  -  [*DEPRE CATED*!] A  transclud e linking  function:  `function( scope, clo neLinkingF n)`
  5994    *
  5995    * <div cl ass="alert  alert-war ning">
  5996    * **Note: ** The tem plate inst ance and t he link in stance may  be differ ent object s if the t emplate ha s
  5997    * been cl oned. For  this reaso n it is ** not** safe  to do any thing othe r than DOM  transform ations tha t
  5998    * apply t o all clon ed DOM nod es within  the compil e function . Specific ally, DOM  listener r egistratio n
  5999    * should  be done in  a linking  function  rather tha n in a com pile funct ion.
  6000    * </div>
  6001  
  6002    * <div cl ass="alert  alert-war ning">
  6003    * **Note: ** The com pile funct ion cannot  handle di rectives t hat recurs ively use  themselves  in their
  6004    * own tem plates or  compile fu nctions. C ompiling t hese direc tives resu lts in an  infinite l oop and a
  6005    * stack o verflow er rors.
  6006    *
  6007    * This ca n be avoid ed by manu ally using  $compile  in the pos tLink func tion to im peratively  compile
  6008    * a direc tive's tem plate inst ead of rel ying on au tomatic te mplate com pilation v ia `templa te` or
  6009    * `templa teUrl` dec laration o r manual c ompilation  inside th e compile  function.
  6010    * </div>
  6011    *
  6012    * <div cl ass="alert  alert-err or">
  6013    * **Note: ** The `tr ansclude`  function t hat is pas sed to the  compile f unction is  deprecate d, as it
  6014    *   e.g.  does not k now about  the right  outer scop e. Please  use the tr ansclude f unction th at is pass ed
  6015    *   to th e link fun ction inst ead.
  6016    * </div>
  6017  
  6018    * A compi le functio n can have  a return  value whic h can be e ither a fu nction or  an object.
  6019    *
  6020    * * retur ning a (po st-link) f unction -  is equival ent to reg istering t he linking  function  via the
  6021    *   `link ` property  of the co nfig objec t when the  compile f unction is  empty.
  6022    *
  6023    * * retur ning an ob ject with  function(s ) register ed via `pr e` and `po st` proper ties - all ows you to
  6024    *   contr ol when a  linking fu nction sho uld be cal led during  the linki ng phase.  See info a bout
  6025    *   pre-l inking and  post-link ing functi ons below.
  6026    *
  6027    *
  6028    * #### `l ink`
  6029    * This pr operty is  used only  if the `co mpile` pro perty is n ot defined .
  6030    *
  6031    * ```js
  6032    *   funct ion link(s cope, iEle ment, iAtt rs, contro ller, tran scludeFn)  { ... }
  6033    * ```
  6034    *
  6035    * The lin k function  is respon sible for  registerin g DOM list eners as w ell as upd ating the  DOM. It is
  6036    * execute d after th e template  has been  cloned. Th is is wher e most of  the direct ive logic  will be
  6037    * put.
  6038    *
  6039    *   * `sc ope` - {@l ink ng.$ro otScope.Sc ope Scope}  - The sco pe to be u sed by the
  6040    *     dir ective for  registeri ng {@link  ng.$rootSc ope.Scope# $watch wat ches}.
  6041    *
  6042    *   * `iE lement` -  instance e lement - T he element  where the  directive  is to be  used. It i s safe to
  6043    *     man ipulate th e children  of the el ement only  in `postL ink` funct ion since  the childr en have
  6044    *     alr eady been  linked.
  6045    *
  6046    *   * `iA ttrs` - in stance att ributes -  Normalized  list of a ttributes  declared o n this ele ment share d
  6047    *     bet ween all d irective l inking fun ctions.
  6048    *
  6049    *   * `co ntroller`  - a contro ller insta nce - A co ntroller i nstance if  at least  one direct ive on the
  6050    *     ele ment defin es a contr oller. The  controlle r is share d among al l the dire ctives, wh ich allows
  6051    *     the  directive s to use t he control lers as a  communicat ion channe l.
  6052    *
  6053    *   * `tr anscludeFn ` - A tran sclude lin king funct ion pre-bo und to the  correct t ransclusio n scope.
  6054    *     Thi s is the s ame as the  `$transcl ude`
  6055    *     par ameter of  directive  controller s, see the re for det ails.
  6056    *     `fu nction([sc ope], clon eLinkingFn , futurePa rentElemen t)`.
  6057    *
  6058    * #### Pr e-linking  function
  6059    *
  6060    * Execute d before t he child e lements ar e linked.  Not safe t o do DOM t ransformat ion since  the
  6061    * compile r linking  function w ill fail t o locate t he correct  elements  for linkin g.
  6062    *
  6063    * #### Po st-linking  function
  6064    *
  6065    * Execute d after th e child el ements are  linked.
  6066    *
  6067    * Note th at child e lements th at contain  `template Url` direc tives will  not have  been compi led
  6068    * and lin ked since  they are w aiting for  their tem plate to l oad asynch ronously a nd their o wn
  6069    * compila tion and l inking has  been susp ended unti l that occ urs.
  6070    *
  6071    * It is s afe to do  DOM transf ormation i n the post -linking f unction on  elements  that are n ot waiting
  6072    * for the ir async t emplates t o be resol ved.
  6073    *
  6074    *
  6075    * ### Tra nsclusion
  6076    *
  6077    * Transcl usion is t he process  of extrac ting a col lection of  DOM eleme nt from on e part of  the DOM an d
  6078    * copying  them to a nother par t of the D OM, while  maintainin g their co nnection t o the orig inal Angul arJS
  6079    * scope f rom where  they were  taken.
  6080    *
  6081    * Transcl usion is u sed (often  with {@li nk ngTrans clude}) to  insert th e
  6082    * origina l contents  of a dire ctive's el ement into  a specifi ed place i n the temp late of th e directiv e.
  6083    * The ben efit of tr ansclusion , over sim ply moving  the DOM e lements ma nually, is  that the  transclude d
  6084    * content  has acces s to the p roperties  on the sco pe from wh ich it was  taken, ev en if the  directive
  6085    * has iso lated scop e.
  6086    * See the  {@link gu ide/direct ive#creati ng-a-direc tive-that- wraps-othe r-elements  Directive s Guide}.
  6087    *
  6088    * This ma kes it pos sible for  the widget  to have p rivate sta te for its  template,  while the  transclud ed
  6089    * content  has acces s to its o riginating  scope.
  6090    *
  6091    * <div cl ass="alert  alert-war ning">
  6092    * **Note: ** When te sting an e lement tra nsclude di rective yo u must not  place the  directive  at the ro ot of the
  6093    * DOM fra gment that  is being  compiled.  See {@link  guide/uni t-testing# testing-tr ansclusion -directive s
  6094    * Testing  Transclus ion Direct ives}.
  6095    * </div>
  6096    *
  6097    * #### Tr ansclusion  Functions
  6098    *
  6099    * When a  directive  requests t ransclusio n, the com piler extr acts its c ontents an d provides  a **trans clusion
  6100    * functio n** to the  directive 's `link`  function a nd `contro ller`. Thi s transclu sion funct ion is a s pecial
  6101    * **linki ng functio n** that w ill return  the compi led conten ts linked  to a new t ransclusio n scope.
  6102    *
  6103    * <div cl ass="alert  alert-inf o">
  6104    * If you  are just u sing {@lin k ngTransc lude} then  you don't  need to w orry about  this func tion, sinc e
  6105    * ngTrans clude will  deal with  it for us .
  6106    * </div>
  6107    *
  6108    * If you  want to ma nually con trol the i nsertion a nd removal  of the tr anscluded  content in  your dire ctive
  6109    * then yo u must use  this tran sclude fun ction. Whe n you call  a transcl ude functi on it retu rns a a jq Lite/JQuer y
  6110    * object  that conta ins the co mpiled DOM , which is  linked to  the corre ct transcl usion scop e.
  6111    *
  6112    * When yo u call a t ransclusio n function  you can p ass in a * *clone att ach functi on**. This  function  accepts
  6113    * two par ameters, ` function(c lone, scop e) { ... } `, where t he `clone`  is a fres h compiled  copy of y our transc luded
  6114    * content  and the ` scope` is  the newly  created tr ansclusion  scope, to  which the  clone is  bound.
  6115    *
  6116    * <div cl ass="alert  alert-inf o">
  6117    * **Best  Practice** : Always p rovide a ` cloneFn` ( clone atta ch functio n) when yo u call a t ranslude f unction
  6118    * since y ou then ge t a fresh  clone of t he origina l DOM and  also have  access to  the new tr ansclusion  scope.
  6119    * </div>
  6120    *
  6121    * It is n ormal prac tice to at tach your  transclude d content  (`clone`)  to the DOM  inside yo ur **clone
  6122    * attach  function** :
  6123    *
  6124    * ```js
  6125    * var tra nscludedCo ntent, tra nsclusionS cope;
  6126    *
  6127    * $transc lude(funct ion(clone,  scope) {
  6128    *   eleme nt.append( clone);
  6129    *   trans cludedCont ent = clon e;
  6130    *   trans clusionSco pe = scope ;
  6131    * });
  6132    * ```
  6133    *
  6134    * Later,  if you wan t to remov e the tran scluded co ntent from  your DOM  then you s hould also  destroy t he
  6135    * associa ted transc lusion sco pe:
  6136    *
  6137    * ```js
  6138    * transcl udedConten t.remove() ;
  6139    * transcl usionScope .$destroy( );
  6140    * ```
  6141    *
  6142    * <div cl ass="alert  alert-inf o">
  6143    * **Best  Practice** : if you i ntend to a dd and rem ove transc luded cont ent manual ly in your  directive
  6144    * (by cal ling the t ransclude  function t o get the  DOM and an d calling  `element.r emove()` t o remove i t),
  6145    * then yo u are also  responsib le for cal ling `$des troy` on t he transcl usion scop e.
  6146    * </div>
  6147    *
  6148    * The bui lt-in DOM  manipulati on directi ves, such  as {@link  ngIf}, {@l ink ngSwit ch} and {@ link ngRep eat}
  6149    * automat ically des troy their  translude d clones a s necessar y so you d o not need  to worry  about this  if
  6150    * you are  simply us ing {@link  ngTranscl ude} to in ject the t ransclusio n into you r directiv e.
  6151    *
  6152    *
  6153    * #### Tr ansclusion  Scopes
  6154    *
  6155    * When yo u call a t ransclude  function i t returns  a DOM frag ment that  is pre-bou nd to a ** transclusi on
  6156    * scope** . This sco pe is spec ial, in th at it is a  child of  the direct ive's scop e (and so  gets destr oyed
  6157    * when th e directiv e's scope  gets destr oyed) but  it inherit s the prop erties of  the scope  from which  it
  6158    * was tak en.
  6159    *
  6160    * For exa mple consi der a dire ctive that  uses tran sclusion a nd isolate d scope. T he DOM hie rarchy mig ht look
  6161    * like th is:
  6162    *
  6163    * ```html
  6164    * <div ng -app>
  6165    *   <div  isolate>
  6166    *     <di v transclu sion>
  6167    *     </d iv>
  6168    *   </div >
  6169    * </div>
  6170    * ```
  6171    *
  6172    * The `$p arent` sco pe hierarc hy will lo ok like th is:
  6173    *
  6174    * ```
  6175    * - $root Scope
  6176    *   - iso late
  6177    *     - t ransclusio n
  6178    * ```
  6179    *
  6180    * but the  scopes wi ll inherit  prototypi cally from  different  scopes to  their `$p arent`.
  6181    *
  6182    * ```
  6183    * - $root Scope
  6184    *   - tra nsclusion
  6185    * - isola te
  6186    * ```
  6187    *
  6188    *
  6189    * ### Att ributes
  6190    *
  6191    * The {@l ink ng.$co mpile.dire ctive.Attr ibutes Att ributes} o bject - pa ssed as a  parameter  in the
  6192    * `link() ` or `comp ile()` fun ctions. It  has a var iety of us es.
  6193    *
  6194    * accessi ng *Normal ized attri bute names :*
  6195    * Directi ves like ' ngBind' ca n be expre ssed in ma ny ways: ' ng:bind',  `data-ng-b ind`, or ' x-ng-bind' .
  6196    * the att ributes ob ject allow s for norm alized acc ess to
  6197    *   the a ttributes.
  6198    *
  6199    * * *Dire ctive inte r-communic ation:* Al l directiv es share t he same in stance of  the attrib utes
  6200    *   objec t which al lows the d irectives  to use the  attribute s object a s inter di rective
  6201    *   commu nication.
  6202    *
  6203    * * *Supp orts inter polation:*  Interpola tion attri butes are  assigned t o the attr ibute obje ct
  6204    *   allow ing other  directives  to read t he interpo lated valu e.
  6205    *
  6206    * * *Obse rving inte rpolated a ttributes: * Use `$ob serve` to  observe th e value ch anges of a ttributes
  6207    *   that  contain in terpolatio n (e.g. `s rc="{{bar} }"`). Not  only is th is very ef ficient bu t it's als o
  6208    *   the o nly way to  easily ge t the actu al value b ecause dur ing the li nking phas e the inte rpolation
  6209    *   hasn' t been eva luated yet  and so th e value is  at this t ime set to  `undefine d`.
  6210    *
  6211    * ```js
  6212    * functio n linkingF n(scope, e lm, attrs,  ctrl) {
  6213    *   // ge t the attr ibute valu e
  6214    *   conso le.log(att rs.ngModel );
  6215    *
  6216    *   // ch ange the a ttribute
  6217    *   attrs .$set('ngM odel', 'ne w value');
  6218    *
  6219    *   // ob serve chan ges to int erpolated  attribute
  6220    *   attrs .$observe( 'ngModel',  function( value) {
  6221    *     con sole.log(' ngModel ha s changed  value to '  + value);
  6222    *   });
  6223    * }
  6224    * ```
  6225    *
  6226    * ## Exam ple
  6227    *
  6228    * <div cl ass="alert  alert-war ning">
  6229    * **Note* *: Typical ly directi ves are re gistered w ith `modul e.directiv e`. The ex ample belo w is
  6230    * to illu strate how  `$compile ` works.
  6231    * </div>
  6232    *
  6233    <example  module="co mpileExamp le">
  6234      <file n ame="index .html">
  6235       <scrip t>
  6236         angu lar.module ('compileE xample', [ ], functio n($compile Provider)  {
  6237           //  configure  new 'comp ile' direc tive by pa ssing a di rective
  6238           //  factory f unction. T he factory  function  injects th e '$compil e'
  6239           $c ompileProv ider.direc tive('comp ile', func tion($comp ile) {
  6240              // directi ve factory  creates a  link func tion
  6241              return fun ction(scop e, element , attrs) {
  6242                scope.$w atch(
  6243                  functi on(scope)  {
  6244                     //  watch the  'compile'  expression  for chang es
  6245                    retu rn scope.$ eval(attrs .compile);
  6246                  },
  6247                  functi on(value)  {
  6248                    // w hen the 'c ompile' ex pression c hanges
  6249                    // a ssign it i nto the cu rrent DOM
  6250                    elem ent.html(v alue);
  6251  
  6252                    // c ompile the  new DOM a nd link it  to the cu rrent
  6253                    // s cope.
  6254                    // N OTE: we on ly compile  .childNod es so that
  6255                    // w e don't ge t into inf inite loop  compiling  ourselves
  6256                    $com pile(eleme nt.content s())(scope );
  6257                  }
  6258                );
  6259              };
  6260           }) ;
  6261         })
  6262         .con troller('G reeterCont roller', [ '$scope',  function($ scope) {
  6263           $s cope.name  = 'Angular ';
  6264           $s cope.html  = 'Hello { {name}}';
  6265         }]);
  6266       </scri pt>
  6267       <div n g-controll er="Greete rControlle r">
  6268         <inp ut ng-mode l="name">  <br>
  6269         <tex tarea ng-m odel="html "></textar ea> <br>
  6270         <div  compile=" html"></di v>
  6271       </div>
  6272      </file>
  6273      <file n ame="protr actor.js"  type="prot ractor">
  6274        it('s hould auto  compile',  function( ) {
  6275          var  textarea  = $('texta rea');
  6276          var  output =  $('div[com pile]');
  6277          //  The initia l state re ads 'Hello  Angular'.
  6278          exp ect(output .getText() ).toBe('He llo Angula r');
  6279          tex tarea.clea r();
  6280          tex tarea.send Keys('{{na me}}!');
  6281          exp ect(output .getText() ).toBe('An gular!');
  6282        });
  6283      </file>
  6284    </example >
  6285  
  6286    *
  6287    *
  6288    * @param  {string|DO MElement}  element El ement or H TML string  to compil e into a t emplate fu nction.
  6289    * @param  {function( angular.Sc ope, clone AttachFn=) } transclu de functio n availabl e to direc tives - DE PRECATED.
  6290    *
  6291    * <div cl ass="alert  alert-err or">
  6292    * **Note: ** Passing  a `transc lude` func tion to th e $compile  function  is depreca ted, as it
  6293    *   e.g.  will not u se the rig ht outer s cope. Plea se pass th e transclu de functio n as a
  6294    *   `pare ntBoundTra nscludeFn`  to the li nk functio n instead.
  6295    * </div>
  6296    *
  6297    * @param  {number} m axPriority  only appl y directiv es lower t han given  priority ( Only effec ts the
  6298    *                  r oot elemen t(s), not  their chil dren)
  6299    * @return s {functio n(scope, c loneAttach Fn=, optio ns=)} a li nk functio n which is  used to b ind templa te
  6300    * (a DOM  element/tr ee) to a s cope. Wher e:
  6301    *
  6302    *  * `sco pe` - A {@ link ng.$r ootScope.S cope Scope } to bind  to.
  6303    *  * `clo neAttachFn ` - If `cl oneAttachF n` is prov ided, then  the link  function w ill clone  the
  6304    *  `templ ate` and c all the `c loneAttach Fn` functi on allowin g the call er to atta ch the
  6305    *  cloned  elements  to the DOM  document  at the app ropriate p lace. The  `cloneAtta chFn` is
  6306    *  called  as: <br>  `cloneAtta chFn(clone dElement,  scope)` wh ere:
  6307    *
  6308    *      *  `clonedEle ment` - is  a clone o f the orig inal `elem ent` passe d into the  compiler.
  6309    *      *  `scope` -  is the cur rent scope  with whic h the link ing functi on is work ing with.
  6310    *
  6311    *  * `opt ions` - An  optional  object has h with lin king optio ns. If `op tions` is  provided,  then the f ollowing
  6312    *  keys m ay be used  to contro l linking  behavior:
  6313    *
  6314    *      *  `parentBou ndTransclu deFn` - th e transclu de functio n made ava ilable to
  6315    *         directives ; if given , it will  be passed  through to  the link  functions  of
  6316    *         directives  found in  `element`  during com pilation.
  6317    *      *  `transclud eControlle rs` - an o bject hash  with keys  that map  controller  names
  6318    *         to control ler instan ces; if gi ven, it wi ll make th e controll ers
  6319    *         available  to directi ves.
  6320    *      *  `futurePar entElement ` - define s the pare nt to whic h the `clo neAttachFn ` will add
  6321    *         the cloned  elements;  only need ed for tra nscludes t hat are al lowed to c ontain non  html
  6322    *         elements ( e.g. SVG e lements).  See also t he directi ve.control ler proper ty.
  6323    *
  6324    * Calling  the linki ng functio n returns  the elemen t of the t emplate. I t is eithe r the orig inal
  6325    * element  passed in , or the c lone of th e element  if the `cl oneAttachF n` is prov ided.
  6326    *
  6327    * After l inking the  view is n ot updated  until aft er a call  to $digest  which typ ically is  done by
  6328    * Angular  automatic ally.
  6329    *
  6330    * If you  need acces s to the b ound view,  there are  two ways  to do it:
  6331    *
  6332    * - If yo u are not  asking the  linking f unction to  clone the  template,  create th e DOM elem ent(s)
  6333    *   befor e you send  them to t he compile r and keep  this refe rence arou nd.
  6334    *   ```js
  6335    *     var  element =  $compile( '<p>{{tota l}}</p>')( scope);
  6336    *   ```
  6337    *
  6338    * - if on  the other  hand, you  need the  element to  be cloned , the view  reference  from the  original
  6339    *   examp le would n ot point t o the clon e, but rat her to the  original  template t hat was cl oned. In
  6340    *   this  case, you  can access  the clone  via the c loneAttach Fn:
  6341    *   ```js
  6342    *     var  templateE lement = a ngular.ele ment('<p>{ {total}}</ p>'),
  6343    *          scope = . ...;
  6344    *
  6345    *     var  clonedEle ment = $co mpile(temp lateElemen t)(scope,  function(c lonedEleme nt, scope)  {
  6346    *       / /attach th e clone to  DOM docum ent at the  right pla ce
  6347    *     });
  6348    *
  6349    *     //n ow we have  reference  to the cl oned DOM v ia `cloned Element`
  6350    *   ```
  6351    *
  6352    *
  6353    * For inf ormation o n how the  compiler w orks, see  the
  6354    * {@link  guide/comp iler Angul ar HTML Co mpiler} se ction of t he Develop er Guide.
  6355    */
  6356  
  6357   var $compi leMinErr =  minErr('$ compile');
  6358  
  6359   /**
  6360    * @ngdoc  provider
  6361    * @name $ compilePro vider
  6362    *
  6363    * @descri ption
  6364    */
  6365   $CompilePr ovider.$in ject = ['$ provide',  '$$sanitiz eUriProvid er'];
  6366   function $ CompilePro vider($pro vide, $$sa nitizeUriP rovider) {
  6367     var hasD irectives  = {},
  6368         Suff ix = 'Dire ctive',
  6369         COMM ENT_DIRECT IVE_REGEXP  = /^\s*di rective\:\ s*([\w\-]+ )\s+(.*)$/ ,
  6370         CLAS S_DIRECTIV E_REGEXP =  /(([\w\-] +)(?:\:([^ ;]+))?;?)/ ,
  6371         ALL_ OR_NOTHING _ATTRS = m akeMap('ng Src,ngSrcs et,src,src set'),
  6372         REQU IRE_PREFIX _REGEXP =  /^(?:(\^\^ ?)?(\?)?(\ ^\^?)?)?/;
  6373  
  6374     // Ref:  http://dev elopers.wh atwg.org/w ebappapis. html#event -handler-i dl-attribu tes
  6375     // The a ssumption  is that fu ture DOM e vent attri bute names  will begi n with
  6376     // 'on'  and be com posed of o nly Englis h letters.
  6377     var EVEN T_HANDLER_ ATTR_REGEX P = /^(on[ a-z]+|form action)$/;
  6378  
  6379     function  parseIsol ateBinding s(scope, d irectiveNa me) {
  6380       var LO CAL_REGEXP  = /^\s*([ @&]|=(\*?) )(\??)\s*( \w*)\s*$/;
  6381  
  6382       var bi ndings = { };
  6383  
  6384       forEac h(scope, f unction(de finition,  scopeName)  {
  6385         var  match = de finition.m atch(LOCAL _REGEXP);
  6386  
  6387         if ( !match) {
  6388           th row $compi leMinErr(' iscp',
  6389                "Invalid  isolate s cope defin ition for  directive  '{0}'." +
  6390                " Defini tion: {...  {1}: '{2} ' ...}",
  6391                directiv eName, sco peName, de finition);
  6392         }
  6393  
  6394         bind ings[scope Name] = {
  6395           mo de: match[ 1][0],
  6396           co llection:  match[2] = == '*',
  6397           op tional: ma tch[3] ===  '?',
  6398           at trName: ma tch[4] ||  scopeName
  6399         };
  6400       });
  6401  
  6402       return  bindings;
  6403     }
  6404  
  6405     /**
  6406      * @ngdo c method
  6407      * @name  $compileP rovider#di rective
  6408      * @kind  function
  6409      *
  6410      * @desc ription
  6411      * Regis ter a new  directive  with the c ompiler.
  6412      *
  6413      * @para m {string| Object} na me Name of  the direc tive in ca mel-case ( i.e. <code >ngBind</c ode> which
  6414      *    wi ll match a s <code>ng -bind</cod e>), or an  object ma p of direc tives wher e the keys  are the
  6415      *    na mes and th e values a re the fac tories.
  6416      * @para m {Functio n|Array} d irectiveFa ctory An i njectable  directive  factory fu nction. Se e
  6417      *    {@ link guide /directive } for more  info.
  6418      * @retu rns {ng.$c ompileProv ider} Self  for chain ing.
  6419      */
  6420      this.di rective =  function r egisterDir ective(nam e, directi veFactory)  {
  6421       assert NotHasOwnP roperty(na me, 'direc tive');
  6422       if (is String(nam e)) {
  6423         asse rtArg(dire ctiveFacto ry, 'direc tiveFactor y');
  6424         if ( !hasDirect ives.hasOw nProperty( name)) {
  6425           ha sDirective s[name] =  [];
  6426           $p rovide.fac tory(name  + Suffix,  ['$injecto r', '$exce ptionHandl er',
  6427              function($ injector,  $exception Handler) {
  6428                var dire ctives = [ ];
  6429                forEach( hasDirecti ves[name],  function( directiveF actory, in dex) {
  6430                  try {
  6431                    var  directive  = $injecto r.invoke(d irectiveFa ctory);
  6432                    if ( isFunction (directive )) {
  6433                      di rective =  { compile:  valueFn(d irective)  };
  6434                    } el se if (!di rective.co mpile && d irective.l ink) {
  6435                      di rective.co mpile = va lueFn(dire ctive.link );
  6436                    }
  6437                    dire ctive.prio rity = dir ective.pri ority || 0 ;
  6438                    dire ctive.inde x = index;
  6439                    dire ctive.name  = directi ve.name ||  name;
  6440                    dire ctive.requ ire = dire ctive.requ ire || (di rective.co ntroller & & directiv e.name);
  6441                    dire ctive.rest rict = dir ective.res trict || ' EA';
  6442                    if ( isObject(d irective.s cope)) {
  6443                      di rective.$$ isolateBin dings = pa rseIsolate Bindings(d irective.s cope, dire ctive.name );
  6444                    }
  6445                    dire ctives.pus h(directiv e);
  6446                  } catc h (e) {
  6447                    $exc eptionHand ler(e);
  6448                  }
  6449                });
  6450                return d irectives;
  6451              }]);
  6452         }
  6453         hasD irectives[ name].push (directive Factory);
  6454       } else  {
  6455         forE ach(name,  reversePar ams(regist erDirectiv e));
  6456       }
  6457       return  this;
  6458     };
  6459  
  6460  
  6461     /**
  6462      * @ngdo c method
  6463      * @name  $compileP rovider#aH refSanitiz ationWhite list
  6464      * @kind  function
  6465      *
  6466      * @desc ription
  6467      * Retri eves or ov errides th e default  regular ex pression t hat is use d for whit elisting o f safe
  6468      * urls  during a[h ref] sanit ization.
  6469      *
  6470      * The s anitizatio n is a sec urity meas ure aimed  at prevent ing XSS at tacks via  html links .
  6471      *
  6472      * Any u rl about t o be assig ned to a[h ref] via d ata-bindin g is first  normalize d and turn ed into
  6473      * an ab solute url . Afterwar ds, the ur l is match ed against  the `aHre fSanitizat ionWhiteli st`
  6474      * regul ar express ion. If a  match is f ound, the  original u rl is writ ten into t he dom. Ot herwise,
  6475      * the a bsolute ur l is prefi xed with ` 'unsafe:'`  string an d only the n is it wr itten into  the DOM.
  6476      *
  6477      * @para m {RegExp= } regexp N ew regexp  to whiteli st urls wi th.
  6478      * @retu rns {RegEx p|ng.$comp ileProvide r} Current  RegExp if  called wi thout valu e or self  for
  6479      *    ch aining oth erwise.
  6480      */
  6481     this.aHr efSanitiza tionWhitel ist = func tion(regex p) {
  6482       if (is Defined(re gexp)) {
  6483         $$sa nitizeUriP rovider.aH refSanitiz ationWhite list(regex p);
  6484         retu rn this;
  6485       } else  {
  6486         retu rn $$sanit izeUriProv ider.aHref Sanitizati onWhitelis t();
  6487       }
  6488     };
  6489  
  6490  
  6491     /**
  6492      * @ngdo c method
  6493      * @name  $compileP rovider#im gSrcSaniti zationWhit elist
  6494      * @kind  function
  6495      *
  6496      * @desc ription
  6497      * Retri eves or ov errides th e default  regular ex pression t hat is use d for whit elisting o f safe
  6498      * urls  during img [src] sani tization.
  6499      *
  6500      * The s anitizatio n is a sec urity meas ure aimed  at prevent  XSS attac ks via htm l links.
  6501      *
  6502      * Any u rl about t o be assig ned to img [src] via  data-bindi ng is firs t normaliz ed and tur ned into
  6503      * an ab solute url . Afterwar ds, the ur l is match ed against  the `imgS rcSanitiza tionWhitel ist`
  6504      * regul ar express ion. If a  match is f ound, the  original u rl is writ ten into t he dom. Ot herwise,
  6505      * the a bsolute ur l is prefi xed with ` 'unsafe:'`  string an d only the n is it wr itten into  the DOM.
  6506      *
  6507      * @para m {RegExp= } regexp N ew regexp  to whiteli st urls wi th.
  6508      * @retu rns {RegEx p|ng.$comp ileProvide r} Current  RegExp if  called wi thout valu e or self  for
  6509      *    ch aining oth erwise.
  6510      */
  6511     this.img SrcSanitiz ationWhite list = fun ction(rege xp) {
  6512       if (is Defined(re gexp)) {
  6513         $$sa nitizeUriP rovider.im gSrcSaniti zationWhit elist(rege xp);
  6514         retu rn this;
  6515       } else  {
  6516         retu rn $$sanit izeUriProv ider.imgSr cSanitizat ionWhiteli st();
  6517       }
  6518     };
  6519  
  6520     /**
  6521      * @ngdo c method
  6522      * @name   $compile Provider#d ebugInfoEn abled
  6523      *
  6524      * @para m {boolean =} enabled  update th e debugInf oEnabled s tate if pr ovided, ot herwise ju st return  the
  6525      * curre nt debugIn foEnabled  state
  6526      * @retu rns {*} cu rrent valu e if used  as getter  or itself  (chaining)  if used a s setter
  6527      *
  6528      * @kind  function
  6529      *
  6530      * @desc ription
  6531      * Call  this metho d to enabl e/disable  various de bug runtim e informat ion in the  compiler  such as ad ding
  6532      * bindi ng informa tion and a  reference  to the cu rrent scop e on to DO M elements .
  6533      * If en abled, the  compiler  will add t he followi ng to DOM  elements t hat have b een bound  to the sco pe
  6534      * * `ng -binding`  CSS class
  6535      * * `$b inding` da ta propert y containi ng an arra y of the b inding exp ressions
  6536      *
  6537      * You m ay want to  disable t his in pro duction fo r a signif icant perf ormance bo ost. See
  6538      * {@lin k guide/pr oduction#d isabling-d ebug-data  Disabling  Debug Data } for more .
  6539      *
  6540      * The d efault val ue is true .
  6541      */
  6542     var debu gInfoEnabl ed = true;
  6543     this.deb ugInfoEnab led = func tion(enabl ed) {
  6544       if (is Defined(en abled)) {
  6545         debu gInfoEnabl ed = enabl ed;
  6546         retu rn this;
  6547       }
  6548       return  debugInfo Enabled;
  6549     };
  6550  
  6551     this.$ge t = [
  6552                '$inject or', '$int erpolate',  '$excepti onHandler' , '$templa teRequest' , '$parse' ,
  6553                '$contro ller', '$r ootScope',  '$documen t', '$sce' , '$animat e', '$$san itizeUri',
  6554       functi on($inject or,   $int erpolate,    $excepti onHandler,    $templa teRequest,    $parse,
  6555                 $contro ller,   $r ootScope,    $documen t,   $sce,    $animat e,   $$san itizeUri)  {
  6556  
  6557       var At tributes =  function( element, a ttributesT oCopy) {
  6558         if ( attributes ToCopy) {
  6559           va r keys = O bject.keys (attribute sToCopy);
  6560           va r i, l, ke y;
  6561  
  6562           fo r (i = 0,  l = keys.l ength; i <  l; i++) {
  6563              key = keys [i];
  6564              this[key]  = attribut esToCopy[k ey];
  6565           }
  6566         } el se {
  6567           th is.$attr =  {};
  6568         }
  6569  
  6570         this .$$element  = element ;
  6571       };
  6572  
  6573       Attrib utes.proto type = {
  6574         $nor malize: di rectiveNor malize,
  6575  
  6576  
  6577         /**
  6578          * @ ngdoc meth od
  6579          * @ name $comp ile.direct ive.Attrib utes#$addC lass
  6580          * @ kind funct ion
  6581          *
  6582          * @ descriptio n
  6583          * A dds the CS S class va lue specif ied by the  classVal  parameter  to the ele ment. If a nimations
  6584          * a re enabled  then an a nimation w ill be tri ggered for  the class  addition.
  6585          *
  6586          * @ param {str ing} class Val The cl assName va lue that w ill be add ed to the  element
  6587          */
  6588         $add Class: fun ction(clas sVal) {
  6589           if  (classVal  && classV al.length  > 0) {
  6590              $animate.a ddClass(th is.$$eleme nt, classV al);
  6591           }
  6592         },
  6593  
  6594         /**
  6595          * @ ngdoc meth od
  6596          * @ name $comp ile.direct ive.Attrib utes#$remo veClass
  6597          * @ kind funct ion
  6598          *
  6599          * @ descriptio n
  6600          * R emoves the  CSS class  value spe cified by  the classV al paramet er from th e element.  If
  6601          * a nimations  are enable d then an  animation  will be tr iggered fo r the clas s removal.
  6602          *
  6603          * @ param {str ing} class Val The cl assName va lue that w ill be rem oved from  the elemen t
  6604          */
  6605         $rem oveClass:  function(c lassVal) {
  6606           if  (classVal  && classV al.length  > 0) {
  6607              $animate.r emoveClass (this.$$el ement, cla ssVal);
  6608           }
  6609         },
  6610  
  6611         /**
  6612          * @ ngdoc meth od
  6613          * @ name $comp ile.direct ive.Attrib utes#$upda teClass
  6614          * @ kind funct ion
  6615          *
  6616          * @ descriptio n
  6617          * A dds and re moves the  appropriat e CSS clas s values t o the elem ent based  on the dif ference
  6618          * b etween the  new and o ld CSS cla ss values  (specified  as newCla sses and o ldClasses) .
  6619          *
  6620          * @ param {str ing} newCl asses The  current CS S classNam e value
  6621          * @ param {str ing} oldCl asses The  former CSS  className  value
  6622          */
  6623         $upd ateClass:  function(n ewClasses,  oldClasse s) {
  6624           va r toAdd =  tokenDiffe rence(newC lasses, ol dClasses);
  6625           if  (toAdd &&  toAdd.len gth) {
  6626              $animate.a ddClass(th is.$$eleme nt, toAdd) ;
  6627           }
  6628  
  6629           va r toRemove  = tokenDi fference(o ldClasses,  newClasse s);
  6630           if  (toRemove  && toRemo ve.length)  {
  6631              $animate.r emoveClass (this.$$el ement, toR emove);
  6632           }
  6633         },
  6634  
  6635         /**
  6636          * S et a norma lized attr ibute on t he element  in a way  such that  all direct ives
  6637          * c an share t he attribu te. This f unction pr operly han dles boole an attribu tes.
  6638          * @ param {str ing} key N ormalized  key. (ie n gAttribute )
  6639          * @ param {str ing|boolea n} value T he value t o set. If  `null` att ribute wil l be delet ed.
  6640          * @ param {boo lean=} wri teAttr If  false, doe s not writ e the valu e to DOM e lement att ribute.
  6641          *      Default s to true.
  6642          * @ param {str ing=} attr Name Optio nal none n ormalized  name. Defa ults to ke y.
  6643          */
  6644         $set : function (key, valu e, writeAt tr, attrNa me) {
  6645           //  TODO: dec ide whethe r or not t o throw an  error if  "class"
  6646           // is set thr ough this  function s ince it ma y cause $u pdateClass  to
  6647           // become uns table.
  6648  
  6649           va r node = t his.$$elem ent[0],
  6650                booleanK ey = getBo oleanAttrN ame(node,  key),
  6651                aliasedK ey = getAl iasedAttrN ame(node,  key),
  6652                observer  = key,
  6653                nodeName ;
  6654  
  6655           if  (booleanK ey) {
  6656              this.$$ele ment.prop( key, value );
  6657              attrName =  booleanKe y;
  6658           }  else if (a liasedKey)  {
  6659              this[alias edKey] = v alue;
  6660              observer =  aliasedKe y;
  6661           }
  6662  
  6663           th is[key] =  value;
  6664  
  6665           //  translate  normalize d key to a ctual key
  6666           if  (attrName ) {
  6667              this.$attr [key] = at trName;
  6668           }  else {
  6669              attrName =  this.$att r[key];
  6670              if (!attrN ame) {
  6671                this.$at tr[key] =  attrName =  snake_cas e(key, '-' );
  6672              }
  6673           }
  6674  
  6675           no deName = n odeName_(t his.$$elem ent);
  6676  
  6677           if  ((nodeNam e === 'a'  && key ===  'href') | |
  6678                (nodeNam e === 'img ' && key = == 'src'))  {
  6679              // sanitiz e a[href]  and img[sr c] values
  6680              this[key]  = value =  $$sanitize Uri(value,  key === ' src');
  6681           }  else if (n odeName == = 'img' &&  key === ' srcset') {
  6682              // sanitiz e img[srcs et] values
  6683              var result  = "";
  6684  
  6685              // first c heck if th ere are sp aces becau se it's no t the same  pattern
  6686              var trimme dSrcset =  trim(value );
  6687              //                 (    999x   , |   999w    ,|   ,|,    )
  6688              var srcPat tern = /(\ s+\d+x\s*, |\s+\d+w\s *,|\s+,|,\ s+)/;
  6689              var patter n = /\s/.t est(trimme dSrcset) ?  srcPatter n : /(,)/;
  6690  
  6691              // split s rcset into  tuple of  uri and de scriptor e xcept for  the last i tem
  6692              var rawUri s = trimme dSrcset.sp lit(patter n);
  6693  
  6694              // for eac h tuples
  6695              var nbrUri sWith2part s = Math.f loor(rawUr is.length  / 2);
  6696              for (var i  = 0; i <  nbrUrisWit h2parts; i ++) {
  6697                var inne rIdx = i *  2;
  6698                // sanit ize the ur i
  6699                result + = $$saniti zeUri(trim (rawUris[i nnerIdx]),  true);
  6700                // add t he descrip tor
  6701                result + = (" " + t rim(rawUri s[innerIdx  + 1]));
  6702              }
  6703  
  6704              // split t he last it em into ur i and desc riptor
  6705              var lastTu ple = trim (rawUris[i  * 2]).spl it(/\s/);
  6706  
  6707              // sanitiz e the last  uri
  6708              result +=  $$sanitize Uri(trim(l astTuple[0 ]), true);
  6709  
  6710              // and add  the last  descriptor  if any
  6711              if (lastTu ple.length  === 2) {
  6712                result + = (" " + t rim(lastTu ple[1]));
  6713              }
  6714              this[key]  = value =  result;
  6715           }
  6716  
  6717           if  (writeAtt r !== fals e) {
  6718              if (value  === null | | value == = undefine d) {
  6719                this.$$e lement.rem oveAttr(at trName);
  6720              } else {
  6721                this.$$e lement.att r(attrName , value);
  6722              }
  6723           }
  6724  
  6725           //  fire obse rvers
  6726           va r $$observ ers = this .$$observe rs;
  6727           $$ observers  && forEach ($$observe rs[observe r], functi on(fn) {
  6728              try {
  6729                fn(value );
  6730              } catch (e ) {
  6731                $excepti onHandler( e);
  6732              }
  6733           }) ;
  6734         },
  6735  
  6736  
  6737         /**
  6738          * @ ngdoc meth od
  6739          * @ name $comp ile.direct ive.Attrib utes#$obse rve
  6740          * @ kind funct ion
  6741          *
  6742          * @ descriptio n
  6743          * O bserves an  interpola ted attrib ute.
  6744          *
  6745          * T he observe r function  will be i nvoked onc e during t he next `$ digest` fo llowing
  6746          * c ompilation . The obse rver is th en invoked  whenever  the interp olated val ue
  6747          * c hanges.
  6748          *
  6749          * @ param {str ing} key N ormalized  key. (ie n gAttribute ) .
  6750          * @ param {fun ction(inte rpolatedVa lue)} fn F unction th at will be  called wh enever
  6751                    the  interpolat ed value o f the attr ibute chan ges.
  6752          *         See  the {@link  guide/dir ective#tex t-and-attr ibute-bind ings Direc tives} gui de for mor e info.
  6753          * @ returns {f unction()}  Returns a  deregistr ation func tion for t his observ er.
  6754          */
  6755         $obs erve: func tion(key,  fn) {
  6756           va r attrs =  this,
  6757                $$observ ers = (att rs.$$obser vers || (a ttrs.$$obs ervers = c reateMap() )),
  6758                listener s = ($$obs ervers[key ] || ($$ob servers[ke y] = []));
  6759  
  6760           li steners.pu sh(fn);
  6761             $rootScope .$e DNS    ync(functi on() {
  6762              if (!liste ners.$$int er && attr s.hasOwnPr operty(key )) {
  6763                // no on e register ed attribu te interpo lation fun ction, so  lets call  it manuall y
  6764                fn(attrs [key]);
  6765              }
  6766           }) ;
  6767  
  6768           re turn funct ion() {
  6769              arrayRemov e(listener s, fn);
  6770           };
  6771         }
  6772       };
  6773  
  6774  
  6775       functi on safeAdd Class($ele ment, clas sName) {
  6776         try  {
  6777           $e lement.add Class(clas sName);
  6778         } ca tch (e) {
  6779           //  ignore, s ince it me ans that w e are tryi ng to set  class on
  6780           //  SVG eleme nt, where  class name  is read-o nly.
  6781         }
  6782       }
  6783  
  6784  
  6785       var st artSymbol  = $interpo late.start Symbol(),
  6786           en dSymbol =  $interpola te.endSymb ol(),
  6787           de normalizeT emplate =  (startSymb ol == '{{'  || endSym bol  == '} }')
  6788                ? identi ty
  6789                : functi on denorma lizeTempla te(templat e) {
  6790                  return  template. replace(/\ {\{/g, sta rtSymbol). replace(/} }/g, endSy mbol);
  6791           },
  6792           NG _ATTR_BIND ING = /^ng Attr[A-Z]/ ;
  6793  
  6794       compil e.$$addBin dingInfo =  debugInfo Enabled ?  function $ $addBindin gInfo($ele ment, bind ing) {
  6795         var  bindings =  $element. data('$bin ding') ||  [];
  6796  
  6797         if ( isArray(bi nding)) {
  6798           bi ndings = b indings.co ncat(bindi ng);
  6799         } el se {
  6800           bi ndings.pus h(binding) ;
  6801         }
  6802  
  6803         $ele ment.data( '$binding' , bindings );
  6804       } : no op;
  6805  
  6806       compil e.$$addBin dingClass  = debugInf oEnabled ?  function  $$addBindi ngClass($e lement) {
  6807         safe AddClass($ element, ' ng-binding ');
  6808       } : no op;
  6809  
  6810       compil e.$$addSco peInfo = d ebugInfoEn abled ? fu nction $$a ddScopeInf o($element , scope, i solated, n oTemplate)  {
  6811         var  dataName =  isolated  ? (noTempl ate ? '$is olateScope NoTemplate ' : '$isol ateScope')  : '$scope ';
  6812         $ele ment.data( dataName,  scope);
  6813       } : no op;
  6814  
  6815       compil e.$$addSco peClass =  debugInfoE nabled ? f unction $$ addScopeCl ass($eleme nt, isolat ed) {
  6816         safe AddClass($ element, i solated ?  'ng-isolat e-scope' :  'ng-scope ');
  6817       } : no op;
  6818  
  6819       return  compile;
  6820  
  6821       //==== ========== ========== ========
  6822  
  6823       functi on compile ($compileN odes, tran scludeFn,  maxPriorit y, ignoreD irective,
  6824                             previo usCompileC ontext) {
  6825         if ( !($compile Nodes inst anceof jqL ite)) {
  6826           //  jquery al ways rewra ps, wherea s we need  to preserv e the orig inal selec tor so tha t we can
  6827           //  modify it .
  6828           $c ompileNode s = jqLite ($compileN odes);
  6829         }
  6830         // W e can not  compile to p level te xt element s since te xt nodes c an be merg ed and we  will
  6831         // n ot be able  to attach  scope dat a to them,  so we wil l wrap the m in <span >
  6832         forE ach($compi leNodes, f unction(no de, index)  {
  6833           if  (node.nod eType == N ODE_TYPE_T EXT && nod e.nodeValu e.match(/\ S+/) /* no n-empty */  ) {
  6834              $compileNo des[index]  = jqLite( node).wrap ('<span></ span>').pa rent()[0];
  6835           }
  6836         });
  6837         var  compositeL inkFn =
  6838                  compil eNodes($co mpileNodes , transclu deFn, $com pileNodes,
  6839                                max Priority,  ignoreDire ctive, pre viousCompi leContext) ;
  6840         comp ile.$$addS copeClass( $compileNo des);
  6841         var  namespace  = null;
  6842         retu rn functio n publicLi nkFn(scope , cloneCon nectFn, op tions) {
  6843           as sertArg(sc ope, 'scop e');
  6844  
  6845           op tions = op tions || { };
  6846           va r parentBo undTranscl udeFn = op tions.pare ntBoundTra nscludeFn,
  6847              transclude Controller s = option s.transclu deControll ers,
  6848              futurePare ntElement  = options. futurePare ntElement;
  6849  
  6850           //  When `par entBoundTr anscludeFn ` is passe d, it is a
  6851           //  `controll ersBoundTr ansclude`  function ( it was pre viously pa ssed
  6852           //  as `trans clude` to  directive. link) so w e must unw rap it to  get
  6853           //  its `boun dTransclud eFn`
  6854           if  (parentBo undTranscl udeFn && p arentBound Transclude Fn.$$bound Transclude ) {
  6855              parentBoun dTransclud eFn = pare ntBoundTra nscludeFn. $$boundTra nsclude;
  6856           }
  6857  
  6858           if  (!namespa ce) {
  6859              namespace  = detectNa mespaceFor ChildEleme nts(future ParentElem ent);
  6860           }
  6861           va r $linkNod e;
  6862           if  (namespac e !== 'htm l') {
  6863              // When us ing a dire ctive with  replace:t rue and te mplateUrl  the $compi leNodes
  6864              // (or a c hild eleme nt inside  of them)
  6865              // might c hange, so  we need to  recreate  the namesp ace adapte d compileN odes
  6866              // for cal l to the l ink functi on.
  6867              // Note: T his will a lready clo ne the nod es...
  6868              $linkNode  = jqLite(
  6869                wrapTemp late(names pace, jqLi te('<div>' ).append($ compileNod es).html() )
  6870              );
  6871           }  else if (c loneConnec tFn) {
  6872              // importa nt!!: we m ust call o ur jqLite. clone() si nce the jQ uery one i s trying t o be smart
  6873              // and som etimes cha nges the s tructure o f the DOM.
  6874              $linkNode  = JQLitePr ototype.cl one.call($ compileNod es);
  6875           }  else {
  6876              $linkNode  = $compile Nodes;
  6877           }
  6878  
  6879           if  (transclu deControll ers) {
  6880              for (var c ontrollerN ame in tra nscludeCon trollers)  {
  6881                $linkNod e.data('$'  + control lerName +  'Controlle r', transc ludeContro llers[cont rollerName ].instance );
  6882              }
  6883           }
  6884  
  6885           co mpile.$$ad dScopeInfo ($linkNode , scope);
  6886  
  6887           if  (cloneCon nectFn) cl oneConnect Fn($linkNo de, scope) ;
  6888           if  (composit eLinkFn) c ompositeLi nkFn(scope , $linkNod e, $linkNo de, parent BoundTrans cludeFn);
  6889           re turn $link Node;
  6890         };
  6891       }
  6892  
  6893       functi on detectN amespaceFo rChildElem ents(paren tElement)  {
  6894         // T ODO: Make  this detec t MathML a s well...
  6895         var  node = par entElement  && parent Element[0] ;
  6896         if ( !node) {
  6897           re turn 'html ';
  6898         } el se {
  6899           re turn nodeN ame_(node)  !== 'fore ignobject'  && node.t oString(). match(/SVG /) ? 'svg'  : 'html';
  6900         }
  6901       }
  6902  
  6903       /**
  6904        * Com pile funct ion matche s each nod e in nodeL ist agains t the dire ctives. On ce all dir ectives
  6905        * for  a particu lar node a re collect ed their c ompile fun ctions are  executed.  The compi le
  6906        * fun ctions ret urn values  - the lin king funct ions - are  combined  into a com posite lin king
  6907        * fun ction, whi ch is the  a linking  function f or the nod e.
  6908        *
  6909        * @pa ram {NodeL ist} nodeL ist an arr ay of node s or NodeL ist to com pile
  6910        * @pa ram {funct ion(angula r.Scope, c loneAttach Fn=)} tran scludeFn A  linking f unction, w here the
  6911        *         scope  argument i s auto-gen erated to  the new ch ild of the  transclud ed parent  scope.
  6912        * @pa ram {DOMEl ement=} $r ootElement  If the no deList is  the root o f the comp ilation tr ee then
  6913        *         the ro otElement  must be se t the jqLi te collect ion of the  compile r oot. This  is
  6914        *         needed  so that t he jqLite  collection  items can  be replac ed with wi dgets.
  6915        * @pa ram {numbe r=} maxPri ority Max  directive  priority.
  6916        * @re turns {Fun ction} A c omposite l inking fun ction of a ll of the  matched di rectives o r null.
  6917        */
  6918       functi on compile Nodes(node List, tran scludeFn,  $rootEleme nt, maxPri ority, ign oreDirecti ve,
  6919                                 pr eviousComp ileContext ) {
  6920         var  linkFns =  [],
  6921              attrs, dir ectives, n odeLinkFn,  childNode s, childLi nkFn, link FnFound, n odeLinkFnF ound;
  6922  
  6923         for  (var i = 0 ; i < node List.lengt h; i++) {
  6924           at trs = new  Attributes ();
  6925  
  6926           //  we must a lways refe r to nodeL ist[i] sin ce the nod es can be  replaced u nderneath  us.
  6927           di rectives =  collectDi rectives(n odeList[i] , [], attr s, i === 0  ? maxPrio rity : und efined,
  6928                                               ignoreDire ctive);
  6929  
  6930           no deLinkFn =  (directiv es.length)
  6931                ? applyD irectivesT oNode(dire ctives, no deList[i],  attrs, tr anscludeFn , $rootEle ment,
  6932                                            nu ll, [], [] , previous CompileCon text)
  6933                : null;
  6934  
  6935           if  (nodeLink Fn && node LinkFn.sco pe) {
  6936              compile.$$ addScopeCl ass(attrs. $$element) ;
  6937           }
  6938  
  6939           ch ildLinkFn  = (nodeLin kFn && nod eLinkFn.te rminal ||
  6940                           !(childN odes = nod eList[i].c hildNodes)  ||
  6941                           !childNo des.length )
  6942                ? null
  6943                : compil eNodes(chi ldNodes,
  6944                     nod eLinkFn ?  (
  6945                      (n odeLinkFn. transclude OnThisElem ent || !no deLinkFn.t emplateOnT hisElement )
  6946                          && nodeLi nkFn.trans clude) : t ranscludeF n);
  6947  
  6948           if  (nodeLink Fn || chil dLinkFn) {
  6949              linkFns.pu sh(i, node LinkFn, ch ildLinkFn) ;
  6950              linkFnFoun d = true;
  6951              nodeLinkFn Found = no deLinkFnFo und || nod eLinkFn;
  6952           }
  6953  
  6954           // use the pr evious con text only  for the fi rst elemen t in the v irtual gro up
  6955           pr eviousComp ileContext  = null;
  6956         }
  6957  
  6958         // r eturn a li nking func tion if we  have foun d anything , null oth erwise
  6959         retu rn linkFnF ound ? com positeLink Fn : null;
  6960  
  6961         func tion compo siteLinkFn (scope, no deList, $r ootElement , parentBo undTranscl udeFn) {
  6962           va r nodeLink Fn, childL inkFn, nod e, childSc ope, i, ii , idx, chi ldBoundTra nscludeFn;
  6963           va r stableNo deList;
  6964  
  6965  
  6966           if  (nodeLink FnFound) {
  6967              // copy no deList so  that if a  nodeLinkFn  removes o r adds an  element at  this DOM  level our
  6968              // offsets  don't get  screwed u p
  6969              var nodeLi stLength =  nodeList. length;
  6970              stableNode List = new  Array(nod eListLengt h);
  6971  
  6972              // create  a sparse a rray by on ly copying  the eleme nts which  have a lin kFn
  6973              for (i = 0 ; i < link Fns.length ; i+=3) {
  6974                idx = li nkFns[i];
  6975                stableNo deList[idx ] = nodeLi st[idx];
  6976              }
  6977           }  else {
  6978              stableNode List = nod eList;
  6979           }
  6980  
  6981           fo r (i = 0,  ii = linkF ns.length;  i < ii;)  {
  6982              node = sta bleNodeLis t[linkFns[ i++]];
  6983              nodeLinkFn  = linkFns [i++];
  6984              childLinkF n = linkFn s[i++];
  6985  
  6986              if (nodeLi nkFn) {
  6987                if (node LinkFn.sco pe) {
  6988                  childS cope = sco pe.$new();
  6989                  compil e.$$addSco peInfo(jqL ite(node),  childScop e);
  6990                } else {
  6991                  childS cope = sco pe;
  6992                }
  6993  
  6994                if (node LinkFn.tra nscludeOnT hisElement ) {
  6995                  childB oundTransc ludeFn = c reateBound Transclude Fn(
  6996                      sc ope, nodeL inkFn.tran sclude, pa rentBoundT ranscludeF n,
  6997                      no deLinkFn.e lementTran scludeOnTh isElement) ;
  6998  
  6999                } else i f (!nodeLi nkFn.templ ateOnThisE lement &&  parentBoun dTransclud eFn) {
  7000                  childB oundTransc ludeFn = p arentBound Transclude Fn;
  7001  
  7002                } else i f (!parent BoundTrans cludeFn &&  transclud eFn) {
  7003                  childB oundTransc ludeFn = c reateBound Transclude Fn(scope,  transclude Fn);
  7004  
  7005                } else {
  7006                  childB oundTransc ludeFn = n ull;
  7007                }
  7008  
  7009                nodeLink Fn(childLi nkFn, chil dScope, no de, $rootE lement, ch ildBoundTr anscludeFn );
  7010  
  7011              } else if  (childLink Fn) {
  7012                childLin kFn(scope,  node.chil dNodes, un defined, p arentBound Transclude Fn);
  7013              }
  7014           }
  7015         }
  7016       }
  7017  
  7018       functi on createB oundTransc ludeFn(sco pe, transc ludeFn, pr eviousBoun dTransclud eFn, eleme ntTransclu sion) {
  7019  
  7020         var  boundTrans cludeFn =  function(t ranscluded Scope, clo neFn, cont rollers, f utureParen tElement,  containing Scope) {
  7021  
  7022           if  (!transcl udedScope)  {
  7023              transclude dScope = s cope.$new( false, con tainingSco pe);
  7024              transclude dScope.$$t ranscluded  = true;
  7025           }
  7026  
  7027           re turn trans cludeFn(tr anscludedS cope, clon eFn, {
  7028              parentBoun dTransclud eFn: previ ousBoundTr anscludeFn ,
  7029              transclude Controller s: control lers,
  7030              futurePare ntElement:  futurePar entElement
  7031           }) ;
  7032         };
  7033  
  7034         retu rn boundTr anscludeFn ;
  7035       }
  7036  
  7037       /**
  7038        * Loo ks for dir ectives on  the given  node and  adds them  to the dir ective col lection wh ich is
  7039        * sor ted.
  7040        *
  7041        * @pa ram node N ode to sea rch.
  7042        * @pa ram direct ives An ar ray to whi ch the dir ectives ar e added to . This arr ay is sort ed before
  7043        *         the fu nction ret urns.
  7044        * @pa ram attrs  The shared  attrs obj ect which  is used to  populate  the normal ized attri butes.
  7045        * @pa ram {numbe r=} maxPri ority Max  directive  priority.
  7046        */
  7047       functi on collect Directives (node, dir ectives, a ttrs, maxP riority, i gnoreDirec tive) {
  7048         var  nodeType =  node.node Type,
  7049              attrsMap =  attrs.$at tr,
  7050              match,
  7051              className;
  7052  
  7053         swit ch (nodeTy pe) {
  7054           ca se NODE_TY PE_ELEMENT : /* Eleme nt */
  7055              // use the  node name : <directi ve>
  7056              addDirecti ve(directi ves,
  7057                  direct iveNormali ze(nodeNam e_(node)),  'E', maxP riority, i gnoreDirec tive);
  7058  
  7059              // iterate  over the  attributes
  7060              for (var a ttr, name,  nName, ng AttrName,  value, isN gAttr, nAt trs = node .attribute s,
  7061                       j  = 0, jj =  nAttrs &&  nAttrs.le ngth; j <  jj; j++) {
  7062                var attr StartName  = false;
  7063                var attr EndName =  false;
  7064  
  7065                attr = n Attrs[j];
  7066                name = a ttr.name;
  7067                value =  trim(attr. value);
  7068  
  7069                // suppo rt ngAttr  attribute  binding
  7070                ngAttrNa me = direc tiveNormal ize(name);
  7071                if (isNg Attr = NG_ ATTR_BINDI NG.test(ng AttrName))  {
  7072                  name =  snake_cas e(ngAttrNa me.substr( 6), '-');
  7073                }
  7074  
  7075                var dire ctiveNName  = ngAttrN ame.replac e(/(Start| End)$/, '' );
  7076                if (dire ctiveIsMul tiElement( directiveN Name)) {
  7077                  if (ng AttrName = == directi veNName +  'Start') {
  7078                    attr StartName  = name;
  7079                    attr EndName =  name.subst r(0, name. length - 5 ) + 'end';
  7080                    name  = name.su bstr(0, na me.length  - 6);
  7081                  }
  7082                }
  7083  
  7084                nName =  directiveN ormalize(n ame.toLowe rCase());
  7085                attrsMap [nName] =  name;
  7086                if (isNg Attr || !a ttrs.hasOw nProperty( nName)) {
  7087                    attr s[nName] =  value;
  7088                    if ( getBoolean AttrName(n ode, nName )) {
  7089                      at trs[nName]  = true; / / presence  means tru e
  7090                    }
  7091                }
  7092                addAttrI nterpolate Directive( node, dire ctives, va lue, nName , isNgAttr );
  7093                addDirec tive(direc tives, nNa me, 'A', m axPriority , ignoreDi rective, a ttrStartNa me,
  7094                               attr EndName);
  7095              }
  7096  
  7097              // use cla ss as dire ctive
  7098              className  = node.cla ssName;
  7099              if (isStri ng(classNa me) && cla ssName !==  '') {
  7100                while (m atch = CLA SS_DIRECTI VE_REGEXP. exec(class Name)) {
  7101                  nName  = directiv eNormalize (match[2]) ;
  7102                  if (ad dDirective (directive s, nName,  'C', maxPr iority, ig noreDirect ive)) {
  7103                    attr s[nName] =  trim(matc h[3]);
  7104                  }
  7105                  classN ame = clas sName.subs tr(match.i ndex + mat ch[0].leng th);
  7106                }
  7107              }
  7108              break;
  7109           ca se NODE_TY PE_TEXT: / * Text Nod e */
  7110              addTextInt erpolateDi rective(di rectives,  node.nodeV alue);
  7111              break;
  7112           ca se NODE_TY PE_COMMENT : /* Comme nt */
  7113              try {
  7114                match =  COMMENT_DI RECTIVE_RE GEXP.exec( node.nodeV alue);
  7115                if (matc h) {
  7116                  nName  = directiv eNormalize (match[1]) ;
  7117                  if (ad dDirective (directive s, nName,  'M', maxPr iority, ig noreDirect ive)) {
  7118                    attr s[nName] =  trim(matc h[2]);
  7119                  }
  7120                }
  7121              } catch (e ) {
  7122                // turns  out that  under some  circumsta nces IE9 t hrows erro rs when on e attempts  to read
  7123                // comme nt's node  value.
  7124                // Just  ignore it  and contin ue. (Can't  seem to r eproduce i n test cas e.)
  7125              }
  7126              break;
  7127         }
  7128  
  7129         dire ctives.sor t(byPriori ty);
  7130         retu rn directi ves;
  7131       }
  7132  
  7133       /**
  7134        * Giv en a node  with an di rective-st art it col lects all  of the sib lings unti l it finds
  7135        * dir ective-end .
  7136        * @pa ram node
  7137        * @pa ram attrSt art
  7138        * @pa ram attrEn d
  7139        * @re turns {*}
  7140        */
  7141       functi on groupSc an(node, a ttrStart,  attrEnd) {
  7142         var  nodes = [] ;
  7143         var  depth = 0;
  7144         if ( attrStart  && node.ha sAttribute  && node.h asAttribut e(attrStar t)) {
  7145           do  {
  7146              if (!node)  {
  7147                throw $c ompileMinE rr('uterdi r',
  7148                           "Untermi nated attr ibute, fou nd '{0}' b ut no matc hing '{1}'  found.",
  7149                           attrStar t, attrEnd );
  7150              }
  7151              if (node.n odeType ==  NODE_TYPE _ELEMENT)  {
  7152                if (node .hasAttrib ute(attrSt art)) dept h++;
  7153                if (node .hasAttrib ute(attrEn d)) depth- -;
  7154              }
  7155              nodes.push (node);
  7156              node = nod e.nextSibl ing;
  7157           }  while (dep th > 0);
  7158         } el se {
  7159           no des.push(n ode);
  7160         }
  7161  
  7162         retu rn jqLite( nodes);
  7163       }
  7164  
  7165       /**
  7166        * Wra pper for l inking fun ction whic h converts  normal li nking func tion into  a grouped
  7167        * lin king funct ion.
  7168        * @pa ram linkFn
  7169        * @pa ram attrSt art
  7170        * @pa ram attrEn d
  7171        * @re turns {Fun ction}
  7172        */
  7173       functi on groupEl ementsLink FnWrapper( linkFn, at trStart, a ttrEnd) {
  7174         retu rn functio n(scope, e lement, at trs, contr ollers, tr anscludeFn ) {
  7175           el ement = gr oupScan(el ement[0],  attrStart,  attrEnd);
  7176           re turn linkF n(scope, e lement, at trs, contr ollers, tr anscludeFn );
  7177         };
  7178       }
  7179  
  7180       /**
  7181        * Onc e the dire ctives hav e been col lected, th eir compil e function s are exec uted. This  method
  7182        * is  responsibl e for inli ning direc tive templ ates as we ll as term inating th e applicat ion
  7183        * of  the direct ives if th e terminal  directive  has been  reached.
  7184        *
  7185        * @pa ram {Array } directiv es Array o f collecte d directiv es to exec ute their  compile fu nction.
  7186        *         this n eeds to be  pre-sorte d by prior ity order.
  7187        * @pa ram {Node}  compileNo de The raw  DOM node  to apply t he compile  functions  to
  7188        * @pa ram {Objec t} templat eAttrs The  shared at tribute fu nction
  7189        * @pa ram {funct ion(angula r.Scope, c loneAttach Fn=)} tran scludeFn A  linking f unction, w here the
  7190        *                                                       scop e argument  is auto-g enerated t o the new
  7191        *                                                       chil d of the t ranscluded  parent sc ope.
  7192        * @pa ram {JQLit e} jqColle ction If w e are work ing on the  root of t he compile  tree then  this
  7193        *                                 argu ment has t he root jq Lite array  so that w e can repl ace nodes
  7194        *                                 on i t.
  7195        * @pa ram {Objec t=} origin alReplaceD irective A n optional  directive  that will  be ignore d when
  7196        *                                               c ompiling t he transcl usion.
  7197        * @pa ram {Array .<Function >} preLink Fns
  7198        * @pa ram {Array .<Function >} postLin kFns
  7199        * @pa ram {Objec t} previou sCompileCo ntext Cont ext used f or previou s compilat ion of the  current
  7200        *                                            node
  7201        * @re turns {Fun ction} lin kFn
  7202        */
  7203       functi on applyDi rectivesTo Node(direc tives, com pileNode,  templateAt trs, trans cludeFn,
  7204                                         jqCol lection, o riginalRep laceDirect ive, preLi nkFns, pos tLinkFns,
  7205                                         previ ousCompile Context) {
  7206         prev iousCompil eContext =  previousC ompileCont ext || {};
  7207  
  7208         var  terminalPr iority = - Number.MAX _VALUE,
  7209              newScopeDi rective,
  7210              controller Directives  = previou sCompileCo ntext.cont rollerDire ctives,
  7211              controller s,
  7212              newIsolate ScopeDirec tive = pre viousCompi leContext. newIsolate ScopeDirec tive,
  7213              templateDi rective =  previousCo mpileConte xt.templat eDirective ,
  7214              nonTlbTran scludeDire ctive = pr eviousComp ileContext .nonTlbTra nscludeDir ective,
  7215              hasTranscl udeDirecti ve = false ,
  7216              hasTemplat e = false,
  7217              hasElement Transclude Directive  = previous CompileCon text.hasEl ementTrans cludeDirec tive,
  7218              $compileNo de = templ ateAttrs.$ $element =  jqLite(co mpileNode) ,
  7219              directive,
  7220              directiveN ame,
  7221              $template,
  7222              replaceDir ective = o riginalRep laceDirect ive,
  7223              childTrans cludeFn =  transclude Fn,
  7224              linkFn,
  7225              directiveV alue;
  7226  
  7227         // e xecutes al l directiv es on the  current el ement
  7228         for  (var i = 0 , ii = dir ectives.le ngth; i <  ii; i++) {
  7229           di rective =  directives [i];
  7230           va r attrStar t = direct ive.$$star t;
  7231           va r attrEnd  = directiv e.$$end;
  7232  
  7233           //  collect m ultiblock  sections
  7234           if  (attrStar t) {
  7235              $compileNo de = group Scan(compi leNode, at trStart, a ttrEnd);
  7236           }
  7237           $t emplate =  undefined;
  7238  
  7239           if  (terminal Priority >  directive .priority)  {
  7240              break; //  prevent fu rther proc essing of  directives
  7241           }
  7242  
  7243           if  (directiv eValue = d irective.s cope) {
  7244  
  7245              // skip th e check fo r directiv es with as ync templa tes, we'll  check the  derived s ync
  7246              // directi ve when th e template  arrives
  7247              if (!direc tive.templ ateUrl) {
  7248                if (isOb ject(direc tiveValue) ) {
  7249                  // Thi s directiv e is tryin g to add a n isolated  scope.
  7250                  // Che ck that th ere is no  scope of a ny kind al ready
  7251                  assert NoDuplicat e('new/iso lated scop e', newIso lateScopeD irective | | newScope Directive,
  7252                                      directiv e, $compil eNode);
  7253                  newIso lateScopeD irective =  directive ;
  7254                } else {
  7255                  // Thi s directiv e is tryin g to add a  child sco pe.
  7256                  // Che ck that th ere is no  isolated s cope alrea dy
  7257                  assert NoDuplicat e('new/iso lated scop e', newIso lateScopeD irective,  directive,
  7258                                      $compile Node);
  7259                }
  7260              }
  7261  
  7262              newScopeDi rective =  newScopeDi rective ||  directive ;
  7263           }
  7264  
  7265           di rectiveNam e = direct ive.name;
  7266  
  7267           if  (!directi ve.templat eUrl && di rective.co ntroller)  {
  7268              directiveV alue = dir ective.con troller;
  7269              controller Directives  = control lerDirecti ves || {};
  7270              assertNoDu plicate("' " + direct iveName +  "' control ler",
  7271                  contro llerDirect ives[direc tiveName],  directive , $compile Node);
  7272              controller Directives [directive Name] = di rective;
  7273           }
  7274  
  7275           if  (directiv eValue = d irective.t ransclude)  {
  7276              hasTranscl udeDirecti ve = true;
  7277  
  7278              // Special  case ngIf  and ngRep eat so tha t we don't  complain  about dupl icate tran sclusion.
  7279              // This op tion shoul d only be  used by di rectives t hat know h ow to safe ly handle  element tr ansclusion ,
  7280              // where t he transcl uded nodes  are added  or replac ed after l inking.
  7281              if (!direc tive.$$tlb ) {
  7282                assertNo Duplicate( 'transclus ion', nonT lbTransclu deDirectiv e, directi ve, $compi leNode);
  7283                nonTlbTr anscludeDi rective =  directive;
  7284              }
  7285  
  7286              if (direct iveValue = = 'element ') {
  7287                hasEleme ntTransclu deDirectiv e = true;
  7288                terminal Priority =  directive .priority;
  7289                $templat e = $compi leNode;
  7290                $compile Node = tem plateAttrs .$$element  =
  7291                    jqLi te(documen t.createCo mment(' '  + directiv eName + ':  ' +
  7292                                                     temp lateAttrs[ directiveN ame] + ' ' ));
  7293                compileN ode = $com pileNode[0 ];
  7294                replaceW ith(jqColl ection, sl iceArgs($t emplate),  compileNod e);
  7295  
  7296                childTra nscludeFn  = compile( $template,  transclud eFn, termi nalPriorit y,
  7297                                               replaceDir ective &&  replaceDir ective.nam e, {
  7298                                                 // Don't  pass in:
  7299                                                 // - con trollerDir ectives -  otherwise  we'll crea te duplica tes contro llers
  7300                                                 // - new IsolateSco peDirectiv e or templ ateDirecti ve - combi ning templ ates with
  7301                                                 //   ele ment trans clusion do esn't make  sense.
  7302                                                 //
  7303                                                 // We ne ed only no nTlbTransc ludeDirect ive so tha t we preve nt putting  transclus ion
  7304                                                 // on th e same ele ment more  than once.
  7305                                                 nonTlbTr anscludeDi rective: n onTlbTrans cludeDirec tive
  7306                                               });
  7307              } else {
  7308                $templat e = jqLite (jqLiteClo ne(compile Node)).con tents();
  7309                $compile Node.empty (); // cle ar content s
  7310                childTra nscludeFn  = compile( $template,  transclud eFn);
  7311              }
  7312           }
  7313  
  7314           if  (directiv e.template ) {
  7315              hasTemplat e = true;
  7316              assertNoDu plicate('t emplate',  templateDi rective, d irective,  $compileNo de);
  7317              templateDi rective =  directive;
  7318  
  7319              directiveV alue = (is Function(d irective.t emplate))
  7320                  ? dire ctive.temp late($comp ileNode, t emplateAtt rs)
  7321                  : dire ctive.temp late;
  7322  
  7323              directiveV alue = den ormalizeTe mplate(dir ectiveValu e);
  7324  
  7325              if (direct ive.replac e) {
  7326                replaceD irective =  directive ;
  7327                if (jqLi teIsTextNo de(directi veValue))  {
  7328                  $templ ate = [];
  7329                } else {
  7330                  $templ ate = remo veComments (wrapTempl ate(direct ive.templa teNamespac e, trim(di rectiveVal ue)));
  7331                }
  7332                compileN ode = $tem plate[0];
  7333  
  7334                if ($tem plate.leng th != 1 ||  compileNo de.nodeTyp e !== NODE _TYPE_ELEM ENT) {
  7335                  throw  $compileMi nErr('tplr t',
  7336                      "T emplate fo r directiv e '{0}' mu st have ex actly one  root eleme nt. {1}",
  7337                      di rectiveNam e, '');
  7338                }
  7339  
  7340                replaceW ith(jqColl ection, $c ompileNode , compileN ode);
  7341  
  7342                var newT emplateAtt rs = {$att r: {}};
  7343  
  7344                // combi ne directi ves from t he origina l node and  from the  template:
  7345                // - tak e the arra y of direc tives for  this eleme nt
  7346                // - spl it it into  two parts , those th at already  applied ( processed)  and those  that were n't (unpro cessed)
  7347                // - col lect direc tives from  the templ ate and so rt them by  priority
  7348                // - com bine direc tives as:  processed  + template  + unproce ssed
  7349                var temp lateDirect ives = col lectDirect ives(compi leNode, [] , newTempl ateAttrs);
  7350                var unpr ocessedDir ectives =  directives .splice(i  + 1, direc tives.leng th - (i +  1));
  7351  
  7352                if (newI solateScop eDirective ) {
  7353                  markDi rectivesAs Isolate(te mplateDire ctives);
  7354                }
  7355                directiv es = direc tives.conc at(templat eDirective s).concat( unprocesse dDirective s);
  7356                mergeTem plateAttri butes(temp lateAttrs,  newTempla teAttrs);
  7357  
  7358                ii = dir ectives.le ngth;
  7359              } else {
  7360                $compile Node.html( directiveV alue);
  7361              }
  7362           }
  7363  
  7364           if  (directiv e.template Url) {
  7365              hasTemplat e = true;
  7366              assertNoDu plicate('t emplate',  templateDi rective, d irective,  $compileNo de);
  7367              templateDi rective =  directive;
  7368  
  7369              if (direct ive.replac e) {
  7370                replaceD irective =  directive ;
  7371              }
  7372  
  7373              nodeLinkFn  = compile TemplateUr l(directiv es.splice( i, directi ves.length  - i), $co mpileNode,
  7374                  templa teAttrs, j qCollectio n, hasTran scludeDire ctive && c hildTransc ludeFn, pr eLinkFns,  postLinkFn s, {
  7375                    cont rollerDire ctives: co ntrollerDi rectives,
  7376                    newI solateScop eDirective : newIsola teScopeDir ective,
  7377                    temp lateDirect ive: templ ateDirecti ve,
  7378                    nonT lbTransclu deDirectiv e: nonTlbT ranscludeD irective
  7379                  });
  7380              ii = direc tives.leng th;
  7381           }  else if (d irective.c ompile) {
  7382              try {
  7383                linkFn =  directive .compile($ compileNod e, templat eAttrs, ch ildTranscl udeFn);
  7384                if (isFu nction(lin kFn)) {
  7385                  addLin kFns(null,  linkFn, a ttrStart,  attrEnd);
  7386                } else i f (linkFn)  {
  7387                  addLin kFns(linkF n.pre, lin kFn.post,  attrStart,  attrEnd);
  7388                }
  7389              } catch (e ) {
  7390                $excepti onHandler( e, startin gTag($comp ileNode));
  7391              }
  7392           }
  7393  
  7394           if  (directiv e.terminal ) {
  7395              nodeLinkFn .terminal  = true;
  7396              terminalPr iority = M ath.max(te rminalPrio rity, dire ctive.prio rity);
  7397           }
  7398  
  7399         }
  7400  
  7401         node LinkFn.sco pe = newSc opeDirecti ve && newS copeDirect ive.scope  === true;
  7402         node LinkFn.tra nscludeOnT hisElement  = hasTran scludeDire ctive;
  7403         node LinkFn.ele mentTransc ludeOnThis Element =  hasElement Transclude Directive;
  7404         node LinkFn.tem plateOnThi sElement =  hasTempla te;
  7405         node LinkFn.tra nsclude =  childTrans cludeFn;
  7406  
  7407         prev iousCompil eContext.h asElementT ranscludeD irective =  hasElemen tTransclud eDirective ;
  7408  
  7409         // m ight be no rmal or de layed node LinkFn dep ending on  if templat eUrl is pr esent
  7410         retu rn nodeLin kFn;
  7411  
  7412         //// ////////// //////
  7413  
  7414         func tion addLi nkFns(pre,  post, att rStart, at trEnd) {
  7415           if  (pre) {
  7416              if (attrSt art) pre =  groupElem entsLinkFn Wrapper(pr e, attrSta rt, attrEn d);
  7417              pre.requir e = direct ive.requir e;
  7418              pre.direct iveName =  directiveN ame;
  7419              if (newIso lateScopeD irective = == directi ve || dire ctive.$$is olateScope ) {
  7420                pre = cl oneAndAnno tateFn(pre , {isolate Scope: tru e});
  7421              }
  7422              preLinkFns .push(pre) ;
  7423           }
  7424           if  (post) {
  7425              if (attrSt art) post  = groupEle mentsLinkF nWrapper(p ost, attrS tart, attr End);
  7426              post.requi re = direc tive.requi re;
  7427              post.direc tiveName =  directive Name;
  7428              if (newIso lateScopeD irective = == directi ve || dire ctive.$$is olateScope ) {
  7429                post = c loneAndAnn otateFn(po st, {isola teScope: t rue});
  7430              }
  7431              postLinkFn s.push(pos t);
  7432           }
  7433         }
  7434  
  7435  
  7436         func tion getCo ntrollers( directiveN ame, requi re, $eleme nt, elemen tControlle rs) {
  7437           va r value, r etrievalMe thod = 'da ta', optio nal = fals e;
  7438           va r $searchE lement = $ element;
  7439           va r match;
  7440           if  (isString (require))  {
  7441              match = re quire.matc h(REQUIRE_ PREFIX_REG EXP);
  7442              require =  require.su bstring(ma tch[0].len gth);
  7443  
  7444              if (match[ 3]) {
  7445                if (matc h[1]) matc h[3] = nul l;
  7446                else mat ch[1] = ma tch[3];
  7447              }
  7448              if (match[ 1] === '^' ) {
  7449                retrieva lMethod =  'inherited Data';
  7450              } else if  (match[1]  === '^^')  {
  7451                retrieva lMethod =  'inherited Data';
  7452                $searchE lement = $ element.pa rent();
  7453              }
  7454              if (match[ 2] === '?' ) {
  7455                optional  = true;
  7456              }
  7457  
  7458              value = nu ll;
  7459  
  7460              if (elemen tControlle rs && retr ievalMetho d === 'dat a') {
  7461                if (valu e = elemen tControlle rs[require ]) {
  7462                  value  = value.in stance;
  7463                }
  7464              }
  7465              value = va lue || $se archElemen t[retrieva lMethod](' $' + requi re + 'Cont roller');
  7466  
  7467              if (!value  && !optio nal) {
  7468                throw $c ompileMinE rr('ctreq' ,
  7469                    "Con troller '{ 0}', requi red by dir ective '{1 }', can't  be found!" ,
  7470                    requ ire, direc tiveName);
  7471              }
  7472              return val ue || null ;
  7473           }  else if (i sArray(req uire)) {
  7474              value = [] ;
  7475              forEach(re quire, fun ction(requ ire) {
  7476                value.pu sh(getCont rollers(di rectiveNam e, require , $element , elementC ontrollers ));
  7477              });
  7478           }
  7479           re turn value ;
  7480         }
  7481  
  7482  
  7483         func tion nodeL inkFn(chil dLinkFn, s cope, link Node, $roo tElement,  boundTrans cludeFn) {
  7484           va r i, ii, l inkFn, con troller, i solateScop e, element Controller s, transcl udeFn, $el ement,
  7485                attrs;
  7486  
  7487           if  (compileN ode === li nkNode) {
  7488              attrs = te mplateAttr s;
  7489              $element =  templateA ttrs.$$ele ment;
  7490           }  else {
  7491              $element =  jqLite(li nkNode);
  7492              attrs = ne w Attribut es($elemen t, templat eAttrs);
  7493           }
  7494  
  7495           if  (newIsola teScopeDir ective) {
  7496              isolateSco pe = scope .$new(true );
  7497           }
  7498  
  7499           if  (boundTra nscludeFn)  {
  7500              // track ` boundTrans cludeFn` s o it can b e unwrappe d if `tran scludeFn`
  7501              // is late r passed a s `parentB oundTransc ludeFn` to  `publicLi nkFn`
  7502              transclude Fn = contr ollersBoun dTransclud e;
  7503              transclude Fn.$$bound Transclude  = boundTr anscludeFn ;
  7504           }
  7505  
  7506           if  (controll erDirectiv es) {
  7507              // TODO: m erge `cont rollers` a nd `elemen tControlle rs` into s ingle obje ct.
  7508              controller s = {};
  7509              elementCon trollers =  {};
  7510              forEach(co ntrollerDi rectives,  function(d irective)  {
  7511                var loca ls = {
  7512                  $scope : directiv e === newI solateScop eDirective  || direct ive.$$isol ateScope ?  isolateSc ope : scop e,
  7513                  $eleme nt: $eleme nt,
  7514                  $attrs : attrs,
  7515                  $trans clude: tra nscludeFn
  7516                }, contr ollerInsta nce;
  7517  
  7518                controll er = direc tive.contr oller;
  7519                if (cont roller ==  '@') {
  7520                  contro ller = att rs[directi ve.name];
  7521                }
  7522  
  7523                controll erInstance  = $contro ller(contr oller, loc als, true,  directive .controlle rAs);
  7524  
  7525                // For d irectives  with eleme nt transcl usion the  element is  a comment ,
  7526                // but j Query .dat a doesn't  support at taching da ta to comm ent nodes  as it's ha rd to
  7527                // clean  up (http: //bugs.jqu ery.com/ti cket/8335) .
  7528                // Inste ad, we sav e the cont rollers fo r the elem ent in a l ocal hash  and attach  to .data
  7529                // later , once we  have the a ctual elem ent.
  7530                elementC ontrollers [directive .name] = c ontrollerI nstance;
  7531                if (!has ElementTra nscludeDir ective) {
  7532                  $eleme nt.data('$ ' + direct ive.name +  'Controll er', contr ollerInsta nce.instan ce);
  7533                }
  7534  
  7535                controll ers[direct ive.name]  = controll erInstance ;
  7536              });
  7537           }
  7538  
  7539           if  (newIsola teScopeDir ective) {
  7540              compile.$$ addScopeIn fo($elemen t, isolate Scope, tru e, !(templ ateDirecti ve && (tem plateDirec tive === n ewIsolateS copeDirect ive ||
  7541                  templa teDirectiv e === newI solateScop eDirective .$$origina lDirective )));
  7542              compile.$$ addScopeCl ass($eleme nt, true);
  7543  
  7544              var isolat eScopeCont roller = c ontrollers  && contro llers[newI solateScop eDirective .name];
  7545              var isolat eBindingCo ntext = is olateScope ;
  7546              if (isolat eScopeCont roller &&  isolateSco peControll er.identif ier &&
  7547                  newIso lateScopeD irective.b indToContr oller ===  true) {
  7548                isolateB indingCont ext = isol ateScopeCo ntroller.i nstance;
  7549              }
  7550  
  7551              forEach(is olateScope .$$isolate Bindings =  newIsolat eScopeDire ctive.$$is olateBindi ngs, funct ion(defini tion, scop eName) {
  7552                var attr Name = def inition.at trName,
  7553                    opti onal = def inition.op tional,
  7554                    mode  = definit ion.mode,  // @, =, o r &
  7555                    last Value,
  7556                    pare ntGet, par entSet, co mpare;
  7557  
  7558                switch ( mode) {
  7559  
  7560                  case ' @':
  7561                    attr s.$observe (attrName,  function( value) {
  7562                      is olateBindi ngContext[ scopeName]  = value;
  7563                    });
  7564                    attr s.$$observ ers[attrNa me].$$scop e = scope;
  7565                    if ( attrs[attr Name]) {
  7566                      //  If the at tribute ha s been pro vided then  we trigge r an inter polation t o ensure
  7567                      //  the value  is there  for use in  the link  fn
  7568                      is olateBindi ngContext[ scopeName]  = $interp olate(attr s[attrName ])(scope);
  7569                    }
  7570                    brea k;
  7571  
  7572                  case ' =':
  7573                    if ( optional & & !attrs[a ttrName])  {
  7574                      re turn;
  7575                    }
  7576                    pare ntGet = $p arse(attrs [attrName] );
  7577                    if ( parentGet. literal) {
  7578                      co mpare = eq uals;
  7579                    } el se {
  7580                      co mpare = fu nction(a,  b) { retur n a === b  || (a !==  a && b !==  b); };
  7581                    }
  7582                    pare ntSet = pa rentGet.as sign || fu nction() {
  7583                      //  reset the  change, o r we will  throw this  exception  on every  $digest
  7584                      la stValue =  isolateBin dingContex t[scopeNam e] = paren tGet(scope );
  7585                      th row $compi leMinErr(' nonassign' ,
  7586                           "Express ion '{0}'  used with  directive  '{1}' is n on-assigna ble!",
  7587                           attrs[at trName], n ewIsolateS copeDirect ive.name);
  7588                    };
  7589                    last Value = is olateBindi ngContext[ scopeName]  = parentG et(scope);
  7590                    var  parentValu eWatch = f unction pa rentValueW atch(paren tValue) {
  7591                      if  (!compare (parentVal ue, isolat eBindingCo ntext[scop eName])) {
  7592                         // we are  out of syn c and need  to copy
  7593                         if (!compa re(parentV alue, last Value)) {
  7594                           // paren t changed  and it has  precedenc e
  7595                           isolateB indingCont ext[scopeN ame] = par entValue;
  7596                         } else {
  7597                           // if th e parent c an be assi gned then  do so
  7598                           parentSe t(scope, p arentValue  = isolate BindingCon text[scope Name]);
  7599                         }
  7600                      }
  7601                      re turn lastV alue = par entValue;
  7602                    };
  7603                    pare ntValueWat ch.$statef ul = true;
  7604                    var  unwatch;
  7605                    if ( definition .collectio n) {
  7606                      un watch = sc ope.$watch Collection (attrs[att rName], pa rentValueW atch);
  7607                    } el se {
  7608                      un watch = sc ope.$watch ($parse(at trs[attrNa me], paren tValueWatc h), null,  parentGet. literal);
  7609                    }
  7610                    isol ateScope.$ on('$destr oy', unwat ch);
  7611                    brea k;
  7612  
  7613                  case ' &':
  7614                    pare ntGet = $p arse(attrs [attrName] );
  7615                    isol ateBinding Context[sc opeName] =  function( locals) {
  7616                      re turn paren tGet(scope , locals);
  7617                    };
  7618                    brea k;
  7619                }
  7620              });
  7621           }
  7622           if  (controll ers) {
  7623              forEach(co ntrollers,  function( controller ) {
  7624                controll er();
  7625              });
  7626              controller s = null;
  7627           }
  7628  
  7629           //  PRELINKIN G
  7630           fo r (i = 0,  ii = preLi nkFns.leng th; i < ii ; i++) {
  7631              linkFn = p reLinkFns[ i];
  7632              invokeLink Fn(linkFn,
  7633                  linkFn .isolateSc ope ? isol ateScope :  scope,
  7634                  $eleme nt,
  7635                  attrs,
  7636                  linkFn .require & & getContr ollers(lin kFn.direct iveName, l inkFn.requ ire, $elem ent, eleme ntControll ers),
  7637                  transc ludeFn
  7638              );
  7639           }
  7640  
  7641           //  RECURSION
  7642           //  We only p ass the is olate scop e, if the  isolate di rective ha s a templa te,
  7643           //  otherwise  the child  elements  do not bel ong to the  isolate d irective.
  7644           va r scopeToC hild = sco pe;
  7645           if  (newIsola teScopeDir ective &&  (newIsolat eScopeDire ctive.temp late || ne wIsolateSc opeDirecti ve.templat eUrl === n ull)) {
  7646              scopeToChi ld = isola teScope;
  7647           }
  7648           ch ildLinkFn  && childLi nkFn(scope ToChild, l inkNode.ch ildNodes,  undefined,  boundTran scludeFn);
  7649  
  7650           //  POSTLINKI NG
  7651           fo r (i = pos tLinkFns.l ength - 1;  i >= 0; i --) {
  7652              linkFn = p ostLinkFns [i];
  7653              invokeLink Fn(linkFn,
  7654                  linkFn .isolateSc ope ? isol ateScope :  scope,
  7655                  $eleme nt,
  7656                  attrs,
  7657                  linkFn .require & & getContr ollers(lin kFn.direct iveName, l inkFn.requ ire, $elem ent, eleme ntControll ers),
  7658                  transc ludeFn
  7659              );
  7660           }
  7661  
  7662           //  This is t he functio n that is  injected a s `$transc lude`.
  7663           //  Note: all  arguments  are optio nal!
  7664           fu nction con trollersBo undTranscl ude(scope,  cloneAtta chFn, futu reParentEl ement) {
  7665              var transc ludeContro llers;
  7666  
  7667              // No scop e passed i n:
  7668              if (!isSco pe(scope))  {
  7669                futurePa rentElemen t = cloneA ttachFn;
  7670                cloneAtt achFn = sc ope;
  7671                scope =  undefined;
  7672              }
  7673  
  7674              if (hasEle mentTransc ludeDirect ive) {
  7675                transclu deControll ers = elem entControl lers;
  7676              }
  7677              if (!futur eParentEle ment) {
  7678                futurePa rentElemen t = hasEle mentTransc ludeDirect ive ? $ele ment.paren t() : $ele ment;
  7679              }
  7680              return bou ndTransclu deFn(scope , cloneAtt achFn, tra nscludeCon trollers,  futurePare ntElement,  scopeToCh ild);
  7681           }
  7682         }
  7683       }
  7684  
  7685       functi on markDir ectivesAsI solate(dir ectives) {
  7686         // m ark all di rectives a s needing  isolate sc ope.
  7687         for  (var j = 0 , jj = dir ectives.le ngth; j <  jj; j++) {
  7688           di rectives[j ] = inheri t(directiv es[j], {$$ isolateSco pe: true}) ;
  7689         }
  7690       }
  7691  
  7692       /**
  7693        * loo ks up the  directive  and decora tes it wit h exceptio n handling  and prope r paramete rs. We
  7694        * cal l this the  boundDire ctive.
  7695        *
  7696        * @pa ram {strin g} name na me of the  directive  to look up .
  7697        * @pa ram {strin g} locatio n The dire ctive must  be found  in specifi c format.
  7698        *   S tring cont aining any  of theses  character s:
  7699        *
  7700        *   *  `E`: elem ent name
  7701        *   *  `A': attr ibute
  7702        *   *  `C`: clas s
  7703        *   *  `M`: comm ent
  7704        * @re turns {boo lean} true  if direct ive was ad ded.
  7705        */
  7706       functi on addDire ctive(tDir ectives, n ame, locat ion, maxPr iority, ig noreDirect ive, start AttrName,
  7707                               endA ttrName) {
  7708         if ( name === i gnoreDirec tive) retu rn null;
  7709         var  match = nu ll;
  7710         if ( hasDirecti ves.hasOwn Property(n ame)) {
  7711           fo r (var dir ective, di rectives =  $injector .get(name  + Suffix),
  7712                i = 0, i i = direct ives.lengt h; i < ii;  i++) {
  7713              try {
  7714                directiv e = direct ives[i];
  7715                if ((max Priority = == undefin ed || maxP riority >  directive. priority)  &&
  7716                     dir ective.res trict.inde xOf(locati on) != -1)  {
  7717                  if (st artAttrNam e) {
  7718                    dire ctive = in herit(dire ctive, {$$ start: sta rtAttrName , $$end: e ndAttrName });
  7719                  }
  7720                  tDirec tives.push (directive );
  7721                  match  = directiv e;
  7722                }
  7723              } catch (e ) { $excep tionHandle r(e); }
  7724           }
  7725         }
  7726         retu rn match;
  7727       }
  7728  
  7729  
  7730       /**
  7731        * loo ks up the  directive  and return s true if  it is a mu lti-elemen t directiv e,
  7732        * and  therefore  requires  DOM nodes  between -s tart and - end marker s to be gr ouped
  7733        * tog ether.
  7734        *
  7735        * @pa ram {strin g} name na me of the  directive  to look up .
  7736        * @re turns true  if direct ive was re gistered a s multi-el ement.
  7737        */
  7738       functi on directi veIsMultiE lement(nam e) {
  7739         if ( hasDirecti ves.hasOwn Property(n ame)) {
  7740           fo r (var dir ective, di rectives =  $injector .get(name  + Suffix),
  7741                i = 0, i i = direct ives.lengt h; i < ii;  i++) {
  7742              directive  = directiv es[i];
  7743              if (direct ive.multiE lement) {
  7744                return t rue;
  7745              }
  7746           }
  7747         }
  7748         retu rn false;
  7749       }
  7750  
  7751       /**
  7752        * Whe n the elem ent is rep laced with  HTML temp late then  the new at tributes
  7753        * on  the templa te need to  be merged  with the  existing a ttributes  in the DOM .
  7754        * The  desired e ffect is t o have bot h of the a ttributes  present.
  7755        *
  7756        * @pa ram {objec t} dst des tination a ttributes  (original  DOM)
  7757        * @pa ram {objec t} src sou rce attrib utes (from  the direc tive templ ate)
  7758        */
  7759       functi on mergeTe mplateAttr ibutes(dst , src) {
  7760         var  srcAttr =  src.$attr,
  7761              dstAttr =  dst.$attr,
  7762              $element =  dst.$$ele ment;
  7763  
  7764         // r eapply the  old attri butes to t he new ele ment
  7765         forE ach(dst, f unction(va lue, key)  {
  7766           if  (key.char At(0) != ' $') {
  7767              if (src[ke y] && src[ key] !== v alue) {
  7768                value +=  (key ===  'style' ?  ';' : ' ')  + src[key ];
  7769              }
  7770              dst.$set(k ey, value,  true, src Attr[key]) ;
  7771           }
  7772         });
  7773  
  7774         // c opy the ne w attribut es on the  old attrs  object
  7775         forE ach(src, f unction(va lue, key)  {
  7776           if  (key == ' class') {
  7777              safeAddCla ss($elemen t, value);
  7778              dst['class '] = (dst[ 'class'] ?  dst['clas s'] + ' '  : '') + va lue;
  7779           }  else if (k ey == 'sty le') {
  7780              $element.a ttr('style ', $elemen t.attr('st yle') + '; ' + value) ;
  7781              dst['style '] = (dst[ 'style'] ?  dst['styl e'] + ';'  : '') + va lue;
  7782              // `dst` w ill never  contain ha sOwnProper ty as DOM  parser won 't let it.
  7783              // You wil l get an " InvalidCha racterErro r: DOM Exc eption 5"  error if y ou
  7784              // have an  attribute  like "has -own-prope rty" or "d ata-has-ow n-property ", etc.
  7785           }  else if (k ey.charAt( 0) != '$'  && !dst.ha sOwnProper ty(key)) {
  7786              dst[key] =  value;
  7787              dstAttr[ke y] = srcAt tr[key];
  7788           }
  7789         });
  7790       }
  7791  
  7792  
  7793       functi on compile TemplateUr l(directiv es, $compi leNode, tA ttrs,
  7794           $r ootElement , childTra nscludeFn,  preLinkFn s, postLin kFns, prev iousCompil eContext)  {
  7795         var  linkQueue  = [],
  7796              afterTempl ateNodeLin kFn,
  7797              afterTempl ateChildLi nkFn,
  7798              beforeTemp lateCompil eNode = $c ompileNode [0],
  7799              origAsyncD irective =  directive s.shift(),
  7800              // The fac t that we  have to co py and pat ch the dir ective see ms wrong!
  7801              derivedSyn cDirective  = extend( {}, origAs yncDirecti ve, {
  7802                template Url: null,  transclud e: null, r eplace: nu ll, $$orig inalDirect ive: origA syncDirect ive
  7803              }),
  7804              templateUr l = (isFun ction(orig AsyncDirec tive.templ ateUrl))
  7805                  ? orig AsyncDirec tive.templ ateUrl($co mpileNode,  tAttrs)
  7806                  : orig AsyncDirec tive.templ ateUrl,
  7807              templateNa mespace =  origAsyncD irective.t emplateNam espace;
  7808  
  7809         $com pileNode.e mpty();
  7810  
  7811         $tem plateReque st($sce.ge tTrustedRe sourceUrl( templateUr l))
  7812           .t hen(functi on(content ) {
  7813              var compil eNode, tem pTemplateA ttrs, $tem plate, chi ldBoundTra nscludeFn;
  7814  
  7815              content =  denormaliz eTemplate( content);
  7816  
  7817              if (origAs yncDirecti ve.replace ) {
  7818                if (jqLi teIsTextNo de(content )) {
  7819                  $templ ate = [];
  7820                } else {
  7821                  $templ ate = remo veComments (wrapTempl ate(templa teNamespac e, trim(co ntent)));
  7822                }
  7823                compileN ode = $tem plate[0];
  7824  
  7825                if ($tem plate.leng th != 1 ||  compileNo de.nodeTyp e !== NODE _TYPE_ELEM ENT) {
  7826                  throw  $compileMi nErr('tplr t',
  7827                      "T emplate fo r directiv e '{0}' mu st have ex actly one  root eleme nt. {1}",
  7828                      or igAsyncDir ective.nam e, templat eUrl);
  7829                }
  7830  
  7831                tempTemp lateAttrs  = {$attr:  {}};
  7832                replaceW ith($rootE lement, $c ompileNode , compileN ode);
  7833                var temp lateDirect ives = col lectDirect ives(compi leNode, [] , tempTemp lateAttrs) ;
  7834  
  7835                if (isOb ject(origA syncDirect ive.scope) ) {
  7836                  markDi rectivesAs Isolate(te mplateDire ctives);
  7837                }
  7838                directiv es = templ ateDirecti ves.concat (directive s);
  7839                mergeTem plateAttri butes(tAtt rs, tempTe mplateAttr s);
  7840              } else {
  7841                compileN ode = befo reTemplate CompileNod e;
  7842                $compile Node.html( content);
  7843              }
  7844  
  7845              directives .unshift(d erivedSync Directive) ;
  7846  
  7847              afterTempl ateNodeLin kFn = appl yDirective sToNode(di rectives,  compileNod e, tAttrs,
  7848                  childT ranscludeF n, $compil eNode, ori gAsyncDire ctive, pre LinkFns, p ostLinkFns ,
  7849                  previo usCompileC ontext);
  7850              forEach($r ootElement , function (node, i)  {
  7851                if (node  == compil eNode) {
  7852                  $rootE lement[i]  = $compile Node[0];
  7853                }
  7854              });
  7855              afterTempl ateChildLi nkFn = com pileNodes( $compileNo de[0].chil dNodes, ch ildTranscl udeFn);
  7856  
  7857              while (lin kQueue.len gth) {
  7858                var scop e = linkQu eue.shift( ),
  7859                    befo reTemplate LinkNode =  linkQueue .shift(),
  7860                    link RootElemen t = linkQu eue.shift( ),
  7861                    boun dTransclud eFn = link Queue.shif t(),
  7862                    link Node = $co mpileNode[ 0];
  7863  
  7864                if (scop e.$$destro yed) conti nue;
  7865  
  7866                if (befo reTemplate LinkNode ! == beforeT emplateCom pileNode)  {
  7867                  var ol dClasses =  beforeTem plateLinkN ode.classN ame;
  7868  
  7869                  if (!( previousCo mpileConte xt.hasElem entTranscl udeDirecti ve &&
  7870                      or igAsyncDir ective.rep lace)) {
  7871                    // i t was clon ed therefo re we have  to clone  as well.
  7872                    link Node = jqL iteClone(c ompileNode );
  7873                  }
  7874                  replac eWith(link RootElemen t, jqLite( beforeTemp lateLinkNo de), linkN ode);
  7875  
  7876                  // Cop y in CSS c lasses fro m original  node
  7877                  safeAd dClass(jqL ite(linkNo de), oldCl asses);
  7878                }
  7879                if (afte rTemplateN odeLinkFn. transclude OnThisElem ent) {
  7880                  childB oundTransc ludeFn = c reateBound Transclude Fn(scope,  afterTempl ateNodeLin kFn.transc lude, boun dTransclud eFn);
  7881                } else {
  7882                  childB oundTransc ludeFn = b oundTransc ludeFn;
  7883                }
  7884                afterTem plateNodeL inkFn(afte rTemplateC hildLinkFn , scope, l inkNode, $ rootElemen t,
  7885                  childB oundTransc ludeFn);
  7886              }
  7887              linkQueue  = null;
  7888           }) ;
  7889  
  7890         retu rn functio n delayedN odeLinkFn( ignoreChil dLinkFn, s cope, node , rootElem ent, bound Transclude Fn) {
  7891           va r childBou ndTransclu deFn = bou ndTransclu deFn;
  7892           if  (scope.$$ destroyed)  return;
  7893           if  (linkQueu e) {
  7894              linkQueue. push(scope ,
  7895                              node,
  7896                              rootE lement,
  7897                              child BoundTrans cludeFn);
  7898           }  else {
  7899              if (afterT emplateNod eLinkFn.tr anscludeOn ThisElemen t) {
  7900                childBou ndTransclu deFn = cre ateBoundTr anscludeFn (scope, af terTemplat eNodeLinkF n.transclu de, boundT ranscludeF n);
  7901              }
  7902              afterTempl ateNodeLin kFn(afterT emplateChi ldLinkFn,  scope, nod e, rootEle ment, chil dBoundTran scludeFn);
  7903           }
  7904         };
  7905       }
  7906  
  7907  
  7908       /**
  7909        * Sor ting funct ion for bo und direct ives.
  7910        */
  7911       functi on byPrior ity(a, b)  {
  7912         var  diff = b.p riority -  a.priority ;
  7913         if ( diff !== 0 ) return d iff;
  7914         if ( a.name !==  b.name) r eturn (a.n ame < b.na me) ? -1 :  1;
  7915         retu rn a.index  - b.index ;
  7916       }
  7917  
  7918  
  7919       functi on assertN oDuplicate (what, pre viousDirec tive, dire ctive, ele ment) {
  7920         if ( previousDi rective) {
  7921           th row $compi leMinErr(' multidir',  'Multiple  directive s [{0}, {1 }] asking  for {2} on : {3}',
  7922                previous Directive. name, dire ctive.name , what, st artingTag( element));
  7923         }
  7924       }
  7925  
  7926  
  7927       functi on addText Interpolat eDirective (directive s, text) {
  7928         var  interpolat eFn = $int erpolate(t ext, true) ;
  7929         if ( interpolat eFn) {
  7930           di rectives.p ush({
  7931              priority:  0,
  7932              compile: f unction te xtInterpol ateCompile Fn(templat eNode) {
  7933                var temp lateNodePa rent = tem plateNode. parent(),
  7934                    hasC ompilePare nt = !!tem plateNodeP arent.leng th;
  7935  
  7936                // When  transcludi ng a templ ate that h as binding s in the r oot
  7937                // we do n't have a  parent an d thus nee d to add t he class d uring link ing fn.
  7938                if (hasC ompilePare nt) compil e.$$addBin dingClass( templateNo deParent);
  7939  
  7940                return f unction te xtInterpol ateLinkFn( scope, nod e) {
  7941                  var pa rent = nod e.parent() ;
  7942                  if (!h asCompileP arent) com pile.$$add BindingCla ss(parent) ;
  7943                  compil e.$$addBin dingInfo(p arent, int erpolateFn .expressio ns);
  7944                  scope. $watch(int erpolateFn , function  interpola teFnWatchA ction(valu e) {
  7945                    node [0].nodeVa lue = valu e;
  7946                  });
  7947                };
  7948              }
  7949           }) ;
  7950         }
  7951       }
  7952  
  7953  
  7954       functi on wrapTem plate(type , template ) {
  7955         type  = lowerca se(type ||  'html');
  7956         swit ch (type)  {
  7957         case  'svg':
  7958         case  'math':
  7959           va r wrapper  = document .createEle ment('div' );
  7960           wr apper.inne rHTML = '< ' + type +  '>' + tem plate + '< /' + type  + '>';
  7961           re turn wrapp er.childNo des[0].chi ldNodes;
  7962         defa ult:
  7963           re turn templ ate;
  7964         }
  7965       }
  7966  
  7967  
  7968       functi on getTrus tedContext (node, att rNormalize dName) {
  7969         if ( attrNormal izedName = = "srcdoc" ) {
  7970           re turn $sce. HTML;
  7971         }
  7972         var  tag = node Name_(node );
  7973         // m action[xli nk:href] c an source  SVG.  It's  not limit ed to <mac tion>.
  7974         if ( attrNormal izedName = = "xlinkHr ef" ||
  7975              (tag == "f orm" && at trNormaliz edName ==  "action")  ||
  7976              (tag != "i mg" && (at trNormaliz edName ==  "src" ||
  7977                                 at trNormaliz edName ==  "ngSrc")))  {
  7978           re turn $sce. RESOURCE_U RL;
  7979         }
  7980       }
  7981  
  7982  
  7983       functi on addAttr Interpolat eDirective (node, dir ectives, v alue, name , allOrNot hing) {
  7984         var  interpolat eFn = $int erpolate(v alue, true );
  7985  
  7986         // n o interpol ation foun d -> ignor e
  7987         if ( !interpola teFn) retu rn;
  7988  
  7989  
  7990         if ( name === " multiple"  && nodeNam e_(node) = == "select ") {
  7991           th row $compi leMinErr(" selmulti",
  7992                "Binding  to the 'm ultiple' a ttribute i s not supp orted. Ele ment: {0}" ,
  7993                starting Tag(node)) ;
  7994         }
  7995  
  7996         dire ctives.pus h({
  7997           pr iority: 10 0,
  7998           co mpile: fun ction() {
  7999                return {
  8000                  pre: f unction at trInterpol atePreLink Fn(scope,  element, a ttr) {
  8001                    var  $$observer s = (attr. $$observer s || (attr .$$observe rs = {}));
  8002  
  8003                    if ( EVENT_HAND LER_ATTR_R EGEXP.test (name)) {
  8004                      th row $compi leMinErr(' nodomevent s',
  8005                           "Interpo lations fo r HTML DOM  event att ributes ar e disallow ed.  Pleas e use the  " +
  8006                               "ng-  versions  (such as n g-click in stead of o nclick) in stead.");
  8007                    }
  8008  
  8009                    // I f the attr ibute was  removed, t hen we are  done
  8010                    if ( !attr[name ]) {
  8011                      re turn;
  8012                    }
  8013  
  8014                    // w e need to  interpolat e again, i n case the  attribute  value has  been upda ted
  8015                    // ( e.g. by an other dire ctive's co mpile func tion)
  8016                    inte rpolateFn  = $interpo late(attr[ name], tru e, getTrus tedContext (node, nam e),
  8017                         ALL_OR_NOT HING_ATTRS [name] ||  allOrNothi ng);
  8018  
  8019                    // i f attribut e was upda ted so tha t there is  no interp olation go ing on we  don't want  to
  8020                    // r egister an y observer s
  8021                    if ( !interpola teFn) retu rn;
  8022  
  8023                    // i nitialize  attr objec t so that  it's ready  in case w e need the  value for  isolate
  8024                    // s cope initi alization,  otherwise  the value  would not  be availa ble from i solate
  8025                    // d irective's  linking f n during l inking pha se
  8026                    attr [name] = i nterpolate Fn(scope);
  8027  
  8028                    ($$o bservers[n ame] || ($ $observers [name] = [ ])).$$inte r = true;
  8029                    (att r.$$observ ers && att r.$$observ ers[name]. $$scope ||  scope).
  8030                      $w atch(inter polateFn,  function i nterpolate FnWatchAct ion(newVal ue, oldVal ue) {
  8031                         //special  case for c lass attri bute addit ion + remo val
  8032                         //so that  class chan ges can ta p into the  animation
  8033                         //hooks pr ovided by  the $anima te service . Be sure  to
  8034                         //skip ani mations wh en the fir st digest  occurs (wh en
  8035                         //both the  new and t he old val ues are th e same) si nce
  8036                         //the CSS  classes ar e the non- interpolat ed values
  8037                         if (name = == 'class'  && newVal ue != oldV alue) {
  8038                           attr.$up dateClass( newValue,  oldValue);
  8039                         } else {
  8040                           attr.$se t(name, ne wValue);
  8041                         }
  8042                      }) ;
  8043                  }
  8044                };
  8045              }
  8046         });
  8047       }
  8048  
  8049  
  8050       /**
  8051        * Thi s is a spe cial jqLit e.replaceW ith, which  can repla ce items w hich
  8052        * hav e no paren ts, provid ed that th e containi ng jqLite  collection  is provid ed.
  8053        *
  8054        * @pa ram {JqLit e=} $rootE lement The  root of t he compile  tree. Use d so that  we can rep lace nodes
  8055        *                                  in  the root o f the tree .
  8056        * @pa ram {JqLit e} element sToRemove  The jqLite  element w hich we ar e going to  replace.  We keep
  8057        *                                      the shell,  but repla ce its DOM  node refe rence.
  8058        * @pa ram {Node}  newNode T he new DOM  node.
  8059        */
  8060       functi on replace With($root Element, e lementsToR emove, new Node) {
  8061         var  firstEleme ntToRemove  = element sToRemove[ 0],
  8062              removeCoun t = elemen tsToRemove .length,
  8063              parent = f irstElemen tToRemove. parentNode ,
  8064              i, ii;
  8065  
  8066         if ( $rootEleme nt) {
  8067           fo r (i = 0,  ii = $root Element.le ngth; i <  ii; i++) {
  8068              if ($rootE lement[i]  == firstEl ementToRem ove) {
  8069                $rootEle ment[i++]  = newNode;
  8070                for (var  j = i, j2  = j + rem oveCount -  1,
  8071                          jj = $roo tElement.l ength;
  8072                     j <  jj; j++,  j2++) {
  8073                  if (j2  < jj) {
  8074                    $roo tElement[j ] = $rootE lement[j2] ;
  8075                  } else  {
  8076                    dele te $rootEl ement[j];
  8077                  }
  8078                }
  8079                $rootEle ment.lengt h -= remov eCount - 1 ;
  8080  
  8081                // If th e replaced  element i s also the  jQuery .c ontext the n replace  it
  8082                // .cont ext is a d eprecated  jQuery api , so we sh ould set i t only whe n jQuery s et it
  8083                // http: //api.jque ry.com/con text/
  8084                if ($roo tElement.c ontext ===  firstElem entToRemov e) {
  8085                  $rootE lement.con text = new Node;
  8086                }
  8087                break;
  8088              }
  8089           }
  8090         }
  8091  
  8092         if ( parent) {
  8093           pa rent.repla ceChild(ne wNode, fir stElementT oRemove);
  8094         }
  8095  
  8096         // T ODO(perf):  what's th is documen t fragment  for? is i t needed?  can we at  least reus e it?
  8097         var  fragment =  document. createDocu mentFragme nt();
  8098         frag ment.appen dChild(fir stElementT oRemove);
  8099  
  8100         // C opy over u ser data ( that inclu des Angula r's $scope  etc.). Do n't copy p rivate
  8101         // d ata here b ecause the re's no pu blic inter face in jQ uery to do  that and  copying ov er
  8102         // e vent liste ners (whic h is the m ain use of  private d ata) would n't work a nyway.
  8103         jqLi te(newNode ).data(jqL ite(firstE lementToRe move).data ());
  8104  
  8105         // R emove data  of the re placed ele ment. We c annot just  call .rem ove()
  8106         // o n the elem ent it sin ce that wo uld deallo cate scope  that is n eeded
  8107         // f or the new  node. Ins tead, remo ve the dat a "manuall y".
  8108         if ( !jQuery) {
  8109           de lete jqLit e.cache[fi rstElement ToRemove[j qLite.expa ndo]];
  8110         } el se {
  8111           //  jQuery 2. x doesn't  expose the  data stor age. Use j Query.clea nData to c lean up af ter
  8112           //  the repla ced elemen t. The cle anData ver sion monke y-patched  by Angular  would cau se
  8113           //  the scope  to be tra shed and w e do need  the very s ame scope  to work wi th the new
  8114           //  element.  However, w e cannot j ust cache  the non-pa tched vers ion and us e it here  as
  8115           //  that woul d break if  another l ibrary pat ches the m ethod afte r Angular  does (one
  8116           //  example i s jQuery U I). Instea d, set a f lag indica ting scope  destroyin g should b e
  8117           //  skipped t his one ti me.
  8118           sk ipDestroyO nNextJQuer yCleanData  = true;
  8119           jQ uery.clean Data([firs tElementTo Remove]);
  8120         }
  8121  
  8122         for  (var k = 1 , kk = ele mentsToRem ove.length ; k < kk;  k++) {
  8123           va r element  = elements ToRemove[k ];
  8124           jq Lite(eleme nt).remove (); // mus t do this  way to cle an up expa ndo
  8125           fr agment.app endChild(e lement);
  8126           de lete eleme ntsToRemov e[k];
  8127         }
  8128  
  8129         elem entsToRemo ve[0] = ne wNode;
  8130         elem entsToRemo ve.length  = 1;
  8131       }
  8132  
  8133  
  8134       functi on cloneAn dAnnotateF n(fn, anno tation) {
  8135         retu rn extend( function()  { return  fn.apply(n ull, argum ents); },  fn, annota tion);
  8136       }
  8137  
  8138  
  8139       functi on invokeL inkFn(link Fn, scope,  $element,  attrs, co ntrollers,  transclud eFn) {
  8140         try  {
  8141           li nkFn(scope , $element , attrs, c ontrollers , transclu deFn);
  8142         } ca tch (e) {
  8143           $e xceptionHa ndler(e, s tartingTag ($element) );
  8144         }
  8145       }
  8146     }];
  8147   }
  8148  
  8149   var PREFIX _REGEXP =  /^((?:x|da ta)[\:\-_] )/i;
  8150   /**
  8151    * Convert s all acce pted direc tives form at into pr oper direc tive name.
  8152    * All of  these will  become 'm yDirective ':
  8153    *   my:Di rective
  8154    *   my-di rective
  8155    *   x-my- directive
  8156    *   data- my:directi ve
  8157    *
  8158    * Also th ere is spe cial case  for Moz pr efix start ing with u pper case  letter.
  8159    * @param  name Name  to normali ze
  8160    */
  8161   function d irectiveNo rmalize(na me) {
  8162     return c amelCase(n ame.replac e(PREFIX_R EGEXP, '') );
  8163   }
  8164  
  8165   /**
  8166    * @ngdoc  type
  8167    * @name $ compile.di rective.At tributes
  8168    *
  8169    * @descri ption
  8170    * A share d object b etween dir ective com pile / lin king funct ions which  contains  normalized  DOM
  8171    * element  attribute s. The val ues reflec t current  binding st ate `{{ }} `. The nor malization  is
  8172    * needed  since all  of these a re treated  as equiva lent in An gular:
  8173    *
  8174    * ```
  8175    *    <spa n ng:bind= "a" ng-bin d="a" data -ng-bind=" a" x-ng-bi nd="a">
  8176    * ```
  8177    */
  8178  
  8179   /**
  8180    * @ngdoc  property
  8181    * @name $ compile.di rective.At tributes#$ attr
  8182    *
  8183    * @descri ption
  8184    * A map o f DOM elem ent attrib ute names  to the nor malized na me. This i s
  8185    * needed  to do reve rse lookup  from norm alized nam e back to  actual nam e.
  8186    */
  8187  
  8188  
  8189   /**
  8190    * @ngdoc  method
  8191    * @name $ compile.di rective.At tributes#$ set
  8192    * @kind f unction
  8193    *
  8194    * @descri ption
  8195    * Set DOM  element a ttribute v alue.
  8196    *
  8197    *
  8198    * @param  {string} n ame Normal ized eleme nt attribu te name of  the prope rty to mod ify. The n ame is
  8199    *           reverse- translated  using the  {@link ng .$compile. directive. Attributes #$attr $at tr}
  8200    *           property  to the or iginal nam e.
  8201    * @param  {string} v alue Value  to set th e attribut e to. The  value can  be an inte rpolated s tring.
  8202    */
  8203  
  8204  
  8205  
  8206   /**
  8207    * Closure  compiler  type infor mation
  8208    */
  8209  
  8210   function n odesetLink ingFn(
  8211     /* angul ar.Scope * / scope,
  8212     /* NodeL ist */ nod eList,
  8213     /* Eleme nt */ root Element,
  8214     /* funct ion(Functi on) */ bou ndTransclu deFn
  8215   ) {}
  8216  
  8217   function d irectiveLi nkingFn(
  8218     /* nodes etLinkingF n */ nodes etLinkingF n,
  8219     /* angul ar.Scope * / scope,
  8220     /* Node  */ node,
  8221     /* Eleme nt */ root Element,
  8222     /* funct ion(Functi on) */ bou ndTransclu deFn
  8223   ) {}
  8224  
  8225   function t okenDiffer ence(str1,  str2) {
  8226     var valu es = '',
  8227         toke ns1 = str1 .split(/\s +/),
  8228         toke ns2 = str2 .split(/\s +/);
  8229  
  8230     outer:
  8231     for (var  i = 0; i  < tokens1. length; i+ +) {
  8232       var to ken = toke ns1[i];
  8233       for (v ar j = 0;  j < tokens 2.length;  j++) {
  8234         if ( token == t okens2[j])  continue  outer;
  8235       }
  8236       values  += (value s.length >  0 ? ' ' :  '') + tok en;
  8237     }
  8238     return v alues;
  8239   }
  8240  
  8241   function r emoveComme nts(jqNode s) {
  8242     jqNodes  = jqLite(j qNodes);
  8243     var i =  jqNodes.le ngth;
  8244  
  8245     if (i <=  1) {
  8246       return  jqNodes;
  8247     }
  8248  
  8249     while (i --) {
  8250       var no de = jqNod es[i];
  8251       if (no de.nodeTyp e === NODE _TYPE_COMM ENT) {
  8252         spli ce.call(jq Nodes, i,  1);
  8253       }
  8254     }
  8255     return j qNodes;
  8256   }
  8257  
  8258   /**
  8259    * @ngdoc  provider
  8260    * @name $ controller Provider
  8261    * @descri ption
  8262    * The {@l ink ng.$co ntroller $ controller  service}  is used by  Angular t o create n ew
  8263    * control lers.
  8264    *
  8265    * This pr ovider all ows contro ller regis tration vi a the
  8266    * {@link  ng.$contro llerProvid er#registe r register } method.
  8267    */
  8268   function $ Controller Provider()  {
  8269     var cont rollers =  {},
  8270         glob als = fals e,
  8271         CNTR L_REG = /^ (\S+)(\s+a s\s+(\w+)) ?$/;
  8272  
  8273  
  8274     /**
  8275      * @ngdo c method
  8276      * @name  $controll erProvider #register
  8277      * @para m {string| Object} na me Control ler name,  or an obje ct map of  controller s where th e keys are
  8278      *    th e names an d the valu es are the  construct ors.
  8279      * @para m {Functio n|Array} c onstructor  Controlle r construc tor fn (op tionally d ecorated w ith DI
  8280      *    an notations  in the arr ay notatio n).
  8281      */
  8282     this.reg ister = fu nction(nam e, constru ctor) {
  8283       assert NotHasOwnP roperty(na me, 'contr oller');
  8284       if (is Object(nam e)) {
  8285         exte nd(control lers, name );
  8286       } else  {
  8287         cont rollers[na me] = cons tructor;
  8288       }
  8289     };
  8290  
  8291     /**
  8292      * @ngdo c method
  8293      * @name  $controll erProvider #allowGlob als
  8294      * @desc ription If  called, a llows `$co ntroller`  to find co ntroller c onstructor s on `wind ow`
  8295      */
  8296     this.all owGlobals  = function () {
  8297       global s = true;
  8298     };
  8299  
  8300  
  8301     this.$ge t = ['$inj ector', '$ window', f unction($i njector, $ window) {
  8302  
  8303       /**
  8304        * @ng doc servic e
  8305        * @na me $contro ller
  8306        * @re quires $in jector
  8307        *
  8308        * @pa ram {Funct ion|string } construc tor If cal led with a  function  then it's  considered  to be the
  8309        *     controller  construct or functio n. Otherwi se it's co nsidered t o be a str ing which  is used
  8310        *     to retriev e the cont roller con structor u sing the f ollowing s teps:
  8311        *
  8312        *     * check if  a control ler with g iven name  is registe red via `$ controller Provider`
  8313        *     * check if  evaluatin g the stri ng on the  current sc ope return s a constr uctor
  8314        *     * if $cont rollerProv ider#allow Globals, c heck `wind ow[constru ctor]` on  the global
  8315        *       `window`  object (n ot recomme nded)
  8316        *
  8317        *     The string  can use t he `contro ller as pr operty` sy ntax, wher e the cont roller ins tance is p ublished
  8318        *     as the spe cified pro perty on t he `scope` ; the `sco pe` must b e injected  into `loc als` param  for this
  8319        *     to work co rrectly.
  8320        *
  8321        * @pa ram {Objec t} locals  Injection  locals for  Controlle r.
  8322        * @re turn {Obje ct} Instan ce of give n controll er.
  8323        *
  8324        * @de scription
  8325        * `$c ontroller`  service i s responsi ble for in stantiatin g controll ers.
  8326        *
  8327        * It' s just a s imple call  to {@link  auto.$inj ector $inj ector}, bu t extracte d into
  8328        * a s ervice, so  that one  can overri de this se rvice with  [BC versi on](https: //gist.git hub.com/16 49788).
  8329        */
  8330       return  function( expression , locals,  later, ide nt) {
  8331         // P RIVATE API :
  8332         //    param `la ter` --- i ndicates t hat the co ntroller's  construct or is invo ked at a l ater time.
  8333         //                       I f true, $c ontroller  will alloc ate the ob ject with  the correc t
  8334         //                       p rototype c hain, but  will not i nvoke the  controller  until a r eturned
  8335         //                       c allback is  invoked.
  8336         //    param `id ent` --- A n optional  label whi ch overrid es the lab el parsed  from the c ontroller
  8337         //                       e xpression,  if any.
  8338         var  instance,  match, con structor,  identifier ;
  8339         late r = later  === true;
  8340         if ( ident && i sString(id ent)) {
  8341           id entifier =  ident;
  8342         }
  8343  
  8344         if ( isString(e xpression) ) {
  8345           ma tch = expr ession.mat ch(CNTRL_R EG),
  8346           co nstructor  = match[1] ,
  8347           id entifier =  identifie r || match [3];
  8348           ex pression =  controlle rs.hasOwnP roperty(co nstructor)
  8349                ? contro llers[cons tructor]
  8350                : getter (locals.$s cope, cons tructor, t rue) ||
  8351                    (glo bals ? get ter($windo w, constru ctor, true ) : undefi ned);
  8352  
  8353           as sertArgFn( expression , construc tor, true) ;
  8354         }
  8355  
  8356         if ( later) {
  8357           //  Instantia te control ler later:
  8358           //  This mach inery is u sed to cre ate an ins tance of t he object  before cal ling the
  8359           //  controlle r's constr uctor itse lf.
  8360           //
  8361           //  This allo ws propert ies to be  added to t he control ler before  the const ructor is
  8362           //  invoked.  Primarily,  this is u sed for is olate scop e bindings  in $compi le.
  8363           //
  8364           //  This feat ure is not  intended  for use by  applicati ons, and i s thus not  documente d
  8365           //  publicly.
  8366           //  Object cr eation: ht tp://jsper f.com/crea te-constru ctor/2
  8367           va r controll erPrototyp e = (isArr ay(express ion) ?
  8368              expression [expressio n.length -  1] : expr ession).pr ototype;
  8369           in stance = O bject.crea te(control lerPrototy pe);
  8370  
  8371           if  (identifi er) {
  8372              addIdentif ier(locals , identifi er, instan ce, constr uctor || e xpression. name);
  8373           }
  8374  
  8375           re turn exten d(function () {
  8376              $injector. invoke(exp ression, i nstance, l ocals, con structor);
  8377              return ins tance;
  8378           },  {
  8379              instance:  instance,
  8380              identifier : identifi er
  8381           }) ;
  8382         }
  8383  
  8384         inst ance = $in jector.ins tantiate(e xpression,  locals, c onstructor );
  8385  
  8386         if ( identifier ) {
  8387           ad dIdentifie r(locals,  identifier , instance , construc tor || exp ression.na me);
  8388         }
  8389  
  8390         retu rn instanc e;
  8391       };
  8392  
  8393       functi on addIden tifier(loc als, ident ifier, ins tance, nam e) {
  8394         if ( !(locals & & isObject (locals.$s cope))) {
  8395           th row minErr ('$control ler')('nos cp',
  8396              "Cannot ex port contr oller '{0} ' as '{1}' ! No $scop e object p rovided vi a `locals` .",
  8397              name, iden tifier);
  8398         }
  8399  
  8400         loca ls.$scope[ identifier ] = instan ce;
  8401       }
  8402     }];
  8403   }
  8404  
  8405   /**
  8406    * @ngdoc  service
  8407    * @name $ document
  8408    * @requir es $window
  8409    *
  8410    * @descri ption
  8411    * A {@lin k angular. element jQ uery or jq Lite} wrap per for th e browser' s `window. document`  object.
  8412    *
  8413    * @exampl e
  8414      <exampl e module=" documentEx ample">
  8415        <file  name="ind ex.html">
  8416          <di v ng-contr oller="Exa mpleContro ller">
  8417            < p>$documen t title: < b ng-bind= "title"></ b></p>
  8418            < p>window.d ocument ti tle: <b ng -bind="win dowTitle"> </b></p>
  8419          </d iv>
  8420        </fil e>
  8421        <file  name="scr ipt.js">
  8422          ang ular.modul e('documen tExample',  [])
  8423            . controller ('ExampleC ontroller' , ['$scope ', '$docum ent', func tion($scop e, $docume nt) {
  8424               $scope.ti tle = $doc ument[0].t itle;
  8425               $scope.wi ndowTitle  = angular. element(wi ndow.docum ent)[0].ti tle;
  8426            } ]);
  8427        </fil e>
  8428      </examp le>
  8429    */
  8430   function $ DocumentPr ovider() {
  8431     this.$ge t = ['$win dow', func tion(windo w) {
  8432       return  jqLite(wi ndow.docum ent);
  8433     }];
  8434   }
  8435  
  8436   /**
  8437    * @ngdoc  service
  8438    * @name $ exceptionH andler
  8439    * @requir es ng.$log
  8440    *
  8441    * @descri ption
  8442    * Any unc aught exce ption in a ngular exp ressions i s delegate d to this  service.
  8443    * The def ault imple mentation  simply del egates to  `$log.erro r` which l ogs it int o
  8444    * the bro wser conso le.
  8445    *
  8446    * In unit  tests, if  `angular- mocks.js`  is loaded,  this serv ice is ove rridden by
  8447    * {@link  ngMock.$ex ceptionHan dler mock  $exception Handler} w hich aids  in testing .
  8448    *
  8449    * ## Exam ple:
  8450    *
  8451    * ```js
  8452    *   angul ar.module( 'exception Override',  []).facto ry('$excep tionHandle r', functi on() {
  8453    *     ret urn functi on(excepti on, cause)  {
  8454    *       e xception.m essage +=  ' (caused  by "' + ca use + '")' ;
  8455    *       t hrow excep tion;
  8456    *     };
  8457    *   });
  8458    * ```
  8459    *
  8460    * This ex ample will  override  the normal  action of  `$excepti onHandler` , to make  angular
  8461    * excepti ons fail h ard when t hey happen , instead  of just lo gging to t he console .
  8462    *
  8463    * <hr />
  8464    * Note, t hat code e xecuted in  event-lis teners (ev en those r egistered  using jqLi te's `on`/ `bind`
  8465    * methods ) does not  delegate  exceptions  to the {@ link ng.$e xceptionHa ndler $exc eptionHand ler}
  8466    * (unless  executed  during a d igest).
  8467    *
  8468    * If you  wish, you  can manual ly delegat e exceptio ns, e.g.
  8469    * `try {  ... } catc h(e) { $ex ceptionHan dler(e); } `
  8470    *
  8471    * @param  {Error} ex ception Ex ception as sociated w ith the er ror.
  8472    * @param  {string=}  cause opti onal infor mation abo ut the con text in wh ich
  8473    *       t he error w as thrown.
  8474    *
  8475    */
  8476   function $ ExceptionH andlerProv ider() {
  8477     this.$ge t = ['$log ', functio n($log) {
  8478       return  function( exception,  cause) {
  8479         $log .error.app ly($log, a rguments);
  8480       };
  8481     }];
  8482   }
  8483  
  8484   var APPLIC ATION_JSON  = 'applic ation/json ';
  8485   var CONTEN T_TYPE_APP LICATION_J SON = {'Co ntent-Type ': APPLICA TION_JSON  + ';charse t=utf-8'};
  8486   var JSON_S TART = /^\ s*(\[|\{[^ \{])/;
  8487   var JSON_E ND = /[\}\ ]]\s*$/;
  8488   var JSON_P ROTECTION_ PREFIX = / ^\)\]\}',? \n/;
  8489  
  8490   function d efaultHttp ResponseTr ansform(da ta, header s) {
  8491     if (isSt ring(data) ) {
  8492       // str ip json vu lnerabilit y protecti on prefix
  8493       data =  data.repl ace(JSON_P ROTECTION_ PREFIX, '' );
  8494       var co ntentType  = headers( 'Content-T ype');
  8495       if ((c ontentType  && conten tType.inde xOf(APPLIC ATION_JSON ) === 0 &&  data.trim ()) ||
  8496           (J SON_START. test(data)  && JSON_E ND.test(da ta))) {
  8497         data  = fromJso n(data);
  8498       }
  8499     }
  8500     return d ata;
  8501   }
  8502  
  8503   /**
  8504    * Parse h eaders int o key valu e object
  8505    *
  8506    * @param  {string} h eaders Raw  headers a s a string
  8507    * @return s {Object}  Parsed he aders as k ey value o bject
  8508    */
  8509   function p arseHeader s(headers)  {
  8510     var pars ed = creat eMap(), ke y, val, i;
  8511  
  8512     if (!hea ders) retu rn parsed;
  8513  
  8514     forEach( headers.sp lit('\n'),  function( line) {
  8515       i = li ne.indexOf (':');
  8516       key =  lowercase( trim(line. substr(0,  i)));
  8517       val =  trim(line. substr(i +  1));
  8518  
  8519       if (ke y) {
  8520         pars ed[key] =  parsed[key ] ? parsed [key] + ',  ' + val :  val;
  8521       }
  8522     });
  8523  
  8524     return p arsed;
  8525   }
  8526  
  8527  
  8528   /**
  8529    * Returns  a functio n that pro vides acce ss to pars ed headers .
  8530    *
  8531    * Headers  are lazy  parsed whe n first re quested.
  8532    * @see pa rseHeaders
  8533    *
  8534    * @param  {(string|O bject)} he aders Head ers to pro vide acces s to.
  8535    * @return s {functio n(string=) } Returns  a getter f unction wh ich if cal led with:
  8536    *
  8537    *   - if  called wit h single a n argument  returns a  single he ader value  or null
  8538    *   - if  called wit h no argum ents retur ns an obje ct contain ing all he aders.
  8539    */
  8540   function h eadersGett er(headers ) {
  8541     var head ersObj = i sObject(he aders) ? h eaders : u ndefined;
  8542  
  8543     return f unction(na me) {
  8544       if (!h eadersObj)  headersOb j =  parse Headers(he aders);
  8545  
  8546       if (na me) {
  8547         var  value = he adersObj[l owercase(n ame)];
  8548         if ( value ===  void 0) {
  8549           va lue = null ;
  8550         }
  8551         retu rn value;
  8552       }
  8553  
  8554       return  headersOb j;
  8555     };
  8556   }
  8557  
  8558  
  8559   /**
  8560    * Chain a ll given f unctions
  8561    *
  8562    * This fu nction is  used for b oth reques t and resp onse trans forming
  8563    *
  8564    * @param  {*} data D ata to tra nsform.
  8565    * @param  {function( string=)}  headers Ht tp headers  getter fn .
  8566    * @param  {(Function |Array.<Fu nction>)}  fns Functi on or an a rray of fu nctions.
  8567    * @return s {*} Tran sformed da ta.
  8568    */
  8569   function t ransf
D NS     a(data, he aders, fns ) {
  8570     if (isFu nction(fns ))
  8571       return  fns(data,  headers);
  8572  
  8573     forEach( fns, funct ion(fn) {
  8574       data =  fn(data,  headers);
  8575     });
  8576  
  8577     return d ata;
  8578   }
  8579  
  8580  
  8581   function i sSuccess(s tatus) {
  8582     return 2 00 <= stat us && stat us < 300;
  8583   }
  8584  
  8585  
  8586   /**
  8587    * @ngdoc  provider
  8588    * @name $ httpProvid er
  8589    * @descri ption
  8590    * Use `$h ttpProvide r` to chan ge the def ault behav ior of the  {@link ng .$http $ht tp} servic e.
  8591    * */
  8592   function $ HttpProvid er() {
  8593     /**
  8594      * @ngdo c property
  8595      * @name  $httpProv ider#defau lts
  8596      * @desc ription
  8597      *
  8598      * Objec t containi ng default  values fo r all {@li nk ng.$htt p $http} r equests.
  8599      *
  8600      * - **` defaults.c ache`** -  {Object} -  an object  built wit h {@link n g.$cacheFa ctory `$ca cheFactory `}
  8601      * that  will provi de the cac he for all  requests  who set th eir `cache ` property  to `true` .
  8602      * If yo u set the  `default.c ache = fal se` then o nly reques ts that sp ecify thei r own cust om
  8603      * cache  object wi ll be cach ed. See {@ link $http #caching $ http Cachi ng} for mo re informa tion.
  8604      *
  8605      * - **` defaults.x srfCookieN ame`** - { string} -  Name of co okie conta ining the  XSRF token .
  8606      * Defau lts value  is `'XSRF- TOKEN'`.
  8607      *
  8608      * - **` defaults.x srfHeaderN ame`** - { string} -  Name of HT TP header  to populat e with the
  8609      * XSRF  token. Def aults valu e is `'X-X SRF-TOKEN' `.
  8610      *
  8611      * - **` defaults.h eaders`**  - {Object}  - Default  headers f or all $ht tp request s.
  8612      * Refer  to {@link  ng.$http# setting-ht tp-headers  $http} fo r document ation on
  8613      * setti ng default  headers.
  8614      *     -  **`defaul ts.headers .common`**
  8615      *     -  **`defaul ts.headers .post`**
  8616      *     -  **`defaul ts.headers .put`**
  8617      *     -  **`defaul ts.headers .patch`**
  8618      *
  8619      **/
  8620     var defa ults = thi s.defaults  = {
  8621       // tra nsform inc oming resp onse data
  8622       transf ormRespons e: [defaul tHttpRespo nseTransfo rm],
  8623  
  8624       // tra nsform out going requ est data
  8625       transf ormRequest : [functio n(d) {
  8626         retu rn isObjec t(d) && !i sFile(d) & & !isBlob( d) ? toJso n(d) : d;
  8627       }],
  8628  
  8629       // def ault heade rs
  8630       header s: {
  8631         comm on: {
  8632           'A ccept': 'a pplication /json, tex t/plain, * /*'
  8633         },
  8634         post :   shallo wCopy(CONT ENT_TYPE_A PPLICATION _JSON),
  8635         put:     shallo wCopy(CONT ENT_TYPE_A PPLICATION _JSON),
  8636         patc h:  shallo wCopy(CONT ENT_TYPE_A PPLICATION _JSON)
  8637       },
  8638  
  8639       xsrfCo okieName:  'XSRF-TOKE N',
  8640       xsrfHe aderName:  'X-XSRF-TO KEN'
  8641     };
  8642  
  8643     var useA pplyAsync  = false;
  8644     /**
  8645      * @ngdo c method
  8646      * @name  $httpProv ider#useAp plyAsync
  8647      * @desc ription
  8648      *
  8649      * Confi gure $http  service t o combine  processing  of multip le http re sponses re ceived at  around
  8650      * the s ame time v ia {@link  ng.$rootSc ope.Scope# $applyAsyn c $rootSco pe.$applyA sync}. Thi s can resu lt in
  8651      * signi ficant per formance i mprovement  for bigge r applicat ions that  make many  HTTP reque sts
  8652      * concu rrently (c ommon duri ng applica tion boots trap).
  8653      *
  8654      * Defau lts to fal se. If no  value is s pecifed, r eturns the  current c onfigured  value.
  8655      *
  8656      * @para m {boolean =} value I f true, wh en request s are load ed, they w ill schedu le a defer red
  8657      *    "a pply" on t he next ti ck, giving  time for  subsequent  requests  in a rough ly ~10ms w indow
  8658      *    to  load and  share the  same diges t cycle.
  8659      *
  8660      * @retu rns {boole an|Object}  If a valu e is speci fied, retu rns the $h ttpProvide r for chai ning.
  8661      *    ot herwise, r eturns the  current c onfigured  value.
  8662      **/
  8663     this.use ApplyAsync  = functio n(value) {
  8664       if (is Defined(va lue)) {
  8665         useA pplyAsync  = !!value;
  8666         retu rn this;
  8667       }
  8668       return  useApplyA sync;
  8669     };
  8670  
  8671     /**
  8672      * @ngdo c property
  8673      * @name  $httpProv ider#inter ceptors
  8674      * @desc ription
  8675      *
  8676      * Array  containin g service  factories  for all sy nchronous  or asynchr onous {@li nk ng.$htt p $http}
  8677      * pre-p rocessing  of request  or postpr ocessing o f response s.
  8678      *
  8679      * These  service f actories a re ordered  by reques t, i.e. th ey are app lied in th e same ord er as the
  8680      * array , on reque st, but re verse orde r, on resp onse.
  8681      *
  8682      * {@lin k ng.$http #intercept ors Interc eptors det ailed info }
  8683      **/
  8684     var inte rceptorFac tories = t his.interc eptors = [ ];
  8685  
  8686     this.$ge t = ['$htt pBackend',  '$browser ', '$cache Factory',  '$rootScop e', '$q',  '$injector ',
  8687         func tion($http Backend, $ browser, $ cacheFacto ry, $rootS cope, $q,  $injector)  {
  8688  
  8689       var de faultCache  = $cacheF actory('$h ttp');
  8690  
  8691       /**
  8692        * Int erceptors  stored in  reverse or der. Inner  intercept ors before  outer int erceptors.
  8693        * The  reversal  is needed  so that we  can build  up the in terception  chain aro und the
  8694        * ser ver reques t.
  8695        */
  8696       var re versedInte rceptors =  [];
  8697  
  8698       forEac h(intercep torFactori es, functi on(interce ptorFactor y) {
  8699         reve rsedInterc eptors.uns hift(isStr ing(interc eptorFacto ry)
  8700              ? $injecto r.get(inte rceptorFac tory) : $i njector.in voke(inter ceptorFact ory));
  8701       });
  8702  
  8703       /**
  8704        * @ng doc servic e
  8705        * @ki nd functio n
  8706        * @na me $http
  8707        * @re quires ng. $httpBacke nd
  8708        * @re quires $ca cheFactory
  8709        * @re quires $ro otScope
  8710        * @re quires $q
  8711        * @re quires $in jector
  8712        *
  8713        * @de scription
  8714        * The  `$http` s ervice is  a core Ang ular servi ce that fa cilitates  communicat ion with t he remote
  8715        * HTT P servers  via the br owser's [X MLHttpRequ est](https ://develop er.mozilla .org/en/xm lhttpreque st)
  8716        * obj ect or via  [JSONP](h ttp://en.w ikipedia.o rg/wiki/JS ONP).
  8717        *
  8718        * For  unit test ing applic ations tha t use `$ht tp` servic e, see
  8719        * {@l ink ngMock .$httpBack end $httpB ackend moc k}.
  8720        *
  8721        * For  a higher  level of a bstraction , please c heck out t he {@link  ngResource .$resource
  8722        * $re source} se rvice.
  8723        *
  8724        * The  $http API  is based  on the {@l ink ng.$q  deferred/p romise API s} exposed  by
  8725        * the  $q servic e. While f or simple  usage patt erns this  doesn't ma tter much,  for advan ced usage
  8726        * it  is importa nt to fami liarize yo urself wit h these AP Is and the  guarantee s they pro vide.
  8727        *
  8728        *
  8729        * ##  General us age
  8730        * The  `$http` s ervice is  a function  which tak es a singl e argument  â€” a con figuration  object â€
  8731        * tha t is used  to generat e an HTTP  request an d returns   a {@link  ng.$q prom ise}
  8732        * wit h two $htt p specific  methods:  `success`  and `error `.
  8733        *
  8734        * ``` js
  8735        *   / / Simple G ET request  example :
  8736        *   $ http.get(' /someUrl') .
  8737        *      success(f unction(da ta, status , headers,  config) {
  8738        *        // this  callback  will be ca lled async hronously
  8739        *        // when  the respo nse is ava ilable
  8740        *      }).
  8741        *      error(fun ction(data , status,  headers, c onfig) {
  8742        *        // call ed asynchr onously if  an error  occurs
  8743        *        // or s erver retu rns respon se with an  error sta tus.
  8744        *      });
  8745        * ```
  8746        *
  8747        * ``` js
  8748        *   / / Simple P OST reques t example  (passing d ata) :
  8749        *   $ http.post( '/someUrl' , {msg:'he llo word!' }).
  8750        *      success(f unction(da ta, status , headers,  config) {
  8751        *        // this  callback  will be ca lled async hronously
  8752        *        // when  the respo nse is ava ilable
  8753        *      }).
  8754        *      error(fun ction(data , status,  headers, c onfig) {
  8755        *        // call ed asynchr onously if  an error  occurs
  8756        *        // or s erver retu rns respon se with an  error sta tus.
  8757        *      });
  8758        * ```
  8759        *
  8760        *
  8761        * Sin ce the ret urned valu e of calli ng the $ht tp functio n is a `pr omise`, yo u can also  use
  8762        * the  `then` me thod to re gister cal lbacks, an d these ca llbacks wi ll receive  a single  argument â €“
  8763        * an  object rep resenting  the respon se. See th e API sign ature and  type info  below for  more
  8764        * det ails.
  8765        *
  8766        * A r esponse st atus code  between 20 0 and 299  is conside red a succ ess status  and
  8767        * wil l result i n the succ ess callba ck being c alled. Not e that if  the respon se is a re direct,
  8768        * XML HttpReques t will tra nsparently  follow it , meaning  that the e rror callb ack will n ot be
  8769        * cal led for su ch respons es.
  8770        *
  8771        * ##  Writing Un it Tests t hat use $h ttp
  8772        * Whe n unit tes ting (usin g {@link n gMock ngMo ck}), it i s necessar y to call
  8773        * {@l ink ngMock .$httpBack end#flush  $httpBacke nd.flush() } to flush  each pend ing
  8774        * req uest using  trained r esponses.
  8775        *
  8776        * ```
  8777        * $ht tpBackend. expectGET( ...);
  8778        * $ht tp.get(... );
  8779        * $ht tpBackend. flush();
  8780        * ```
  8781        *
  8782        * ##  Shortcut m ethods
  8783        *
  8784        * Sho rtcut meth ods are al so availab le. All sh ortcut met hods requi re passing  in the UR L, and
  8785        * req uest data  must be pa ssed in fo r POST/PUT  requests.
  8786        *
  8787        * ``` js
  8788        *   $ http.get(' /someUrl') .success(s uccessCall back);
  8789        *   $ http.post( '/someUrl' , data).su ccess(succ essCallbac k);
  8790        * ```
  8791        *
  8792        * Com plete list  of shortc ut methods :
  8793        *
  8794        * - { @link ng.$ http#get $ http.get}
  8795        * - { @link ng.$ http#head  $http.head }
  8796        * - { @link ng.$ http#post  $http.post }
  8797        * - { @link ng.$ http#put $ http.put}
  8798        * - { @link ng.$ http#delet e $http.de lete}
  8799        * - { @link ng.$ http#jsonp  $http.jso np}
  8800        * - { @link ng.$ http#patch  $http.pat ch}
  8801        *
  8802        *
  8803        * ##  Setting HT TP Headers
  8804        *
  8805        * The  $http ser vice will  automatica lly add ce rtain HTTP  headers t o all requ ests. Thes e defaults
  8806        * can  be fully  configured  by access ing the `$ httpProvid er.default s.headers`  configura tion
  8807        * obj ect, which  currently  contains  this defau lt configu ration:
  8808        *
  8809        * - ` $httpProvi der.defaul ts.headers .common` ( headers th at are com mon for al l requests ):
  8810        *   -  `Accept:  applicatio n/json, te xt/plain,  * / *`
  8811        * - ` $httpProvi der.defaul ts.headers .post`: (h eader defa ults for P OST reques ts)
  8812        *   -  `Content- Type: appl ication/js on`
  8813        * - ` $httpProvi der.defaul ts.headers .put` (hea der defaul ts for PUT  requests)
  8814        *   -  `Content- Type: appl ication/js on`
  8815        *
  8816        * To  add or ove rwrite the se default s, simply  add or rem ove a prop erty from  these conf iguration
  8817        * obj ects. To a dd headers  for an HT TP method  other than  POST or P UT, simply  add a new  object
  8818        * wit h the lowe rcased HTT P method n ame as the  key, e.g.
  8819        * `$h ttpProvide r.defaults .headers.g et = { 'My -Header' :  'value' } .
  8820        *
  8821        * The  defaults  can also b e set at r untime via  the `$htt p.defaults ` object i n the same
  8822        * fas hion. For  example:
  8823        *
  8824        * ```
  8825        * mod ule.run(fu nction($ht tp) {
  8826        *   $ http.defau lts.header s.common.A uthorizati on = 'Basi c YmVlcDpi b29w'
  8827        * });
  8828        * ```
  8829        *
  8830        * In  addition,  you can su pply a `he aders` pro perty in t he config  object pas sed when
  8831        * cal ling `$htt p(config)` , which ov errides th e defaults  without c hanging th em globall y.
  8832        *
  8833        * To  explicitly  remove a  header aut omatically  added via  $httpProv ider.defau lts.header s on a per  request b asis,
  8834        * Use  the `head ers` prope rty, setti ng the des ired heade r to `unde fined`. Fo r example:
  8835        *
  8836        * ``` js
  8837        * var  req = {
  8838        *  me thod: 'POS T',
  8839        *  ur l: 'http:/ /example.c om',
  8840        *  he aders: {
  8841        *     'Content-T ype': unde fined
  8842        *  },
  8843        *  da ta: { test : 'test' } ,
  8844        * }
  8845        *
  8846        * $ht tp(req).su ccess(func tion(){... }).error(f unction(){ ...});
  8847        * ```
  8848        *
  8849        * ##  Transformi ng Request s and Resp onses
  8850        *
  8851        * Bot h requests  and respo nses can b e transfor med using  transforma tion funct ions: `tra nsformRequ est`
  8852        * and  `transfor mResponse` . These pr operties c an be a si ngle funct ion that r eturns
  8853        * the  transform ed value ( `{function (data, hea dersGetter )`) or an  array of s uch transf ormation f unctions,
  8854        * whi ch allows  you to `pu sh` or `un shift` a n ew transfo rmation fu nction int o the tran sformation  chain.
  8855        *
  8856        * ###  Default T ransformat ions
  8857        *
  8858        * The  `$httpPro vider` pro vider and  `$http` se rvice expo se `defaul ts.transfo rmRequest`  and
  8859        * `de faults.tra nsformResp onse` prop erties. If  a request  does not  provide it s own tran sformation s
  8860        * the n these wi ll be appl ied.
  8861        *
  8862        * You  can augme nt or repl ace the de fault tran sformation s by modif ying these  propertie s by addin g to or
  8863        * rep lacing the  array.
  8864        *
  8865        * Ang ular provi des the fo llowing de fault tran sformation s:
  8866        *
  8867        * Req uest trans formations  (`$httpPr ovider.def aults.tran sformReque st` and `$ http.defau lts.transf ormRequest `):
  8868        *
  8869        * - I f the `dat a` propert y of the r equest con figuration  object co ntains an  object, se rialize it
  8870        *   i nto JSON f ormat.
  8871        *
  8872        * Res ponse tran sformation s (`$httpP rovider.de faults.tra nsformResp onse` and  `$http.def aults.tran sformRespo nse`):
  8873        *
  8874        *  -  If XSRF pr efix is de tected, st rip it (se e Security  Considera tions sect ion below) .
  8875        *  -  If JSON re sponse is  detected,  deserializ e it using  a JSON pa rser.
  8876        *
  8877        *
  8878        * ###  Overridin g the Defa ult Transf ormations  Per Reques t
  8879        *
  8880        * If  you wish o verride th e request/ response t ransformat ions only  for a sing le request  then prov ide
  8881        * `tr ansformReq uest` and/ or `transf ormRespons e` propert ies on the  configura tion objec t passed
  8882        * int o `$http`.
  8883        *
  8884        * Not e that if  you provid e these pr operties o n the conf ig object  the defaul t transfor mations wi ll be
  8885        * ove rwritten.  If you wis h to augme nt the def ault trans formations  then you  must inclu de them in  your
  8886        * loc al transfo rmation ar ray.
  8887        *
  8888        * The  following  code demo nstrates a dding a ne w response  transform ation to b e run afte r the defa ult respon se
  8889        * tra nsformatio ns have be en run.
  8890        *
  8891        * ``` js
  8892        * fun ction appe ndTransfor m(defaults , transfor m) {
  8893        *
  8894        *   / / We can't  guarantee  that the  default tr ansformati on is an a rray
  8895        *   d efaults =  angular.is Array(defa ults) ? de faults : [ defaults];
  8896        *
  8897        *   / / Append t he new tra nsformatio n to the d efaults
  8898        *   r eturn defa ults.conca t(transfor m);
  8899        * }
  8900        *
  8901        * $ht tp({
  8902        *   u rl: '...',
  8903        *   m ethod: 'GE T',
  8904        *   t ransformRe sponse: ap pendTransf orm($http. defaults.t ransformRe sponse, fu nction(val ue) {
  8905        *      return do Transform( value);
  8906        *   } )
  8907        * });
  8908        * ```
  8909        *
  8910        *
  8911        * ##  Caching
  8912        *
  8913        * To  enable cac hing, set  the reques t configur ation `cac he` proper ty to `tru e` (to use  default
  8914        * cac he) or to  a custom c ache objec t (built w ith {@link  ng.$cache Factory `$ cacheFacto ry`}).
  8915        * Whe n the cach e is enabl ed, `$http ` stores t he respons e from the  server in  the speci fied
  8916        * cac he. The ne xt time th e same req uest is ma de, the re sponse is  served fro m the cach e without
  8917        * sen ding a req uest to th e server.
  8918        *
  8919        * Not e that eve n if the r esponse is  served fr om cache,  delivery o f the data  is asynch ronous in
  8920        * the  same way  that real  requests a re.
  8921        *
  8922        * If  there are  multiple G ET request s for the  same URL t hat should  be cached  using the  same
  8923        * cac he, but th e cache is  not popul ated yet,  only one r equest to  the server  will be m ade and
  8924        * the  remaining  requests  will be fu lfilled us ing the re sponse fro m the firs t request.
  8925        *
  8926        * You  can chang e the defa ult cache  to a new o bject (bui lt with
  8927        * {@l ink ng.$ca cheFactory  `$cacheFa ctory`}) b y updating  the
  8928        * {@l ink ng.$ht tp#default s `$http.d efaults.ca che`} prop erty. All  requests w ho set
  8929        * the ir `cache`  property  to `true`  will now u se this ca che object .
  8930        *
  8931        * If  you set th e default  cache to ` false` the n only req uests that  specify t heir own c ustom
  8932        * cac he object  will be ca ched.
  8933        *
  8934        * ##  Intercepto rs
  8935        *
  8936        * Bef ore you st art creati ng interce ptors, be  sure to un derstand t he
  8937        * {@l ink ng.$q  $q and def erred/prom ise APIs}.
  8938        *
  8939        * For  purposes  of global  error hand ling, auth entication , or any k ind of syn chronous o r
  8940        * asy nchronous  pre-proces sing of re quest or p ostprocess ing of res ponses, it  is desira ble to be
  8941        * abl e to inter cept reque sts before  they are  handed to  the server  and
  8942        * res ponses bef ore they a re handed  over to th e applicat ion code t hat
  8943        * ini tiated the se request s. The int erceptors  leverage t he {@link  ng.$q
  8944        * pro mise APIs}  to fulfil l this nee d for both  synchrono us and asy nchronous  pre-proces sing.
  8945        *
  8946        * The  intercept ors are se rvice fact ories that  are regis tered with  the `$htt pProvider`  by
  8947        * add ing them t o the `$ht tpProvider .intercept ors` array . The fact ory is cal led and
  8948        * inj ected with  dependenc ies (if sp ecified) a nd returns  the inter ceptor.
  8949        *
  8950        * The re are two  kinds of  intercepto rs (and tw o kinds of  rejection  intercept ors):
  8951        *
  8952        *   *  `request` : intercep tors get c alled with  a http `c onfig` obj ect. The f unction is  free to
  8953        *      modify th e `config`  object or  create a  new one. T he functio n needs to  return th e `config`
  8954        *      object di rectly, or  a promise  containin g the `con fig` or a  new `confi g` object.
  8955        *   *  `requestE rror`: int erceptor g ets called  when a pr evious int erceptor t hrew an er ror or
  8956        *      resolved  with a rej ection.
  8957        *   *  `response `: interce ptors get  called wit h http `re sponse` ob ject. The  function i s free to
  8958        *      modify th e `respons e` object  or create  a new one.  The funct ion needs  to return  the `respo nse`
  8959        *      object di rectly, or  as a prom ise contai ning the ` response`  or a new ` response`  object.
  8960        *   *  `response Error`: in terceptor  gets calle d when a p revious in terceptor  threw an e rror or
  8961        *      resolved  with a rej ection.
  8962        *
  8963        *
  8964        * ``` js
  8965        *   / / register  the inter ceptor as  a service
  8966        *   $ provide.fa ctory('myH ttpInterce ptor', fun ction($q,  dependency 1, depende ncy2) {
  8967        *      return {
  8968        *        // opti onal metho d
  8969        *        'reques t': functi on(config)  {
  8970        *          // do  something  on succes s
  8971        *          retur n config;
  8972        *        },
  8973        *
  8974        *        // opti onal metho d
  8975        *       'request Error': fu nction(rej ection) {
  8976        *          // do  something  on error
  8977        *          if (c anRecover( rejection) ) {
  8978        *            ret urn respon seOrNewPro mise
  8979        *          }
  8980        *          retur n $q.rejec t(rejectio n);
  8981        *        },
  8982        *
  8983        *
  8984        *
  8985        *        // opti onal metho d
  8986        *        'respon se': funct ion(respon se) {
  8987        *          // do  something  on succes s
  8988        *          retur n response ;
  8989        *        },
  8990        *
  8991        *        // opti onal metho d
  8992        *       'respons eError': f unction(re jection) {
  8993        *          // do  something  on error
  8994        *          if (c anRecover( rejection) ) {
  8995        *            ret urn respon seOrNewPro mise
  8996        *          }
  8997        *          retur n $q.rejec t(rejectio n);
  8998        *        }
  8999        *      };
  9000        *   } );
  9001        *
  9002        *   $ httpProvid er.interce ptors.push ('myHttpIn terceptor' );
  9003        *
  9004        *
  9005        *   / / alternat ively, reg ister the  intercepto r via an a nonymous f actory
  9006        *   $ httpProvid er.interce ptors.push (function( $q, depend ency1, dep endency2)  {
  9007        *      return {
  9008        *       'request ': functio n(config)  {
  9009        *           // s ame as abo ve
  9010        *        },
  9011        *
  9012        *        'respon se': funct ion(respon se) {
  9013        *           // s ame as abo ve
  9014        *        }
  9015        *      };
  9016        *   } );
  9017        * ```
  9018        *
  9019        * ##  Security C onsiderati ons
  9020        *
  9021        * Whe n designin g web appl ications,  consider s ecurity th reats from :
  9022        *
  9023        * - [ JSON vulne rability]( http://haa cked.com/a rchive/200 8/11/20/an atomy-of-a -subtle-js on-vulnera bility.asp x)
  9024        * - [ XSRF](http ://en.wiki pedia.org/ wiki/Cross -site_requ est_forger y)
  9025        *
  9026        * Bot h server a nd the cli ent must c ooperate i n order to  eliminate  these thr eats. Angu lar comes
  9027        * pre -configure d with str ategies th at address  these iss ues, but f or this to  work back end server
  9028        * coo peration i s required .
  9029        *
  9030        * ###  JSON Vuln erability  Protection
  9031        *
  9032        * A [ JSON vulne rability]( http://haa cked.com/a rchive/200 8/11/20/an atomy-of-a -subtle-js on-vulnera bility.asp x)
  9033        * all ows third  party webs ite to tur n your JSO N resource  URL into
  9034        * [JS ONP](http: //en.wikip edia.org/w iki/JSONP)  request u nder some  conditions . To
  9035        * cou nter this  your serve r can pref ix all JSO N requests  with foll owing stri ng `")]}', \n"`.
  9036        * Ang ular will  automatica lly strip  the prefix  before pr ocessing i t as JSON.
  9037        *
  9038        * For  example i f your ser ver needs  to return:
  9039        * ``` js
  9040        * ['o ne','two']
  9041        * ```
  9042        *
  9043        * whi ch is vuln erable to  attack, yo ur server  can return :
  9044        * ``` js
  9045        * )]} ',
  9046        * ['o ne','two']
  9047        * ```
  9048        *
  9049        * Ang ular will  strip the  prefix, be fore proce ssing the  JSON.
  9050        *
  9051        *
  9052        * ###  Cross Sit e Request  Forgery (X SRF) Prote ction
  9053        *
  9054        * [XS RF](http:/ /en.wikipe dia.org/wi ki/Cross-s ite_reques t_forgery)  is a tech nique by w hich
  9055        * an  unauthoriz ed site ca n gain you r user's p rivate dat a. Angular  provides  a mechanis m
  9056        * to  counter XS RF. When p erforming  XHR reques ts, the $h ttp servic e reads a  token from  a cookie
  9057        * (by  default,  `XSRF-TOKE N`) and se ts it as a n HTTP hea der (`X-XS RF-TOKEN`) . Since on ly
  9058        * Jav aScript th at runs on  your doma in could r ead the co okie, your  server ca n be assur ed that
  9059        * the  XHR came  from JavaS cript runn ing on you r domain.  The header  will not  be set for
  9060        * cro ss-domain  requests.
  9061        *
  9062        * To  take advan tage of th is, your s erver need s to set a  token in  a JavaScri pt readabl e session
  9063        * coo kie called  `XSRF-TOK EN` on the  first HTT P GET requ est. On su bsequent X HR request s the
  9064        * ser ver can ve rify that  the cookie  matches ` X-XSRF-TOK EN` HTTP h eader, and  therefore  be sure
  9065        * tha t only Jav aScript ru nning on y our domain  could hav e sent the  request.  The token  must be
  9066        * uni que for ea ch user an d must be  verifiable  by the se rver (to p revent the  JavaScrip t from
  9067        * mak ing up its  own token s). We rec ommend tha t the toke n is a dig est of you r site's
  9068        * aut henticatio n cookie w ith a [sal t](https:/ /en.wikipe dia.org/wi ki/Salt_(c ryptograph y&#41;)
  9069        * for  added sec urity.
  9070        *
  9071        * The  name of t he headers  can be sp ecified us ing the xs rfHeaderNa me and xsr fCookieNam e
  9072        * pro perties of  either $h ttpProvide r.defaults  at config -time, $ht tp.default s at run-t ime,
  9073        * or  the per-re quest conf ig object.
  9074        *
  9075        *
  9076        * @pa ram {objec t} config  Object des cribing th e request  to be made  and how i t should b e
  9077        *     processed.  The objec t has foll owing prop erties:
  9078        *
  9079        *     - **method ** â€“ `{s tring}` â€ “ HTTP met hod (e.g.  'GET', 'PO ST', etc)
  9080        *     - **url**  – `{stri ng}` â€“ A bsolute or  relative  URL of the  resource  that is be ing reques ted.
  9081        *     - **params ** â€“ `{O bject.<str ing|Object >}` â€“ Ma p of strin gs or obje cts which  will be tu rned
  9082        *       to `?key 1=value1&k ey2=value2 ` after th e url. If  the value  is not a s tring, it  will be
  9083        *       JSONifie d.
  9084        *     - **data**  â€“ `{str ing|Object }` â€“ Dat a to be se nt as the  request me ssage data .
  9085        *     - **header s** â€“ `{ Object}` â €“ Map of  strings or  functions  which ret urn string s represen ting
  9086        *       HTTP hea ders to se nd to the  server. If  the retur n value of  a functio n is null,  the
  9087        *       header w ill not be  sent.
  9088        *     - **xsrfHe aderName**  â€“ `{str ing}` â€“  Name of HT TP header  to populat e with the  XSRF toke n.
  9089        *     - **xsrfCo okieName**  â€“ `{str ing}` â€“  Name of co okie conta ining the  XSRF token .
  9090        *     - **transf ormRequest ** â€“
  9091        *       `{functi on(data, h eadersGett er)|Array. <function( data, head ersGetter) >}` â€“
  9092        *       transfor m function  or an arr ay of such  functions . The tran sform func tion takes  the http
  9093        *       request  body and h eaders and  returns i ts transfo rmed (typi cally seri alized) ve rsion.
  9094        *       See {@li nk ng.$htt p#overridi ng-the-def ault-trans formations -per-reque st
  9095        *       Overridi ng the Def ault Trans formations }
  9096        *     - **transf ormRespons e** â€“
  9097        *       `{functi on(data, h eadersGett er)|Array. <function( data, head ersGetter) >}` â€“
  9098        *       transfor m function  or an arr ay of such  functions . The tran sform func tion takes  the http
  9099        *       response  body and  headers an d returns  its transf ormed (typ ically des erialized)  version.
  9100        *       See {@li nk ng.$htt p#overridi ng-the-def ault-trans formations -per-reque st
  9101        *       Overridi ng the Def ault Trans formations }
  9102        *     - **cache* * â€“ `{bo olean|Cach e}` â€“ If  true, a d efault $ht tp cache w ill be use d to cache  the
  9103        *       GET requ est, other wise if a  cache inst ance built  with
  9104        *       {@link n g.$cacheFa ctory $cac heFactory} , this cac he will be  used for
  9105        *       caching.
  9106        *     - **timeou t** â€“ `{ number|Pro mise}` â€“  timeout i n millisec onds, or { @link ng.$ q promise}
  9107        *       that sho uld abort  the reques t when res olved.
  9108        *     - **withCr edentials* * - `{bool ean}` - wh ether to s et the `wi thCredenti als` flag  on the
  9109        *       XHR obje ct. See [r equests wi th credent ials](http s://develo per.mozill a.org/docs /Web/HTTP/ Access_con trol_CORS# Requests_w ith_creden tials)
  9110        *       for more  informati on.
  9111        *     - **respon seType** -  `{string} ` - see
  9112        *       [request Type](http s://develo per.mozill a.org/en-U S/docs/DOM /XMLHttpRe quest#resp onseType).
  9113        *
  9114        * @re turns {Htt pPromise}  Returns a  {@link ng. $q promise } object w ith the
  9115        *   s tandard `t hen` metho d and two  http speci fic method s: `succes s` and `er ror`. The  `then`
  9116        *   m ethod take s two argu ments a su ccess and  an error c allback wh ich will b e called w ith a
  9117        *   r esponse ob ject. The  `success`  and `error ` methods  take a sin gle argume nt - a fun ction that
  9118        *   w ill be cal led when t he request  succeeds  or fails r espectivel y. The arg uments pas sed into
  9119        *   t hese funct ions are d estructure d represen tation of  the respon se object  passed int o the
  9120        *   ` then` meth od. The re sponse obj ect has th ese proper ties:
  9121        *
  9122        *   -  **data**  – `{stri ng|Object} ` â€“ The  response b ody transf ormed with  the trans form
  9123        *      functions .
  9124        *   -  **status* * â€“ `{nu mber}` â€“  HTTP stat us code of  the respo nse.
  9125        *   -  **headers ** â€“ `{f unction([h eaderName] )}` â€“ He ader gette r function .
  9126        *   -  **config* * â€“ `{Ob ject}` â€“  The confi guration o bject that  was used  to generat e the requ est.
  9127        *   -  **statusT ext** â€“  `{string}`  â€“ HTTP  status tex t of the r esponse.
  9128        *
  9129        * @pr operty {Ar ray.<Objec t>} pendin gRequests  Array of c onfig obje cts for cu rrently pe nding
  9130        *   r equests. T his is pri marily mea nt to be u sed for de bugging pu rposes.
  9131        *
  9132        *
  9133        * @ex ample
  9134   <example m odule="htt pExample">
  9135   <file name ="index.ht ml">
  9136     <div ng- controller ="FetchCon troller">
  9137       <selec t ng-model ="method">
  9138         <opt ion>GET</o ption>
  9139         <opt ion>JSONP< /option>
  9140       </sele ct>
  9141       <input  type="tex t" ng-mode l="url" si ze="80"/>
  9142       <butto n id="fetc hbtn" ng-c lick="fetc h()">fetch </button>< br>
  9143       <butto n id="samp legetbtn"  ng-click=" updateMode l('GET', ' http-hello .html')">S ample GET< /button>
  9144       <butto n id="samp lejsonpbtn "
  9145         ng-c lick="upda teModel('J SONP',
  9146                         'https://a ngularjs.o rg/greet.p hp?callbac k=JSON_CAL LBACK&name =Super%20H ero')">
  9147         Samp le JSONP
  9148       </butt on>
  9149       <butto n id="inva lidjsonpbt n"
  9150         ng-c lick="upda teModel('J SONP', 'ht tps://angu larjs.org/ doesntexis t&callback =JSON_CALL BACK')">
  9151           In valid JSON P
  9152         </bu tton>
  9153       <pre>h ttp status  code: {{s tatus}}</p re>
  9154       <pre>h ttp respon se data: { {data}}</p re>
  9155     </div>
  9156   </file>
  9157   <file name ="script.j s">
  9158     angular. module('ht tpExample' , [])
  9159       .contr oller('Fet chControll er', ['$sc ope', '$ht tp', '$tem plateCache ',
  9160         func tion($scop e, $http,  $templateC ache) {
  9161           $s cope.metho d = 'GET';
  9162           $s cope.url =  'http-hel lo.html';
  9163  
  9164           $s cope.fetch  = functio n() {
  9165              $scope.cod e = null;
  9166              $scope.res ponse = nu ll;
  9167  
  9168              $http({met hod: $scop e.method,  url: $scop e.url, cac he: $templ ateCache}) .
  9169                success( function(d ata, statu s) {
  9170                  $scope .status =  status;
  9171                  $scope .data = da ta;
  9172                }).
  9173                error(fu nction(dat a, status)  {
  9174                  $scope .data = da ta || "Req uest faile d";
  9175                  $scope .status =  status;
  9176              });
  9177           };
  9178  
  9179           $s cope.updat eModel = f unction(me thod, url)  {
  9180              $scope.met hod = meth od;
  9181              $scope.url  = url;
  9182           };
  9183         }]);
  9184   </file>
  9185   <file name ="http-hel lo.html">
  9186     Hello, $ http!
  9187   </file>
  9188   <file name ="protract or.js" typ e="protrac tor">
  9189     var stat us = eleme nt(by.bind ing('statu s'));
  9190     var data  = element (by.bindin g('data')) ;
  9191     var fetc hBtn = ele ment(by.id ('fetchbtn '));
  9192     var samp leGetBtn =  element(b y.id('samp legetbtn') );
  9193     var samp leJsonpBtn  = element (by.id('sa mplejsonpb tn'));
  9194     var inva lidJsonpBt n = elemen t(by.id('i nvalidjson pbtn'));
  9195  
  9196     it('shou ld make an  xhr GET r equest', f unction()  {
  9197       sample GetBtn.cli ck();
  9198       fetchB tn.click() ;
  9199       expect (status.ge tText()).t oMatch('20 0');
  9200       expect (data.getT ext()).toM atch(/Hell o, \$http! /);
  9201     });
  9202  
  9203   // Comment ed out due  to flakes . See http s://github .com/angul ar/angular .js/issues /9185
  9204   // it('sho uld make a  JSONP req uest to an gularjs.or g', functi on() {
  9205   //   sampl eJsonpBtn. click();
  9206   //   fetch Btn.click( );
  9207   //   expec t(status.g etText()). toMatch('2 00');
  9208   //   expec t(data.get Text()).to Match(/Sup er Hero!/) ;
  9209   // });
  9210  
  9211     it('shou ld make JS ONP reques t to inval id URL and  invoke th e error ha ndler',
  9212         func tion() {
  9213       invali dJsonpBtn. click();
  9214       fetchB tn.click() ;
  9215       expect (status.ge tText()).t oMatch('0' );
  9216       expect (data.getT ext()).toM atch('Requ est failed ');
  9217     });
  9218   </file>
  9219   </example>
  9220        */
  9221       functi on $http(r equestConf ig) {
  9222         var  config = {
  9223           me thod: 'get ',
  9224           tr ansformReq uest: defa ults.trans formReques t,
  9225           tr ansformRes ponse: def aults.tran sformRespo nse
  9226         };
  9227         var  headers =  mergeHeade rs(request Config);
  9228  
  9229         if ( !angular.i sObject(re questConfi g)) {
  9230           th row minErr ('$http')( 'badreq',  'Http requ est config uration mu st be an o bject.  Re ceived: {0 }', reques tConfig);
  9231         }
  9232  
  9233         exte nd(config,  requestCo nfig);
  9234         conf ig.headers  = headers ;
  9235         conf ig.method  = uppercas e(config.m ethod);
  9236  
  9237         var  serverRequ est = func tion(confi g) {
  9238           he aders = co nfig.heade rs;
  9239             var reqDat a = transf
D NS     a(config.d ata, heade rsGetter(h eaders), c onfig.tran sformReque st);
  9240  
  9241           //  strip con tent-type  if data is  undefined
  9242           if  (isUndefi ned(reqDat a)) {
  9243              forEach(he aders, fun ction(valu e, header)  {
  9244                if (lowe rcase(head er) === 'c ontent-typ e') {
  9245                    dele te headers [header];
  9246                }
  9247              });
  9248           }
  9249  
  9250           if  (isUndefi ned(config .withCrede ntials) &&  !isUndefi ned(defaul ts.withCre dentials))  {
  9251              config.wit hCredentia ls = defau lts.withCr edentials;
  9252           }
  9253  
  9254           //  send requ est
  9255           re turn sendR eq(config,  reqData,  headers).t hen(transf ormRespons e, transfo rmResponse );
  9256         };
  9257  
  9258         var  chain = [s erverReque st, undefi ned];
  9259         var  promise =  $q.when(co nfig);
  9260  
  9261         // a pply inter ceptors
  9262         forE ach(revers edIntercep tors, func tion(inter ceptor) {
  9263           if  (intercep tor.reques t || inter ceptor.req uestError)  {
  9264              chain.unsh ift(interc eptor.requ est, inter ceptor.req uestError) ;
  9265           }
  9266           if  (intercep tor.respon se || inte rceptor.re sponseErro r) {
  9267              chain.push (intercept or.respons e, interce ptor.respo nseError);
  9268           }
  9269         });
  9270  
  9271         whil e (chain.l ength) {
  9272           va r thenFn =  chain.shi ft();
  9273           va r rejectFn  = chain.s hift();
  9274  
  9275           pr omise = pr omise.then (thenFn, r ejectFn);
  9276         }
  9277  
  9278         prom ise.succes s = functi on(fn) {
  9279           pr omise.then (function( response)  {
  9280              fn(respons e.data, re sponse.sta tus, respo nse.header s, config) ;
  9281           }) ;
  9282           re turn promi se;
  9283         };
  9284  
  9285         prom ise.error  = function (fn) {
  9286           pr omise.then (null, fun ction(resp onse) {
  9287              fn(respons e.data, re sponse.sta tus, respo nse.header s, config) ;
  9288           }) ;
  9289           re turn promi se;
  9290         };
  9291  
  9292         retu rn promise ;
  9293  
  9294         func tion trans formRespon se(respons e) {
  9295           //  make a co py since t he respons e must be  cacheable
  9296           va r resp = e xtend({},  response);
  9297           if  (!respons e.data) {
  9298              resp.data  = response .data;
  9299           }  else {
  9300               resp.data  = transf
D NS     a(response .data, res ponse.head ers, confi g.transfor mResponse) ;
  9301           }
  9302           re turn (isSu ccess(resp onse.statu s))
  9303              ? resp
  9304              : $q.rejec t(resp);
  9305         }
  9306  
  9307         func tion merge Headers(co nfig) {
  9308           va r defHeade rs = defau lts.header s,
  9309                reqHeade rs = exten d({}, conf ig.headers ),
  9310                defHeade rName, low ercaseDefH eaderName,  reqHeader Name;
  9311  
  9312           de fHeaders =  extend({} , defHeade rs.common,  defHeader s[lowercas e(config.m ethod)]);
  9313  
  9314           //  using for -in instea d of forEa ch to avoi d unecessa ry iterati on after h eader has  been found
  9315           de faultHeade rsIteratio n:
  9316           fo r (defHead erName in  defHeaders ) {
  9317              lowercaseD efHeaderNa me = lower case(defHe aderName);
  9318  
  9319              for (reqHe aderName i n reqHeade rs) {
  9320                if (lowe rcase(reqH eaderName)  === lower caseDefHea derName) {
  9321                  contin ue default HeadersIte ration;
  9322                }
  9323              }
  9324  
  9325              reqHeaders [defHeader Name] = de fHeaders[d efHeaderNa me];
  9326           }
  9327  
  9328           //  execute i f header v alue is a  function f or merged  headers
  9329           ex ecHeaders( reqHeaders );
  9330           re turn reqHe aders;
  9331  
  9332           fu nction exe cHeaders(h eaders) {
  9333              var header Content;
  9334  
  9335              forEach(he aders, fun ction(head erFn, head er) {
  9336                if (isFu nction(hea derFn)) {
  9337                  header Content =  headerFn() ;
  9338                  if (he aderConten t != null)  {
  9339                    head ers[header ] = header Content;
  9340                  } else  {
  9341                    dele te headers [header];
  9342                  }
  9343                }
  9344              });
  9345           }
  9346         }
  9347       }
  9348  
  9349       $http. pendingReq uests = [] ;
  9350  
  9351       /**
  9352        * @ng doc method
  9353        * @na me $http#g et
  9354        *
  9355        * @de scription
  9356        * Sho rtcut meth od to perf orm `GET`  request.
  9357        *
  9358        * @pa ram {strin g} url Rel ative or a bsolute UR L specifyi ng the des tination o f the requ est
  9359        * @pa ram {Objec t=} config  Optional  configurat ion object
  9360        * @re turns {Htt pPromise}  Future obj ect
  9361        */
  9362  
  9363       /**
  9364        * @ng doc method
  9365        * @na me $http#d elete
  9366        *
  9367        * @de scription
  9368        * Sho rtcut meth od to perf orm `DELET E` request .
  9369        *
  9370        * @pa ram {strin g} url Rel ative or a bsolute UR L specifyi ng the des tination o f the requ est
  9371        * @pa ram {Objec t=} config  Optional  configurat ion object
  9372        * @re turns {Htt pPromise}  Future obj ect
  9373        */
  9374  
  9375       /**
  9376        * @ng doc method
  9377        * @na me $http#h ead
  9378        *
  9379        * @de scription
  9380        * Sho rtcut meth od to perf orm `HEAD`  request.
  9381        *
  9382        * @pa ram {strin g} url Rel ative or a bsolute UR L specifyi ng the des tination o f the requ est
  9383        * @pa ram {Objec t=} config  Optional  configurat ion object
  9384        * @re turns {Htt pPromise}  Future obj ect
  9385        */
  9386  
  9387       /**
  9388        * @ng doc method
  9389        * @na me $http#j sonp
  9390        *
  9391        * @de scription
  9392        * Sho rtcut meth od to perf orm `JSONP ` request.
  9393        *
  9394        * @pa ram {strin g} url Rel ative or a bsolute UR L specifyi ng the des tination o f the requ est.
  9395        *                       The  name of t he callbac k should b e the stri ng `JSON_C ALLBACK`.
  9396        * @pa ram {Objec t=} config  Optional  configurat ion object
  9397        * @re turns {Htt pPromise}  Future obj ect
  9398        */
  9399       create ShortMetho ds('get',  'delete',  'head', 'j sonp');
  9400  
  9401       /**
  9402        * @ng doc method
  9403        * @na me $http#p ost
  9404        *
  9405        * @de scription
  9406        * Sho rtcut meth od to perf orm `POST`  request.
  9407        *
  9408        * @pa ram {strin g} url Rel ative or a bsolute UR L specifyi ng the des tination o f the requ est
  9409        * @pa ram {*} da ta Request  content
  9410        * @pa ram {Objec t=} config  Optional  configurat ion object
  9411        * @re turns {Htt pPromise}  Future obj ect
  9412        */
  9413  
  9414       /**
  9415        * @ng doc method
  9416        * @na me $http#p ut
  9417        *
  9418        * @de scription
  9419        * Sho rtcut meth od to perf orm `PUT`  request.
  9420        *
  9421        * @pa ram {strin g} url Rel ative or a bsolute UR L specifyi ng the des tination o f the requ est
  9422        * @pa ram {*} da ta Request  content
  9423        * @pa ram {Objec t=} config  Optional  configurat ion object
  9424        * @re turns {Htt pPromise}  Future obj ect
  9425        */
  9426  
  9427        /**
  9428         * @n gdoc metho d
  9429         * @n ame $http# patch
  9430         *
  9431         * @d escription
  9432         * Sh ortcut met hod to per form `PATC H` request .
  9433         *
  9434         * @p aram {stri ng} url Re lative or  absolute U RL specify ing the de stination  of the req uest
  9435         * @p aram {*} d ata Reques t content
  9436         * @p aram {Obje ct=} confi g Optional  configura tion objec t
  9437         * @r eturns {Ht tpPromise}  Future ob ject
  9438         */
  9439       create ShortMetho dsWithData ('post', ' put', 'pat ch');
  9440  
  9441           /* *
  9442            *  @ngdoc pr operty
  9443            *  @name $ht tp#default s
  9444            *
  9445            *  @descript ion
  9446            *  Runtime e quivalent  of the `$h ttpProvide r.defaults ` property . Allows c onfigurati on of
  9447            *  default h eaders, wi thCredenti als as wel l as reque st and res ponse tran sformation s.
  9448            *
  9449            *  See "Sett ing HTTP H eaders" an d "Transfo rming Requ ests and R esponses"  sections a bove.
  9450            * /
  9451       $http. defaults =  defaults;
  9452  
  9453  
  9454       return  $http;
  9455  
  9456  
  9457       functi on createS hortMethod s(names) {
  9458         forE ach(argume nts, funct ion(name)  {
  9459           $h ttp[name]  = function (url, conf ig) {
  9460              return $ht tp(extend( config ||  {}, {
  9461                method:  name,
  9462                url: url
  9463              }));
  9464           };
  9465         });
  9466       }
  9467  
  9468  
  9469       functi on createS hortMethod sWithData( name) {
  9470         forE ach(argume nts, funct ion(name)  {
  9471           $h ttp[name]  = function (url, data , config)  {
  9472              return $ht tp(extend( config ||  {}, {
  9473                method:  name,
  9474                url: url ,
  9475                data: da ta
  9476              }));
  9477           };
  9478         });
  9479       }
  9480  
  9481  
  9482       /**
  9483        * Mak es the req uest.
  9484        *
  9485        * !!!  ACCESSES  CLOSURE VA RS:
  9486        * $ht tpBackend,  defaults,  $log, $ro otScope, d efaultCach e, $http.p endingRequ ests
  9487        */
  9488       functi on sendReq (config, r eqData, re qHeaders)  {
  9489         var  deferred =  $q.defer( ),
  9490              promise =  deferred.p romise,
  9491              cache,
  9492              cachedResp ,
  9493              url = buil dUrl(confi g.url, con fig.params );
  9494  
  9495         $htt p.pendingR equests.pu sh(config) ;
  9496         prom ise.then(r emovePendi ngReq, rem ovePending Req);
  9497  
  9498  
  9499         if ( (config.ca che || def aults.cach e) && conf ig.cache ! == false & &
  9500              (config.me thod === ' GET' || co nfig.metho d === 'JSO NP')) {
  9501           ca che = isOb ject(confi g.cache) ?  config.ca che
  9502                  : isOb ject(defau lts.cache)  ? default s.cache
  9503                  : defa ultCache;
  9504         }
  9505  
  9506         if ( cache) {
  9507           ca chedResp =  cache.get (url);
  9508           if  (isDefine d(cachedRe sp)) {
  9509              if (isProm iseLike(ca chedResp))  {
  9510                // cache d request  has alread y been sen t, but the re is no r esponse ye t
  9511                cachedRe sp.then(re movePendin gReq, remo vePendingR eq);
  9512                return c achedResp;
  9513              } else {
  9514                // servi ng from ca che
  9515                if (isAr ray(cached Resp)) {
  9516                  resolv ePromise(c achedResp[ 1], cached Resp[0], s hallowCopy (cachedRes p[2]), cac hedResp[3] );
  9517                } else {
  9518                  resolv ePromise(c achedResp,  200, {},  'OK');
  9519                }
  9520              }
  9521           }  else {
  9522              // put the  promise f or the non -transform ed respons e into cac he as a pl aceholder
  9523              cache.put( url, promi se);
  9524           }
  9525         }
  9526  
  9527  
  9528         // i f we won't  have the  response i n cache, s et the xsr f headers  and
  9529         // s end the re quest to t he backend
  9530         if ( isUndefine d(cachedRe sp)) {
  9531           va r xsrfValu e = urlIsS ameOrigin( config.url )
  9532                ? $brows er.cookies ()[config. xsrfCookie Name || de faults.xsr fCookieNam e]
  9533                : undefi ned;
  9534           if  (xsrfValu e) {
  9535              reqHeaders [(config.x srfHeaderN ame || def aults.xsrf HeaderName )] = xsrfV alue;
  9536           }
  9537  
  9538           $h ttpBackend (config.me thod, url,  reqData,  done, reqH eaders, co nfig.timeo ut,
  9539                config.w ithCredent ials, conf ig.respons eType);
  9540         }
  9541  
  9542         retu rn promise ;
  9543  
  9544  
  9545         /**
  9546          * C allback re gistered t o $httpBac kend():
  9547          *   - caches t he respons e if desir ed
  9548          *   - resolves  the raw $ http promi se
  9549          *   - calls $a pply
  9550          */
  9551         func tion done( status, re sponse, he adersStrin g, statusT ext) {
  9552           if  (cache) {
  9553              if (isSucc ess(status )) {
  9554                cache.pu t(url, [st atus, resp onse, pars eHeaders(h eadersStri ng), statu sText]);
  9555              } else {
  9556                // remov e promise  from the c ache
  9557                cache.re move(url);
  9558              }
  9559           }
  9560  
  9561           fu nction res olveHttpPr omise() {
  9562              resolvePro mise(respo nse, statu s, headers String, st atusText);
  9563           }
  9564  
  9565           if  (useApply Async) {
  9566              $rootScope .$applyAsy nc(resolve HttpPromis e);
  9567           }  else {
  9568              resolveHtt pPromise() ;
  9569              if (!$root Scope.$$ph ase) $root Scope.$app ly();
  9570           }
  9571         }
  9572  
  9573  
  9574         /**
  9575          * R esolves th e raw $htt p promise.
  9576          */
  9577         func tion resol vePromise( response,  status, he aders, sta tusText) {
  9578           //  normalize  internal  statuses t o 0
  9579           st atus = Mat h.max(stat us, 0);
  9580  
  9581           (i sSuccess(s tatus) ? d eferred.re solve : de ferred.rej ect)({
  9582              data: resp onse,
  9583              status: st atus,
  9584              headers: h eadersGett er(headers ),
  9585              config: co nfig,
  9586              statusText : statusTe xt
  9587           }) ;
  9588         }
  9589  
  9590  
  9591         func tion remov ePendingRe q() {
  9592           va r idx = $h ttp.pendin gRequests. indexOf(co nfig);
  9593           if  (idx !==  -1) $http. pendingReq uests.spli ce(idx, 1) ;
  9594         }
  9595       }
  9596  
  9597  
  9598       functi on buildUr l(url, par ams) {
  9599         if ( !params) r eturn url;
  9600         var  parts = [] ;
  9601         forE achSorted( params, fu nction(val ue, key) {
  9602           if  (value == = null ||  isUndefine d(value))  return;
  9603           if  (!isArray (value)) v alue = [va lue];
  9604  
  9605           fo rEach(valu e, functio n(v) {
  9606              if (isObje ct(v)) {
  9607                if (isDa te(v)) {
  9608                  v = v. toISOStrin g();
  9609                } else {
  9610                  v = to Json(v);
  9611                }
  9612              }
  9613              parts.push (encodeUri Query(key)  + '=' +
  9614                          encodeUri Query(v));
  9615           }) ;
  9616         });
  9617         if ( parts.leng th > 0) {
  9618           ur l += ((url .indexOf(' ?') == -1)  ? '?' : ' &') + part s.join('&' );
  9619         }
  9620         retu rn url;
  9621       }
  9622     }];
  9623   }
  9624  
  9625   function c reateXhr()  {
  9626       return  new windo w.XMLHttpR equest();
  9627   }
  9628  
  9629   /**
  9630    * @ngdoc  service
  9631    * @name $ httpBacken d
  9632    * @requir es $window
  9633    * @requir es $docume nt
  9634    *
  9635    * @descri ption
  9636    * HTTP ba ckend used  by the {@ link ng.$h ttp servic e} that de legates to
  9637    * XMLHttp Request ob ject or JS ONP and de als with b rowser inc ompatibili ties.
  9638    *
  9639    * You sho uld never  need to us e this ser vice direc tly, inste ad use the  higher-le vel abstra ctions:
  9640    * {@link  ng.$http $ http} or { @link ngRe source.$re source $re source}.
  9641    *
  9642    * During  testing th is impleme ntation is  swapped w ith {@link  ngMock.$h ttpBackend  mock
  9643    * $httpBa ckend} whi ch can be  trained wi th respons es.
  9644    */
  9645   function $ HttpBacken dProvider( ) {
  9646     this.$ge t = ['$bro wser', '$w indow', '$ document',  function( $browser,  $window, $ document)  {
  9647       return  createHtt pBackend($ browser, c reateXhr,  $browser.d efer, $win dow.angula r.callback s, $docume nt[0]);
  9648     }];
  9649   }
  9650  
  9651   function c reateHttpB ackend($br owser, cre ateXhr, $b rowserDefe r, callbac ks, rawDoc ument) {
  9652     // TODO( vojta): fi x the sign ature
  9653     return f unction(me thod, url,  post, cal lback, hea ders, time out, withC redentials , response Type) {
  9654       $brows er.$$incOu tstandingR equestCoun t();
  9655       url =  url || $br owser.url( );
  9656  
  9657       if (lo wercase(me thod) == ' jsonp') {
  9658         var  callbackId  = '_' + ( callbacks. counter++) .toString( 36);
  9659         call backs[call backId] =  function(d ata) {
  9660           ca llbacks[ca llbackId]. data = dat a;
  9661           ca llbacks[ca llbackId]. called = t rue;
  9662         };
  9663  
  9664         var  jsonpDone  = jsonpReq (url.repla ce('JSON_C ALLBACK',  'angular.c allbacks.'  + callbac kId),
  9665              callbackId , function (status, t ext) {
  9666           co mpleteRequ est(callba ck, status , callback s[callback Id].data,  "", text);
  9667           ca llbacks[ca llbackId]  = noop;
  9668         });
  9669       } else  {
  9670  
  9671         var  xhr = crea teXhr();
  9672  
  9673         xhr. open(metho d, url, tr ue);
  9674         forE ach(header s, functio n(value, k ey) {
  9675           if  (isDefine d(value))  {
  9676                xhr.setR equestHead er(key, va lue);
  9677           }
  9678         });
  9679  
  9680         xhr. onload = f unction re questLoade d() {
  9681           va r statusTe xt = xhr.s tatusText  || '';
  9682  
  9683           //  responseT ext is the  old-schoo l way of r etrieving  response ( supported  by IE8 & 9 )
  9684           //  response/ responseTy pe propert ies were i ntroduced  in XHR Lev el2 spec ( supported  by IE10)
  9685           va r response  = ('respo nse' in xh r) ? xhr.r esponse :  xhr.respon seText;
  9686  
  9687           //  normalize  IE9 bug ( http://bug s.jquery.c om/ticket/ 1450)
  9688           va r status =  xhr.statu s === 1223  ? 204 : x hr.status;
  9689  
  9690           //  fix statu s code whe n it is 0  (0 status  is undocum ented).
  9691           //  Occurs wh en accessi ng file re sources or  on Androi d 4.1 stoc k browser
  9692           //  while ret rieving fi les from a pplication  cache.
  9693           if  (status = == 0) {
  9694              status = r esponse ?  200 : urlR esolve(url ).protocol  == 'file'  ? 404 : 0 ;
  9695           }
  9696  
  9697           co mpleteRequ est(callba ck,
  9698                status,
  9699                response ,
  9700                xhr.getA llResponse Headers(),
  9701                statusTe xt);
  9702         };
  9703  
  9704         var  requestErr or = funct ion() {
  9705           //  The respo nse is alw ays empty
  9706           //  See https ://xhr.spe c.whatwg.o rg/#reques t-error-st eps and ht tps://fetc h.spec.wha twg.org/#c oncept-net work-error
  9707           co mpleteRequ est(callba ck, -1, nu ll, null,  '');
  9708         };
  9709  
  9710         xhr. onerror =  requestErr or;
  9711         xhr. onabort =  requestErr or;
  9712  
  9713         if ( withCreden tials) {
  9714           xh r.withCred entials =  true;
  9715         }
  9716  
  9717         if ( responseTy pe) {
  9718           tr y {
  9719              xhr.respon seType = r esponseTyp e;
  9720           }  catch (e)  {
  9721              // WebKit  added supp ort for th e json res ponseType  value on 0 9/03/2013
  9722              // https:/ /bugs.webk it.org/sho w_bug.cgi? id=73648.  Versions o f Safari p rior to 7  are
  9723              // known t o throw wh en setting  the value  "json" as  the respo nse type.  Other olde r
  9724              // browser s implemen ting the r esponseTyp e
  9725              //
  9726              // The jso n response  type can  be ignored  if not su pported, b ecause JSO N payloads  are
  9727              // parsed  on the cli ent-side r egardless.
  9728              if (respon seType !==  'json') {
  9729                throw e;
  9730              }
  9731           }
  9732         }
  9733  
  9734         xhr. send(post  || null);
  9735       }
  9736  
  9737       if (ti meout > 0)  {
  9738         var  timeoutId  = $browser Defer(time outRequest , timeout) ;
  9739       } else  if (isPro miseLike(t imeout)) {
  9740         time out.then(t imeoutRequ est);
  9741       }
  9742  
  9743  
  9744       functi on timeout Request()  {
  9745         json pDone && j sonpDone() ;
  9746         xhr  && xhr.abo rt();
  9747       }
  9748  
  9749       functi on complet eRequest(c allback, s tatus, res ponse, hea dersString , statusTe xt) {
  9750         // c ancel time out and su bsequent t imeout pro mise resol ution
  9751         if ( timeoutId  !== undefi ned) {
  9752           $b rowserDefe r.cancel(t imeoutId);
  9753         }
  9754         json pDone = xh r = null;
  9755  
  9756         call back(statu s, respons e, headers String, st atusText);
  9757         $bro wser.$$com pleteOutst andingRequ est(noop);
  9758       }
  9759     };
  9760  
  9761     function  jsonpReq( url, callb ackId, don e) {
  9762       // we  can't use  jQuery/jqL ite here b ecause jQu ery does c razy shit  with scrip t elements , e.g.:
  9763       // - f etches loc al scripts  via XHR a nd evals t hem
  9764       // - a dds and im mediately  removes sc ript eleme nts from t he documen t
  9765       var sc ript = raw Document.c reateEleme nt('script '), callba ck = null;
  9766       script .type = "t ext/javasc ript";
  9767       script .src = url ;
  9768       script .async = t rue;
  9769  
  9770       callba ck = funct ion(event)  {
  9771         remo veEventLis tenerFn(sc ript, "loa d", callba ck);
  9772         remo veEventLis tenerFn(sc ript, "err or", callb ack);
  9773         rawD ocument.bo dy.removeC hild(scrip t);
  9774         scri pt = null;
  9775         var  status = - 1;
  9776         var  text = "un known";
  9777  
  9778         if ( event) {
  9779           if  (event.ty pe === "lo ad" && !ca llbacks[ca llbackId]. called) {
  9780              event = {  type: "err or" };
  9781           }
  9782           te xt = event .type;
  9783           st atus = eve nt.type == = "error"  ? 404 : 20 0;
  9784         }
  9785  
  9786         if ( done) {
  9787           do ne(status,  text);
  9788         }
  9789       };
  9790  
  9791       addEve ntListener Fn(script,  "load", c allback);
  9792       addEve ntListener Fn(script,  "error",  callback);
  9793       rawDoc ument.body .appendChi ld(script) ;
  9794       return  callback;
  9795     }
  9796   }
  9797  
  9798   var $inter polateMinE rr = minEr r('$interp olate');
  9799  
  9800   /**
  9801    * @ngdoc  provider
  9802    * @name $ interpolat eProvider
  9803    *
  9804    * @descri ption
  9805    *
  9806    * Used fo r configur ing the in terpolatio n markup.  Defaults t o `{{` and  `}}`.
  9807    *
  9808    * @exampl e
  9809   <example m odule="cus tomInterpo lationApp" >
  9810   <file name ="index.ht ml">
  9811   <script>
  9812     var cust omInterpol ationApp =  angular.m odule('cus tomInterpo lationApp' , []);
  9813  
  9814     customIn terpolatio nApp.confi g(function ($interpol ateProvide r) {
  9815       $inter polateProv ider.start Symbol('// ');
  9816       $inter polateProv ider.endSy mbol('//') ;
  9817     });
  9818  
  9819  
  9820     customIn terpolatio nApp.contr oller('Dem oControlle r', functi on() {
  9821         this .label = " This bindi ng is brou ght you by  // interp olation sy mbols.";
  9822     });
  9823   </script>
  9824   <div ng-ap p="App" ng -controlle r="DemoCon troller as  demo">
  9825       //demo .label//
  9826   </div>
  9827   </file>
  9828   <file name ="protract or.js" typ e="protrac tor">
  9829     it('shou ld interpo late bindi ng with cu stom symbo ls', funct ion() {
  9830       expect (element(b y.binding( 'demo.labe l')).getTe xt()).toBe ('This bin ding is br ought you  by // inte rpolation  symbols.') ;
  9831     });
  9832   </file>
  9833   </example>
  9834    */
  9835   function $ Interpolat eProvider( ) {
  9836     var star tSymbol =  '{{';
  9837     var endS ymbol = '} }';
  9838  
  9839     /**
  9840      * @ngdo c method
  9841      * @name  $interpol ateProvide r#startSym bol
  9842      * @desc ription
  9843      * Symbo l to denot e start of  expressio n in the i nterpolate d string.  Defaults t o `{{`.
  9844      *
  9845      * @para m {string= } value ne w value to  set the s tarting sy mbol to.
  9846      * @retu rns {strin g|self} Re turns the  symbol whe n used as  getter and  self if u sed as set ter.
  9847      */
  9848     this.sta rtSymbol =  function( value) {
  9849       if (va lue) {
  9850         star tSymbol =  value;
  9851         retu rn this;
  9852       } else  {
  9853         retu rn startSy mbol;
  9854       }
  9855     };
  9856  
  9857     /**
  9858      * @ngdo c method
  9859      * @name  $interpol ateProvide r#endSymbo l
  9860      * @desc ription
  9861      * Symbo l to denot e the end  of express ion in the  interpola ted string . Defaults  to `}}`.
  9862      *
  9863      * @para m {string= } value ne w value to  set the e nding symb ol to.
  9864      * @retu rns {strin g|self} Re turns the  symbol whe n used as  getter and  self if u sed as set ter.
  9865      */
  9866     this.end Symbol = f unction(va lue) {
  9867       if (va lue) {
  9868         endS ymbol = va lue;
  9869         retu rn this;
  9870       } else  {
  9871         retu rn endSymb ol;
  9872       }
  9873     };
  9874  
  9875  
  9876     this.$ge t = ['$par se', '$exc eptionHand ler', '$sc e', functi on($parse,  $exceptio nHandler,  $sce) {
  9877       var st artSymbolL ength = st artSymbol. length,
  9878           en dSymbolLen gth = endS ymbol.leng th,
  9879           es capedStart Regexp = n ew RegExp( startSymbo l.replace( /./g, esca pe), 'g'),
  9880           es capedEndRe gexp = new  RegExp(en dSymbol.re place(/./g , escape),  'g');
  9881  
  9882       functi on escape( ch) {
  9883         retu rn '\\\\\\ ' + ch;
  9884       }
  9885  
  9886       /**
  9887        * @ng doc servic e
  9888        * @na me $interp olate
  9889        * @ki nd functio n
  9890        *
  9891        * @re quires $pa rse
  9892        * @re quires $sc e
  9893        *
  9894        * @de scription
  9895        *
  9896        * Com piles a st ring with  markup int o an inter polation f unction. T his servic e is used  by the
  9897        * HTM L {@link n g.$compile  $compile}  service f or data bi nding. See
  9898        * {@l ink ng.$in terpolateP rovider $i nterpolate Provider}  for config uring the
  9899        * int erpolation  markup.
  9900        *
  9901        *
  9902        * ``` js
  9903        *   v ar $interp olate = .. .; // inje cted
  9904        *   v ar exp = $ interpolat e('Hello { {name | up percase}}! ');
  9905        *   e xpect(exp( {name:'Ang ular'}).to Equal('Hel lo ANGULAR !');
  9906        * ```
  9907        *
  9908        * `$i nterpolate ` takes an  optional  fourth arg ument, `al lOrNothing `. If `all OrNothing`  is
  9909        * `tr ue`, the i nterpolati on functio n will ret urn `undef ined` unle ss all emb edded expr essions
  9910        * eva luate to a  value oth er than `u ndefined`.
  9911        *
  9912        * ``` js
  9913        *   v ar $interp olate = .. .; // inje cted
  9914        *   v ar context  = {greeti ng: 'Hello ', name: u ndefined } ;
  9915        *
  9916        *   / / default  "forgiving " mode
  9917        *   v ar exp = $ interpolat e('{{greet ing}} {{na me}}!');
  9918        *   e xpect(exp( context)). toEqual('H ello !');
  9919        *
  9920        *   / / "allOrNo thing" mod e
  9921        *   e xp = $inte rpolate('{ {greeting} } {{name}} !', false,  null, tru e);
  9922        *   e xpect(exp( context)). toBeUndefi ned();
  9923        *   c ontext.nam e = 'Angul ar';
  9924        *   e xpect(exp( context)). toEqual('H ello Angul ar!');
  9925        * ```
  9926        *
  9927        * `al lOrNothing ` is usefu l for inte rpolating  URLs. `ngS rc` and `n gSrcset` u se this be havior.
  9928        *
  9929        * ### #Escaped I nterpolati on
  9930        * $in terpolate  provides a  mechanism  for escap ing interp olation ma rkers. Sta rt and end  markers
  9931        * can  be escape d by prece ding each  of their c haracters  with a REV ERSE SOLID US U+005C  (backslash ).
  9932        * It  will be re ndered as  a regular  start/end  marker, an d will not  be interp reted as a n expressi on
  9933        * or  binding.
  9934        *
  9935        * Thi s enables  web-server s to preve nt script  injection  attacks an d defacing  attacks,  to some
  9936        * deg ree, while  also enab ling code  examples t o work wit hout relyi ng on the
  9937        * {@l ink ng.dir ective:ngN onBindable  ngNonBind able} dire ctive.
  9938        *
  9939        * **F or securit y purposes , it is st rongly enc ouraged th at web ser vers escap e user-sup plied data ,
  9940        * rep lacing ang le bracket s (&lt;, & gt;) with  &amp;lt; a nd &amp;gt ; respecti vely, and  replacing  all
  9941        * int erpolation  start/end  markers w ith their  escaped co unterparts .**
  9942        *
  9943        * Esc aped inter polation m arkers are  only repl aced with  the actual  interpola tion marke rs in rend ered
  9944        * out put when t he $interp olate serv ice proces ses the te xt. So, fo r HTML ele ments inte rpolated
  9945        * by  {@link ng. $compile $ compile},  or otherwi se interpo lated with  the `must HaveExpres sion` para meter
  9946        * set  to `true` , the inte rpolated t ext must c ontain an  unescaped  interpolat ion expres sion. As s uch,
  9947        * thi s is typic ally usefu l only whe n user-dat a is used  in renderi ng a templ ate from t he server,  or
  9948        * whe n otherwis e untruste d data is  used by a  directive.
  9949        *
  9950        * <ex ample>
  9951        *  <f ile name=" index.html ">
  9952              <div ng-in it=" V s ID           user'">
  9953                <p ng-init ="apptitle ='Escaping  demo'">{{ apptitle}} : \{\{  V s ID                    value"; \} \}
  9954        *         </p>
  9955        *       <p><stro ng>{{usern ame}}</str ong> attem pts to inj ect code w hich will  deface the
  9956        *         applic ation, but  fails to  accomplish  their tas k, because  the serve r has corr ectly
  9957        *         escape d the inte rpolation  start/end  markers wi th REVERSE  SOLIDUS U +005C (bac kslash)
  9958        *         charac ters.</p>
  9959        *       <p>Inste ad, the re sult of th e attempte d script i njection i s visible,  and can b e removed
  9960        *         from t he databas e by an ad ministrato r.</p>
  9961        *     </div>
  9962        *  </ file>
  9963        * </e xample>
  9964        *
  9965        * @pa ram {strin g} text Th e text wit h markup t o interpol ate.
  9966        * @pa ram {boole an=} mustH aveExpress ion if set  to true t hen the in terpolatio n string m ust have
  9967        *     embedded e xpression  in order t o return a n interpol ation func tion. Stri ngs with n o
  9968        *     embedded e xpression  will retur n null for  the inter polation f unction.
  9969        * @pa ram {strin g=} truste dContext w hen provid ed, the re turned fun ction pass es the int erpolated
  9970        *     result thr ough {@lin k ng.$sce# getTrusted  $sce.getT rusted(int erpolatedR esult,
  9971        *     trustedCon text)} bef ore return ing it.  R efer to th e {@link n g.$sce $sc e} service  that
  9972        *     provides S trict Cont extual Esc aping for  details.
  9973        * @pa ram {boole an=} allOr Nothing if  `true`, t hen the re turned fun ction retu rns undefi ned
  9974        *     unless all  embedded  expression s evaluate  to a valu e other th an `undefi ned`.
  9975        * @re turns {fun ction(cont ext)} an i nterpolati on functio n which is  used to c ompute the
  9976        *     interpolat ed string.  The funct ion has th ese parame ters:
  9977        *
  9978        * - ` context`:  evaluation  context f or all exp ressions e mbedded in  the inter polated te xt
  9979        */
  9980       functi on $interp olate(text , mustHave Expression , trustedC ontext, al lOrNothing ) {
  9981         allO rNothing =  !!allOrNo thing;
  9982         var  startIndex ,
  9983              endIndex,
  9984              index = 0,
  9985              expression s = [],
  9986              parseFns =  [],
  9987              textLength  = text.le ngth,
  9988              exp,
  9989              concat = [ ],
  9990              expression Positions  = [];
  9991  
  9992         whil e (index <  textLengt h) {
  9993           if  (((startI ndex = tex t.indexOf( startSymbo l, index))  != -1) &&
  9994                 ((endIn dex = text .indexOf(e ndSymbol,  startIndex  + startSy mbolLength )) != -1))  {
  9995              if (index  !== startI ndex) {
  9996                concat.p ush(unesca peText(tex t.substrin g(index, s tartIndex) ));
  9997              }
  9998              exp = text .substring (startInde x + startS ymbolLengt h, endInde x);
  9999              expression s.push(exp );
  10000              parseFns.p ush($parse (exp, pars eStringify Intercepto r));
  10001              index = en dIndex + e ndSymbolLe ngth;
  10002              expression Positions. push(conca t.length);
  10003              concat.pus h('');
  10004           }  else {
  10005              // we did  not find a n interpol ation, so  we have to  add the r emainder t o the sepa rators arr ay
  10006              if (index  !== textLe ngth) {
  10007                concat.p ush(unesca peText(tex t.substrin g(index))) ;
  10008              }
  10009              break;
  10010           }
  10011         }
  10012  
  10013         // C oncatenati ng express ions makes  it hard t o reason a bout wheth er some co mbination  of
  10014         // c oncatenate d values a re unsafe  to use and  could eas ily lead t o XSS.  By  requiring  that a
  10015         // s ingle expr ession be  used for i frame[src] , object[s rc], etc.,  we ensure  that the  value
  10016         // t hat's used  is assign ed or cons tructed by  some JS c ode somewh ere that i s more tes table or
  10017         // m ake it obv ious that  you bound  the value  to some us er control led value.   This hel ps reduce
  10018         // t he load wh en auditin g for XSS  issues.
  10019         if ( trustedCon text && co ncat.lengt h > 1) {
  10020              throw $int erpolateMi nErr('noco ncat',
  10021                  "Error  while int erpolating : {0}\nStr ict Contex tual Escap ing disall ows " +
  10022                  "inter polations  that conca tenate mul tiple expr essions wh en a trust ed value i s " +
  10023                  "requi red.  See  http://doc s.angularj s.org/api/ ng.$sce",  text);
  10024         }
  10025  
  10026         if ( !mustHaveE xpression  || express ions.lengt h) {
  10027           va r compute  = function (values) {
  10028              for (var i  = 0, ii =  expressio ns.length;  i < ii; i ++) {
  10029                if (allO rNothing & & isUndefi ned(values [i])) retu rn;
  10030                concat[e xpressionP ositions[i ]] = value s[i];
  10031              }
  10032              return con cat.join(' ');
  10033           };
  10034  
  10035           va r getValue  = functio n(value) {
  10036              return tru stedContex t ?
  10037                $sce.get Trusted(tr ustedConte xt, value)  :
  10038                $sce.val ueOf(value );
  10039           };
  10040  
  10041           va r stringif y = functi on(value)  {
  10042              if (value  == null) {  // null | | undefine d
  10043                return ' ';
  10044              }
  10045              switch (ty peof value ) {
  10046                case 'st ring':
  10047                  break;
  10048                case 'nu mber':
  10049                  value  = '' + val ue;
  10050                  break;
  10051                default:
  10052                  value  = toJson(v alue);
  10053              }
  10054  
  10055              return val ue;
  10056           };
  10057  
  10058           re turn exten d(function  interpola tionFn(con text) {
  10059                var i =  0;
  10060                var ii =  expressio ns.length;
  10061                var valu es = new A rray(ii);
  10062  
  10063                try {
  10064                  for (;  i < ii; i ++) {
  10065                    valu es[i] = pa rseFns[i]( context);
  10066                  }
  10067  
  10068                  return  compute(v alues);
  10069                } catch  (err) {
  10070                  var ne wErr = $in terpolateM inErr('int err', "Can 't interpo late: {0}\ n{1}", tex t,
  10071                      er r.toString ());
  10072                  $excep tionHandle r(newErr);
  10073                }
  10074  
  10075              }, {
  10076              // all of  these prop erties are  undocumen ted for no w
  10077              exp: text,  //just fo r compatib ility with  regular w atchers cr eated via  $watch
  10078              expression s: express ions,
  10079              $$watchDel egate: fun ction(scop e, listene r, objectE quality) {
  10080                var last Value;
  10081                return s cope.$watc hGroup(par seFns, fun ction inte rpolateFnW atcher(val ues, oldVa lues) {
  10082                  var cu rrValue =  compute(va lues);
  10083                  if (is Function(l istener))  {
  10084                    list ener.call( this, curr Value, val ues !== ol dValues ?  lastValue  : currValu e, scope);
  10085                  }
  10086                  lastVa lue = curr Value;
  10087                }, objec tEquality) ;
  10088              }
  10089           }) ;
  10090         }
  10091  
  10092         func tion unesc apeText(te xt) {
  10093           re turn text. replace(es capedStart Regexp, st artSymbol) .
  10094              replace(es capedEndRe gexp, endS ymbol);
  10095         }
  10096  
  10097         func tion parse StringifyI nterceptor (value) {
  10098           tr y {
  10099              value = ge tValue(val ue);
  10100              return all OrNothing  && !isDefi ned(value)  ? value :  stringify (value);
  10101           }  catch (err ) {
  10102              var newErr  = $interp olateMinEr r('interr' , "Can't i nterpolate : {0}\n{1} ", text,
  10103                err.toSt ring());
  10104              $exception Handler(ne wErr);
  10105           }
  10106         }
  10107       }
  10108  
  10109  
  10110       /**
  10111        * @ng doc method
  10112        * @na me $interp olate#star tSymbol
  10113        * @de scription
  10114        * Sym bol to den ote the st art of exp ression in  the inter polated st ring. Defa ults to `{ {`.
  10115        *
  10116        * Use  {@link ng .$interpol ateProvide r#startSym bol `$inte rpolatePro vider.star tSymbol`}  to change
  10117        * the  symbol.
  10118        *
  10119        * @re turns {str ing} start  symbol.
  10120        */
  10121       $inter polate.sta rtSymbol =  function( ) {
  10122         retu rn startSy mbol;
  10123       };
  10124  
  10125  
  10126       /**
  10127        * @ng doc method
  10128        * @na me $interp olate#endS ymbol
  10129        * @de scription
  10130        * Sym bol to den ote the en d of expre ssion in t he interpo lated stri ng. Defaul ts to `}}` .
  10131        *
  10132        * Use  {@link ng .$interpol ateProvide r#endSymbo l `$interp olateProvi der.endSym bol`} to c hange
  10133        * the  symbol.
  10134        *
  10135        * @re turns {str ing} end s ymbol.
  10136        */
  10137       $inter polate.end Symbol = f unction()  {
  10138         retu rn endSymb ol;
  10139       };
  10140  
  10141       return  $interpol ate;
  10142     }];
  10143   }
  10144  
  10145   function $ IntervalPr ovider() {
  10146     this.$ge t = ['$roo tScope', ' $window',  '$q', '$$q ',
  10147          fun ction($roo tScope,    $window,    $q,   $$q ) {
  10148       var in tervals =  {};
  10149  
  10150  
  10151        /**
  10152         * @n gdoc servi ce
  10153         * @n ame $inter val
  10154         *
  10155         * @d escription
  10156         * An gular's wr apper for  `window.se tInterval` . The `fn`  function  is execute d every `d elay`
  10157         * mi lliseconds .
  10158         *
  10159         * Th e return v alue of re gistering  an interva l function  is a prom ise. This  promise wi ll be
  10160         * no tified upo n each tic k of the i nterval, a nd will be  resolved  after `cou nt` iterat ions, or
  10161         * ru n indefini tely if `c ount` is n ot defined . The valu e of the n otificatio n will be  the
  10162         * nu mber of it erations t hat have r un.
  10163         * To  cancel an  interval,  call `$in terval.can cel(promis e)`.
  10164         *
  10165         * In  tests you  can use { @link ngMo ck.$interv al#flush ` $interval. flush(mill is)`} to
  10166         * mo ve forward  by `milli s` millise conds and  trigger an y function s schedule d to run i n that
  10167         * ti me.
  10168         *
  10169         * <d iv class=" alert aler t-warning" >
  10170         * ** Note**: In tervals cr eated by t his servic e must be  explicitly  destroyed  when you  are finish ed
  10171         * wi th them.   In particu lar they a re not aut omatically  destroyed  when a co ntroller's  scope or  a
  10172         * di rective's  element ar e destroye d.
  10173         * Yo u should t ake this i nto consid eration an d make sur e to alway s cancel t he interva l at the
  10174         * ap propriate  moment.  S ee the exa mple below  for more  details on  how and w hen to do  this.
  10175         * </ div>
  10176         *
  10177         * @p aram {func tion()} fn  A functio n that sho uld be cal led repeat edly.
  10178         * @p aram {numb er} delay  Number of  millisecon ds between  each func tion call.
  10179         * @p aram {numb er=} [coun t=0] Numbe r of times  to repeat . If not s et, or 0,  will repea t
  10180         *    indefinite ly.
  10181         * @p aram {bool ean=} [inv okeApply=t rue] If se t to `fals e` skips m odel dirty  checking,  otherwise
  10182         *    will invok e `fn` wit hin the {@ link ng.$r ootScope.S cope#$appl y $apply}  block.
  10183         * @r eturns {pr omise} A p romise whi ch will be  notified  on each it eration.
  10184         *
  10185         * @e xample
  10186           * <example  module="i nter DNS    ample">
  10187         * <f ile name=" index.html ">
  10188         *    <script>
  10189                angular.mo dule('inte r DNS    ample', [] )
  10190         *        .contr oller('Exa mpleContro ller', ['$ scope', '$ interval',
  10191         *          func tion($scop e, $interv al) {
  10192         *            $s cope.forma t = 'M/d/y y h:mm:ss  a';
  10193         *            $s cope.blood _1 = 100;
  10194         *            $s cope.blood _2 = 120;
  10195         *
  10196         *            va r stop;
  10197         *            $s cope.fight  = functio n() {
  10198         *               // Don't s tart a new  fight if  we are alr eady fight ing
  10199         *               if ( angul ar.isDefin ed(stop) )  return;
  10200         *
  10201         *            st op = $inte rval(funct ion() {
  10202         *               if ($scope .blood_1 >  0 && $sco pe.blood_2  > 0) {
  10203         *                 $scope.b lood_1 = $ scope.bloo d_1 - 3;
  10204         *                 $scope.b lood_2 = $ scope.bloo d_2 - 4;
  10205         *               } else {
  10206         *                 $scope.s topFight() ;
  10207         *               }
  10208         *            },  100);
  10209         *          };
  10210         *
  10211         *          $sco pe.stopFig ht = funct ion() {
  10212         *            if  (angular. isDefined( stop)) {
  10213         *               $interval. cancel(sto p);
  10214         *               stop = und efined;
  10215         *            }
  10216         *          };
  10217         *
  10218         *          $sco pe.resetFi ght = func tion() {
  10219         *            $s cope.blood _1 = 100;
  10220         *            $s cope.blood _2 = 120;
  10221         *          };
  10222         *
  10223         *          $sco pe.$on('$d estroy', f unction()  {
  10224         *            //  Make sure  that the  interval i s destroye d too
  10225         *            $s cope.stopF ight();
  10226         *          });
  10227         *        }])
  10228         *        // Reg ister the  'myCurrent Time' dire ctive fact ory method .
  10229         *        // We  inject $in terval and  dateFilte r service  since the  factory me thod is DI .
  10230         *        .direc tive('myCu rrentTime' , ['$inter val', 'dat eFilter',
  10231         *          func tion($inte rval, date Filter) {
  10232         *            //  return th e directiv e link fun ction. (co mpile func tion not n eeded)
  10233         *            re turn funct ion(scope,  element,  attrs) {
  10234         *               var format ,  // date  format
  10235         *                   stopTi me; // so  that we ca n cancel t he time up dates
  10236         *
  10237         *               // used to  update th e UI
  10238         *               function u pdateTime( ) {
  10239         *                 element. text(dateF ilter(new  Date(), fo rmat));
  10240         *               }
  10241         *
  10242         *               // watch t he express ion, and u pdate the  UI on chan ge.
  10243         *               scope.$wat ch(attrs.m yCurrentTi me, functi on(value)  {
  10244         *                 format =  value;
  10245         *                 updateTi me();
  10246         *               });
  10247         *
  10248         *               stopTime =  $interval (updateTim e, 1000);
  10249         *
  10250         *               // listen  on DOM des troy (remo val) event , and canc el the nex t UI updat e
  10251         *               // to prev ent updati ng time af ter the DO M element  was remove d.
  10252         *               element.on ('$destroy ', functio n() {
  10253         *                 $interva l.cancel(s topTime);
  10254         *               });
  10255         *            }
  10256         *          }]);
  10257         *    </script>
  10258         *
  10259         *    <div>
  10260         *      <div ng- controller ="ExampleC ontroller" >
  10261         *        Date f ormat: <in put ng-mod el="format "> <hr/>
  10262         *        Curren t time is:  <span my- current-ti me="format "></span>
  10263         *        <hr/>
  10264         *        Blood  1 : <font  color='red '>{{blood_ 1}}</font>
  10265         *        Blood  2 : <font  color='red '>{{blood_ 2}}</font>
  10266         *        <butto n type="bu tton" data -ng-click= "fight()"> Fight</but ton>
  10267         *        <butto n type="bu tton" data -ng-click= "stopFight ()">StopFi ght</butto n>
  10268         *        <butto n type="bu tton" data -ng-click= "resetFigh t()">reset Fight</but ton>
  10269         *      </div>
  10270         *    </div>
  10271         *
  10272         * </ file>
  10273         * </ example>
  10274         */
  10275       functi on interva l(fn, dela y, count,  invokeAppl y) {
  10276         var  setInterva l = $windo w.setInter val,
  10277              clearInter val = $win dow.clearI nterval,
  10278              iteration  = 0,
  10279              skipApply  = (isDefin ed(invokeA pply) && ! invokeAppl y),
  10280              deferred =  (skipAppl y ? $$q :  $q).defer( ),
  10281              promise =  deferred.p romise;
  10282  
  10283         coun t = isDefi ned(count)  ? count :  0;
  10284  
  10285         prom ise.then(n ull, null,  fn);
  10286  
  10287         prom ise.$$inte rvalId = s etInterval (function  tick() {
  10288           de ferred.not ify(iterat ion++);
  10289  
  10290           if  (count >  0 && itera tion >= co unt) {
  10291              deferred.r esolve(ite ration);
  10292              clearInter val(promis e.$$interv alId);
  10293              delete int ervals[pro mise.$$int ervalId];
  10294           }
  10295  
  10296           if  (!skipApp ly) $rootS cope.$appl y();
  10297  
  10298         }, d elay);
  10299  
  10300         inte rvals[prom ise.$$inte rvalId] =  deferred;
  10301  
  10302         retu rn promise ;
  10303       }
  10304  
  10305  
  10306        /**
  10307         * @n gdoc metho d
  10308         * @n ame $inter val#cancel
  10309         *
  10310         * @d escription
  10311         * Ca ncels a ta sk associa ted with t he `promis e`.
  10312         *
  10313         * @p aram {prom ise} promi se returne d by the ` $interval`  function.
  10314         * @r eturns {bo olean} Ret urns `true ` if the t ask was su ccessfully  canceled.
  10315         */
  10316       interv al.cancel  = function (promise)  {
  10317         if ( promise &&  promise.$ $intervalI d in inter vals) {
  10318           in tervals[pr omise.$$in tervalId]. reject('ca nceled');
  10319           $w indow.clea rInterval( promise.$$ intervalId );
  10320           de lete inter vals[promi se.$$inter valId];
  10321           re turn true;
  10322         }
  10323         retu rn false;
  10324       };
  10325  
  10326       return  interval;
  10327     }];
  10328   }
  10329  
  10330   /**
  10331    * @ngdoc  service
  10332    * @name $ locale
  10333    *
  10334    * @descri ption
  10335    * $locale  service p rovides lo calization  rules for  various A ngular com ponents. A s of right  now the
  10336    * only pu blic api i s:
  10337    *
  10338    * * `id`  – `{stri ng}` â€“ l ocale id f ormatted a s `languag eId-countr yId` (e.g.  `en-us`)
  10339    */
  10340   function $ LocaleProv ider() {
  10341     this.$ge t = functi on() {
  10342       return  {
  10343         id:  'en-us',
  10344  
  10345         NUMB ER_FORMATS : {
  10346           DE CIMAL_SEP:  '.',
  10347           GR OUP_SEP: ' ,',
  10348           PA TTERNS: [
  10349              { // Decim al Pattern
  10350                minInt:  1,
  10351                minFrac:  0,
  10352                maxFrac:  3,
  10353                posPre:  '',
  10354                posSuf:  '',
  10355                negPre:  '-',
  10356                negSuf:  '',
  10357                gSize: 3 ,
  10358                lgSize:  3
  10359              },{ //Curr ency Patte rn
  10360                minInt:  1,
  10361                minFrac:  2,
  10362                maxFrac:  2,
  10363                posPre:  '\u00A4',
  10364                posSuf:  '',
  10365                negPre:  '(\u00A4',
  10366                negSuf:  ')',
  10367                gSize: 3 ,
  10368                lgSize:  3
  10369              }
  10370           ],
  10371           CU RRENCY_SYM : '$'
  10372         },
  10373  
  10374         DATE TIME_FORMA TS: {
  10375           MO NTH:
  10376                'January ,February, March,Apri l,May,June ,July,Augu st,Septemb er,October ,November, December'
  10377                .split(' ,'),
  10378           SH ORTMONTH:   'Jan,Feb, Mar,Apr,Ma y,Jun,Jul, Aug,Sep,Oc t,Nov,Dec' .split(',' ),
  10379           DA Y: 'Sunday ,Monday,Tu esday,Wedn esday,Thur sday,Frida y,Saturday '.split(', '),
  10380           SH ORTDAY: 'S un,Mon,Tue ,Wed,Thu,F ri,Sat'.sp lit(','),
  10381           AM PMS: ['AM' ,'PM'],
  10382           me dium: 'MMM  d, y h:mm :ss a',
  10383           's hort': 'M/ d/yy h:mm  a',
  10384           fu llDate: 'E EEE, MMMM  d, y',
  10385           lo ngDate: 'M MMM d, y',
  10386           me diumDate:  'MMM d, y' ,
  10387           sh ortDate: ' M/d/yy',
  10388           me diumTime:  'h:mm:ss a ',
  10389           sh ortTime: ' h:mm a'
  10390         },
  10391  
  10392         plur alCat: fun ction(num)  {
  10393           if  (num ===  1) {
  10394              return 'on e';
  10395           }
  10396           re turn 'othe r';
  10397         }
  10398       };
  10399     };
  10400   }
  10401  
  10402   var PATH_M ATCH = /^( [^\?#]*)(\ ?([^#]*))? (#(.*))?$/ ,
  10403       DEFAUL T_PORTS =  {'http': 8 0, 'https' : 443, 'ft p': 21};
  10404   var $locat ionMinErr  = minErr(' $location' );
  10405  
  10406  
  10407   /**
  10408    * Encode  path using  encodeUri Segment, i gnoring fo rward slas hes
  10409    *
  10410    * @param  {string} p ath Path t o encode
  10411    * @return s {string}
  10412    */
  10413   function e ncodePath( path) {
  10414     var segm ents = pat h.split('/ '),
  10415         i =  segments.l ength;
  10416  
  10417     while (i --) {
  10418       segmen ts[i] = en codeUriSeg ment(segme nts[i]);
  10419     }
  10420  
  10421     return s egments.jo in('/');
  10422   }
  10423  
  10424   function p arseAbsolu teUrl(abso luteUrl, l ocationObj ) {
  10425     var pars edUrl = ur lResolve(a bsoluteUrl );
  10426  
  10427     location Obj.$$prot ocol = par sedUrl.pro tocol;
  10428     location Obj.$$host  = parsedU rl.hostnam e;
  10429     location Obj.$$port  = int(par sedUrl.por t) || DEFA ULT_PORTS[ parsedUrl. protocol]  || null;
  10430   }
  10431  
  10432  
  10433   function p arseAppUrl (relativeU rl, locati onObj) {
  10434     var pref ixed = (re lativeUrl. charAt(0)  !== '/');
  10435     if (pref ixed) {
  10436       relati veUrl = '/ ' + relati veUrl;
  10437     }
  10438     var matc h = urlRes olve(relat iveUrl);
  10439     location Obj.$$path  = decodeU RIComponen t(prefixed  && match. pathname.c harAt(0) = == '/' ?
  10440         matc h.pathname .substring (1) : matc h.pathname );
  10441     location Obj.$$sear ch = parse KeyValue(m atch.searc h);
  10442     location Obj.$$hash  = decodeU RIComponen t(match.ha sh);
  10443  
  10444     // make  sure path  starts wit h '/';
  10445     if (loca tionObj.$$ path && lo cationObj. $$path.cha rAt(0) !=  '/') {
  10446       locati onObj.$$pa th = '/' +  locationO bj.$$path;
  10447     }
  10448   }
  10449  
  10450  
  10451   /**
  10452    *
  10453    * @param  {string} b egin
  10454    * @param  {string} w hole
  10455    * @return s {string}  returns t ext from w hole after  begin or  undefined  if it does  not begin  with
  10456    *                     expected  string.
  10457    */
  10458   function b eginsWith( begin, who le) {
  10459     if (whol e.indexOf( begin) ===  0) {
  10460       return  whole.sub str(begin. length);
  10461     }
  10462   }
  10463  
  10464  
  10465   function s tripHash(u rl) {
  10466     var inde x = url.in dexOf('#') ;
  10467     return i ndex == -1  ? url : u rl.substr( 0, index);
  10468   }
  10469  
  10470  
  10471   function s tripFile(u rl) {
  10472     return u rl.substr( 0, stripHa sh(url).la stIndexOf( '/') + 1);
  10473   }
  10474  
  10475   /* return  the server  only (sch eme://host :port) */
  10476   function s erverBase( url) {
  10477     return u rl.substri ng(0, url. indexOf('/ ', url.ind exOf('//')  + 2));
  10478   }
  10479  
  10480  
  10481   /**
  10482    * Locatio nHtml5Url  represents  an url
  10483    * This ob ject is ex posed as $ location s ervice whe n HTML5 mo de is enab led and su pported
  10484    *
  10485    * @constr uctor
  10486    * @param  {string} a ppBase app lication b ase URL
  10487    * @param  {string} b asePrefix  url path p refix
  10488    */
  10489   function L ocationHtm l5Url(appB ase, baseP refix) {
  10490     this.$$h tml5 = tru e;
  10491     basePref ix = baseP refix || ' ';
  10492     var appB aseNoFile  = stripFil e(appBase) ;
  10493     parseAbs oluteUrl(a ppBase, th is);
  10494  
  10495  
  10496     /**
  10497      * Parse  given htm l5 (regula r) url str ing into p roperties
  10498      * @para m {string}  url HTML5  url
  10499      * @priv ate
  10500      */
  10501     this.$$p arse = fun ction(url)  {
  10502       var pa thUrl = be ginsWith(a ppBaseNoFi le, url);
  10503       if (!i sString(pa thUrl)) {
  10504         thro w $locatio nMinErr('i pthprfx',  'Invalid u rl "{0}",  missing pa th prefix  "{1}".', u rl,
  10505              appBaseNoF ile);
  10506       }
  10507  
  10508       parseA ppUrl(path Url, this) ;
  10509  
  10510       if (!t his.$$path ) {
  10511         this .$$path =  '/';
  10512       }
  10513  
  10514       this.$ $compose() ;
  10515     };
  10516  
  10517     /**
  10518      * Compo se url and  update `a bsUrl` pro perty
  10519      * @priv ate
  10520      */
  10521     this.$$c ompose = f unction()  {
  10522       var se arch = toK eyValue(th is.$$searc h),
  10523           ha sh = this. $$hash ? ' #' + encod eUriSegmen t(this.$$h ash) : '';
  10524  
  10525       this.$ $url = enc odePath(th is.$$path)  + (search  ? '?' + s earch : '' ) + hash;
  10526       this.$ $absUrl =  appBaseNoF ile + this .$$url.sub str(1); //  first cha r is alway s '/'
  10527     };
  10528  
  10529     this.$$p arseLinkUr l = functi on(url, re lHref) {
  10530       if (re lHref && r elHref[0]  === '#') {
  10531         // s pecial cas e for link s to hash  fragments:
  10532         // k eep the ol d url and  only repla ce the has h fragment
  10533         this .hash(relH ref.slice( 1));
  10534         retu rn true;
  10535       }
  10536       var ap pUrl, prev AppUrl;
  10537       var re writtenUrl ;
  10538  
  10539       if ((a ppUrl = be ginsWith(a ppBase, ur l)) !== un defined) {
  10540         prev AppUrl = a ppUrl;
  10541         if ( (appUrl =  beginsWith (basePrefi x, appUrl) ) !== unde fined) {
  10542           re writtenUrl  = appBase NoFile + ( beginsWith ('/', appU rl) || app Url);
  10543         } el se {
  10544           re writtenUrl  = appBase  + prevApp Url;
  10545         }
  10546       } else  if ((appU rl = begin sWith(appB aseNoFile,  url)) !==  undefined ) {
  10547         rewr ittenUrl =  appBaseNo File + app Url;
  10548       } else  if (appBa seNoFile = = url + '/ ') {
  10549         rewr ittenUrl =  appBaseNo File;
  10550       }
  10551       if (re writtenUrl ) {
  10552         this .$$parse(r ewrittenUr l);
  10553       }
  10554       return  !!rewritt enUrl;
  10555     };
  10556   }
  10557  
  10558  
  10559   /**
  10560    * Locatio nHashbangU rl represe nts url
  10561    * This ob ject is ex posed as $ location s ervice whe n develope r doesn't  opt into h tml5 mode.
  10562    * It also  serves as  the base  class for  html5 mode  fallback  on legacy  browsers.
  10563    *
  10564    * @constr uctor
  10565    * @param  {string} a ppBase app lication b ase URL
  10566    * @param  {string} h ashPrefix  hashbang p refix
  10567    */
  10568   function L ocationHas hbangUrl(a ppBase, ha shPrefix)  {
  10569     var appB aseNoFile  = stripFil e(appBase) ;
  10570  
  10571     parseAbs oluteUrl(a ppBase, th is);
  10572  
  10573  
  10574     /**
  10575      * Parse  given has hbang url  into prope rties
  10576      * @para m {string}  url Hashb ang url
  10577      * @priv ate
  10578      */
  10579     this.$$p arse = fun ction(url)  {
  10580       var wi thoutBaseU rl = begin sWith(appB ase, url)  || beginsW ith(appBas eNoFile, u rl);
  10581       var wi thoutHashU rl = witho utBaseUrl. charAt(0)  == '#'
  10582           ?  beginsWith (hashPrefi x, without BaseUrl)
  10583           :  (this.$$ht ml5)
  10584              ? withoutB aseUrl
  10585              : '';
  10586  
  10587       if (!i sString(wi thoutHashU rl)) {
  10588         thro w $locatio nMinErr('i hshprfx',  'Invalid u rl "{0}",  missing ha sh prefix  "{1}".', u rl,
  10589              hashPrefix );
  10590       }
  10591       parseA ppUrl(with outHashUrl , this);
  10592  
  10593       this.$ $path = re moveWindow sDriveName (this.$$pa th, withou tHashUrl,  appBase);
  10594  
  10595       this.$ $compose() ;
  10596  
  10597       /*
  10598        * In  Windows, o n an ancho r node on  documents  loaded fro m
  10599        * the  filesyste m, the bro wser will  return a p athname
  10600        * pre fixed with  the drive  name ('/C :/path') w hen a
  10601        * pat hname with out a driv e is set:
  10602        *  *  a.setAttri bute('href ', '/foo')
  10603        *   *  a.pathnam e === '/C: /foo' //tr ue
  10604        *
  10605        * Ins ide of Ang ular, we'r e always u sing pathn ames that
  10606        * do  not includ e drive na mes for ro uting.
  10607        */
  10608       functi on removeW indowsDriv eName(path , url, bas e) {
  10609         /*
  10610         Matc hes paths  for file p rotocol on  windows,
  10611         such  as /C:/fo o/bar, and  captures  only /foo/ bar.
  10612         */
  10613         var  windowsFil ePathExp =  /^\/[A-Z] :(\/.*)/;
  10614  
  10615         var  firstPathS egmentMatc h;
  10616  
  10617         //Ge t the rela tive path  from the i nput URL.
  10618         if ( url.indexO f(base) == = 0) {
  10619           ur l = url.re place(base , '');
  10620         }
  10621  
  10622         // T he input U RL intenti onally con tains a fi rst path s egment tha t ends wit h a colon.
  10623         if ( windowsFil ePathExp.e xec(url))  {
  10624           re turn path;
  10625         }
  10626  
  10627         firs tPathSegme ntMatch =  windowsFil ePathExp.e xec(path);
  10628         retu rn firstPa thSegmentM atch ? fir stPathSegm entMatch[1 ] : path;
  10629       }
  10630     };
  10631  
  10632     /**
  10633      * Compo se hashban g url and  update `ab sUrl` prop erty
  10634      * @priv ate
  10635      */
  10636     this.$$c ompose = f unction()  {
  10637       var se arch = toK eyValue(th is.$$searc h),
  10638           ha sh = this. $$hash ? ' #' + encod eUriSegmen t(this.$$h ash) : '';
  10639  
  10640       this.$ $url = enc odePath(th is.$$path)  + (search  ? '?' + s earch : '' ) + hash;
  10641       this.$ $absUrl =  appBase +  (this.$$ur l ? hashPr efix + thi s.$$url :  '');
  10642     };
  10643  
  10644     this.$$p arseLinkUr l = functi on(url, re lHref) {
  10645       if (st ripHash(ap pBase) ==  stripHash( url)) {
  10646         this .$$parse(u rl);
  10647         retu rn true;
  10648       }
  10649       return  false;
  10650     };
  10651   }
  10652  
  10653  
  10654   /**
  10655    * Locatio nHashbangU rl represe nts url
  10656    * This ob ject is ex posed as $ location s ervice whe n html5 hi story api  is enabled  but the b rowser
  10657    * does no t support  it.
  10658    *
  10659    * @constr uctor
  10660    * @param  {string} a ppBase app lication b ase URL
  10661    * @param  {string} h ashPrefix  hashbang p refix
  10662    */
  10663   function L ocationHas hbangInHtm l5Url(appB ase, hashP refix) {
  10664     this.$$h tml5 = tru e;
  10665     Location HashbangUr l.apply(th is, argume nts);
  10666  
  10667     var appB aseNoFile  = stripFil e(appBase) ;
  10668  
  10669     this.$$p arseLinkUr l = functi on(url, re lHref) {
  10670       if (re lHref && r elHref[0]  === '#') {
  10671         // s pecial cas e for link s to hash  fragments:
  10672         // k eep the ol d url and  only repla ce the has h fragment
  10673         this .hash(relH ref.slice( 1));
  10674         retu rn true;
  10675       }
  10676  
  10677       var re writtenUrl ;
  10678       var ap pUrl;
  10679  
  10680       if (ap pBase == s tripHash(u rl)) {
  10681         rewr ittenUrl =  url;
  10682       } else  if ((appU rl = begin sWith(appB aseNoFile,  url))) {
  10683         rewr ittenUrl =  appBase +  hashPrefi x + appUrl ;
  10684       } else  if (appBa seNoFile = == url + ' /') {
  10685         rewr ittenUrl =  appBaseNo File;
  10686       }
  10687       if (re writtenUrl ) {
  10688         this .$$parse(r ewrittenUr l);
  10689       }
  10690       return  !!rewritt enUrl;
  10691     };
  10692  
  10693     this.$$c ompose = f unction()  {
  10694       var se arch = toK eyValue(th is.$$searc h),
  10695           ha sh = this. $$hash ? ' #' + encod eUriSegmen t(this.$$h ash) : '';
  10696  
  10697       this.$ $url = enc odePath(th is.$$path)  + (search  ? '?' + s earch : '' ) + hash;
  10698       // inc lude hashP refix in $ $absUrl wh en $$url i s empty so  IE8 & 9 d o not relo ad page be cause of r emoval of  '#'
  10699       this.$ $absUrl =  appBase +  hashPrefix  + this.$$ url;
  10700     };
  10701  
  10702   }
  10703  
  10704  
  10705   var locati onPrototyp e = {
  10706  
  10707     /**
  10708      * Are w e in html5  mode?
  10709      * @priv ate
  10710      */
  10711     $$html5:  false,
  10712  
  10713     /**
  10714      * Has a ny change  been repla cing?
  10715      * @priv ate
  10716      */
  10717     $$replac e: false,
  10718  
  10719     /**
  10720      * @ngdo c method
  10721      * @name  $location #absUrl
  10722      *
  10723      * @desc ription
  10724      * This  method is  getter onl y.
  10725      *
  10726      * Retur n full url  represent ation with  all segme nts encode d accordin g to rules  specified  in
  10727      * [RFC  3986](http ://www.iet f.org/rfc/ rfc3986.tx t).
  10728      *
  10729      *
  10730      * ```js
  10731      * // gi ven url ht tp://examp le.com/#/s ome/path?f oo=bar&baz =xoxo
  10732      * var a bsUrl = $l ocation.ab sUrl();
  10733      * // =>  "http://e xample.com /#/some/pa th?foo=bar &baz=xoxo"
  10734      * ```
  10735      *
  10736      * @retu rn {string } full url
  10737      */
  10738     absUrl:  locationGe tter('$$ab sUrl'),
  10739  
  10740     /**
  10741      * @ngdo c method
  10742      * @name  $location #url
  10743      *
  10744      * @desc ription
  10745      * This  method is  getter / s etter.
  10746      *
  10747      * Retur n url (e.g . `/path?a =b#hash`)  when calle d without  any parame ter.
  10748      *
  10749      * Chang e path, se arch and h ash, when  called wit h paramete r and retu rn `$locat ion`.
  10750      *
  10751      *
  10752      * ```js
  10753      * // gi ven url ht tp://examp le.com/#/s ome/path?f oo=bar&baz =xoxo
  10754      * var u rl = $loca tion.url() ;
  10755      * // =>  "/some/pa th?foo=bar &baz=xoxo"
  10756      * ```
  10757      *
  10758      * @para m {string= } url New  url withou t base pre fix (e.g.  `/path?a=b #hash`)
  10759      * @retu rn {string } url
  10760      */
  10761     url: fun ction(url)  {
  10762       if (is Undefined( url))
  10763         retu rn this.$$ url;
  10764  
  10765       var ma tch = PATH _MATCH.exe c(url);
  10766       if (ma tch[1] ||  url === '' ) this.pat h(decodeUR IComponent (match[1]) );
  10767       if (ma tch[2] ||  match[1] | | url ===  '') this.s earch(matc h[3] || '' );
  10768       this.h ash(match[ 5] || '');
  10769  
  10770       return  this;
  10771     },
  10772  
  10773     /**
  10774      * @ngdo c method
  10775      * @name  $location #protocol
  10776      *
  10777      * @desc ription
  10778      * This  method is  getter onl y.
  10779      *
  10780      * Retur n protocol  of curren t url.
  10781      *
  10782      *
  10783      * ```js
  10784      * // gi ven url ht tp://examp le.com/#/s ome/path?f oo=bar&baz =xoxo
  10785      * var p rotocol =  $location. protocol() ;
  10786      * // =>  "http"
  10787      * ```
  10788      *
  10789      * @retu rn {string } protocol  of curren t url
  10790      */
  10791     protocol : location Getter('$$ protocol') ,
  10792  
  10793     /**
  10794      * @ngdo c method
  10795      * @name  $location #host
  10796      *
  10797      * @desc ription
  10798      * This  method is  getter onl y.
  10799      *
  10800      * Retur n host of  current ur l.
  10801      *
  10802      *
  10803      * ```js
  10804      * // gi ven url ht tp://examp le.com/#/s ome/path?f oo=bar&baz =xoxo
  10805      * var h ost = $loc ation.host ();
  10806      * // =>  "example. com"
  10807      * ```
  10808      *
  10809      * @retu rn {string } host of  current ur l.
  10810      */
  10811     host: lo cationGett er('$$host '),
  10812  
  10813     /**
  10814      * @ngdo c method
  10815      * @name  $location #port
  10816      *
  10817      * @desc ription
  10818      * This  method is  getter onl y.
  10819      *
  10820      * Retur n port of  current ur l.
  10821      *
  10822      *
  10823      * ```js
  10824      * // gi ven url ht tp://examp le.com/#/s ome/path?f oo=bar&baz =xoxo
  10825      * var p ort = $loc ation.port ();
  10826      * // =>  80
  10827      * ```
  10828      *
  10829      * @retu rn {Number } port
  10830      */
  10831     port: lo cationGett er('$$port '),
  10832  
  10833     /**
  10834      * @ngdo c method
  10835      * @name  $location #path
  10836      *
  10837      * @desc ription
  10838      * This  method is  getter / s etter.
  10839      *
  10840      * Retur n path of  current ur l when cal led withou t any para meter.
  10841      *
  10842      * Chang e path whe n called w ith parame ter and re turn `$loc ation`.
  10843      *
  10844      * Note:  Path shou ld always  begin with  forward s lash (/),  this metho d will add  the forwa rd slash
  10845      * if it  is missin g.
  10846      *
  10847      *
  10848      * ```js
  10849      * // gi ven url ht tp://examp le.com/#/s ome/path?f oo=bar&baz =xoxo
  10850      * var p ath = $loc ation.path ();
  10851      * // =>  "/some/pa th"
  10852      * ```
  10853      *
  10854      * @para m {(string |number)=}  path New  path
  10855      * @retu rn {string } path
  10856      */
  10857     path: lo cationGett erSetter(' $$path', f unction(pa th) {
  10858       path =  path !==  null ? pat h.toString () : '';
  10859       return  path.char At(0) == ' /' ? path  : '/' + pa th;
  10860     }),
  10861  
  10862     /**
  10863      * @ngdo c method
  10864      * @name  $location #search
  10865      *
  10866      * @desc ription
  10867      * This  method is  getter / s etter.
  10868      *
  10869      * Retur n search p art (as ob ject) of c urrent url  when call ed without  any param eter.
  10870      *
  10871      * Chang e search p art when c alled with  parameter  and retur n `$locati on`.
  10872      *
  10873      *
  10874      * ```js
  10875      * // gi ven url ht tp://examp le.com/#/s ome/path?f oo=bar&baz =xoxo
  10876      * var s earchObjec t = $locat ion.search ();
  10877      * // =>  {foo: 'ba r', baz: ' xoxo'}
  10878      *
  10879      * // se t foo to ' yipee'
  10880      * $loca tion.searc h('foo', ' yipee');
  10881      * // $l ocation.se arch() =>  {foo: 'yip ee', baz:  'xoxo'}
  10882      * ```
  10883      *
  10884      * @para m {string| Object.<st ring>|Obje ct.<Array. <string>>}  search Ne w search p arams - st ring or
  10885      * hash  object.
  10886      *
  10887      * When  called wit h a single  argument  the method  acts as a  setter, s etting the  `search`  component
  10888      * of `$ location`  to the spe cified val ue.
  10889      *
  10890      * If th e argument  is a hash  object co ntaining a n array of  values, t hese value s will be  encoded
  10891      * as du plicate se arch param eters in t he url.
  10892      *
  10893      * @para m {(string |Number|Ar ray<string >|boolean) =} paramVa lue If `se arch` is a  string or  number, t hen `param Value`
  10894      * will  override o nly a sing le search  property.
  10895      *
  10896      * If `p aramValue`  is an arr ay, it wil l override  the prope rty of the  `search`  component  of
  10897      * `$loc ation` spe cified via  the first  argument.
  10898      *
  10899      * If `p aramValue`  is `null` , the prop erty speci fied via t he first a rgument wi ll be dele ted.
  10900      *
  10901      * If `p aramValue`  is `true` , the prop erty speci fied via t he first a rgument wi ll be adde d with no
  10902      * value  nor trail ing equal  sign.
  10903      *
  10904      * @retu rn {Object } If calle d with no  arguments  returns th e parsed ` search` ob ject. If c alled with
  10905      * one o r more arg uments ret urns `$loc ation` obj ect itself .
  10906      */
  10907     search:  function(s earch, par amValue) {
  10908       switch  (argument s.length)  {
  10909         case  0:
  10910           re turn this. $$search;
  10911         case  1:
  10912           if  (isString (search) | | isNumber (search))  {
  10913              search = s earch.toSt ring();
  10914              this.$$sea rch = pars eKeyValue( search);
  10915           }  else if (i sObject(se arch)) {
  10916              search = c opy(search , {});
  10917              // remove  object und efined or  null prope rties
  10918              forEach(se arch, func tion(value , key) {
  10919                if (valu e == null)  delete se arch[key];
  10920              });
  10921  
  10922              this.$$sea rch = sear ch;
  10923           }  else {
  10924              throw $loc ationMinEr r('isrchar g',
  10925                  'The f irst argum ent of the  `$locatio n#search() ` call mus t be a str ing or an  object.');
  10926           }
  10927           br eak;
  10928         defa ult:
  10929           if  (isUndefi ned(paramV alue) || p aramValue  === null)  {
  10930              delete thi s.$$search [search];
  10931           }  else {
  10932              this.$$sea rch[search ] = paramV alue;
  10933           }
  10934       }
  10935  
  10936       this.$ $compose() ;
  10937       return  this;
  10938     },
  10939  
  10940     /**
  10941      * @ngdo c method
  10942      * @name  $location #hash
  10943      *
  10944      * @desc ription
  10945      * This  method is  getter / s etter.
  10946      *
  10947      * Retur n hash fra gment when  called wi thout any  parameter.
  10948      *
  10949      * Chang e hash fra gment when  called wi th paramet er and ret urn `$loca tion`.
  10950      *
  10951      *
  10952      * ```js
  10953      * // gi ven url ht tp://examp le.com/som e/path?foo =bar&baz=x oxo#hashVa lue
  10954      * var h ash = $loc ation.hash ();
  10955      * // =>  "hashValu e"
  10956      * ```
  10957      *
  10958      * @para m {(string |number)=}  hash New  hash fragm ent
  10959      * @retu rn {string } hash
  10960      */
  10961     hash: lo cationGett erSetter(' $$hash', f unction(ha sh) {
  10962       return  hash !==  null ? has h.toString () : '';
  10963     }),
  10964  
  10965     /**
  10966      * @ngdo c method
  10967      * @name  $location #replace
  10968      *
  10969      * @desc ription
  10970      * If ca lled, all  changes to  $location  during cu rrent `$di gest` will  be replac ing curren t history
  10971      * recor d, instead  of adding  new one.
  10972      */
  10973     replace:  function( ) {
  10974       this.$ $replace =  true;
  10975       return  this;
  10976     }
  10977   };
  10978  
  10979   forEach([L ocationHas hbangInHtm l5Url, Loc ationHashb angUrl, Lo cationHtml 5Url], fun ction(Loca tion) {
  10980     Location .prototype  = Object. create(loc ationProto type);
  10981  
  10982     /**
  10983      * @ngdo c method
  10984      * @name  $location #state
  10985      *
  10986      * @desc ription
  10987      * This  method is  getter / s etter.
  10988      *
  10989      * Retur n the hist ory state  object whe n called w ithout any  parameter .
  10990      *
  10991      * Chang e the hist ory state  object whe n called w ith one pa rameter an d return ` $location` .
  10992      * The s tate objec t is later  passed to  `pushStat e` or `rep laceState` .
  10993      *
  10994      * NOTE:  This meth od is supp orted only  in HTML5  mode and o nly in bro wsers supp orting
  10995      * the H TML5 Histo ry API (i. e. methods  `pushStat e` and `re placeState `). If you  need to s upport
  10996      * older  browsers  (like IE9  or Android  < 4.0), d on't use t his method .
  10997      *
  10998      * @para m {object= } state St ate object  for pushS tate or re placeState
  10999      * @retu rn {object } state
  11000      */
  11001     Location .prototype .state = f unction(st ate) {
  11002       if (!a rguments.l ength)
  11003         retu rn this.$$ state;
  11004  
  11005       if (Lo cation !==  LocationH tml5Url ||  !this.$$h tml5) {
  11006         thro w $locatio nMinErr('n ostate', ' History AP I state su pport is a vailable o nly ' +
  11007           'i n HTML5 mo de and onl y in brows ers suppor ting HTML5  History A PI');
  11008       }
  11009       // The  user migh t modify ` stateObjec t` after i nvoking `$ location.s tate(state Object)`
  11010       // but  we're cha nging the  $$state re ference to  $browser. state() du ring the $ digest
  11011       // so  the modifi cation win dow is nar row.
  11012       this.$ $state = i sUndefined (state) ?  null : sta te;
  11013  
  11014       return  this;
  11015     };
  11016   });
  11017  
  11018  
  11019   function l ocationGet ter(proper ty) {
  11020     return f unction()  {
  11021       return  this[prop erty];
  11022     };
  11023   }
  11024  
  11025  
  11026   function l ocationGet terSetter( property,  preprocess ) {
  11027     return f unction(va lue) {
  11028       if (is Undefined( value))
  11029         retu rn this[pr operty];
  11030  
  11031       this[p roperty] =  preproces s(value);
  11032       this.$ $compose() ;
  11033  
  11034       return  this;
  11035     };
  11036   }
  11037  
  11038  
  11039   /**
  11040    * @ngdoc  service
  11041    * @name $ location
  11042    *
  11043    * @requir es $rootEl ement
  11044    *
  11045    * @descri ption
  11046    * The $lo cation ser vice parse s the URL  in the bro wser addre ss bar (ba sed on the
  11047    * [window .location] (https://d eveloper.m ozilla.org /en/window .location) ) and make s the URL
  11048    * availab le to your  applicati on. Change s to the U RL in the  address ba r are refl ected into
  11049    * $locati on service  and chang es to $loc ation are  reflected  into the b rowser add ress bar.
  11050    *
  11051    * **The $ location s ervice:**
  11052    *
  11053    * - Expos es the cur rent URL i n the brow ser addres s bar, so  you can
  11054    *   - Wat ch and obs erve the U RL.
  11055    *   - Cha nge the UR L.
  11056    * - Synch ronizes th e URL with  the brows er when th e user
  11057    *   - Cha nges the a ddress bar .
  11058    *   - Cli cks the ba ck or forw ard button  (or click s a Histor y link).
  11059    *   - Cli cks on a l ink.
  11060    * - Repre sents the  URL object  as a set  of methods  (protocol , host, po rt, path,  search, ha sh).
  11061    *
  11062    * For mor e informat ion see {@ link guide /$location  Developer  Guide: Us ing $locat ion}
  11063    */
  11064  
  11065   /**
  11066    * @ngdoc  provider
  11067    * @name $ locationPr ovider
  11068    * @descri ption
  11069    * Use the  `$locatio nProvider`  to config ure how th e applicat ion deep l inking pat hs are sto red.
  11070    */
  11071   function $ LocationPr ovider() {
  11072     var hash Prefix = ' ',
  11073         html 5Mode = {
  11074           en abled: fal se,
  11075           re quireBase:  true,
  11076           re writeLinks : true
  11077         };
  11078  
  11079     /**
  11080      * @ngdo c method
  11081      * @name  $location Provider#h ashPrefix
  11082      * @desc ription
  11083      * @para m {string= } prefix P refix for  hash part  (containin g path and  search)
  11084      * @retu rns {*} cu rrent valu e if used  as getter  or itself  (chaining)  if used a s setter
  11085      */
  11086     this.has hPrefix =  function(p refix) {
  11087       if (is Defined(pr efix)) {
  11088         hash Prefix = p refix;
  11089         retu rn this;
  11090       } else  {
  11091         retu rn hashPre fix;
  11092       }
  11093     };
  11094  
  11095     /**
  11096      * @ngdo c method
  11097      * @name  $location Provider#h tml5Mode
  11098      * @desc ription
  11099      * @para m {(boolea n|Object)= } mode If  boolean, s ets `html5 Mode.enabl ed` to val ue.
  11100      *   If  object, se ts `enable d`, `requi reBase` an d `rewrite Links` to  respective  values. S upported
  11101      *   pro perties:
  11102      *   - * *enabled**  â€“ `{boo lean}` â€“  (default:  false) If  true, wil l rely on  `history.p ushState`  to
  11103      *     c hange urls  where sup ported. Wi ll fall ba ck to hash -prefixed  paths in b rowsers th at do not
  11104      *     s upport `pu shState`.
  11105      *   - * *requireBa se** - `{b oolean}` -  (default:  `true`) W hen html5M ode is ena bled, spec ifies
  11106      *     w hether or  not a <bas e> tag is  required t o be prese nt. If `en abled` and  `requireB ase` are
  11107      *     t rue, and a  base tag  is not pre sent, an e rror will  be thrown  when `$loc ation` is  injected.
  11108      *     S ee the {@l ink guide/ $location  $location  guide for  more infor mation}
  11109      *   - * *rewriteLi nks** - `{ boolean}`  - (default : `true`)  When html5 Mode is en abled,
  11110      *     e nables/dis ables url  rewriting  for relati ve links.
  11111      *
  11112      * @retu rns {Objec t} html5Mo de object  if used as  getter or  itself (c haining) i f used as  setter
  11113      */
  11114     this.htm l5Mode = f unction(mo de) {
  11115       if (is Boolean(mo de)) {
  11116         html 5Mode.enab led = mode ;
  11117         retu rn this;
  11118       } else  if (isObj ect(mode))  {
  11119  
  11120         if ( isBoolean( mode.enabl ed)) {
  11121           ht ml5Mode.en abled = mo de.enabled ;
  11122         }
  11123  
  11124         if ( isBoolean( mode.requi reBase)) {
  11125           ht ml5Mode.re quireBase  = mode.req uireBase;
  11126         }
  11127  
  11128         if ( isBoolean( mode.rewri teLinks))  {
  11129           ht ml5Mode.re writeLinks  = mode.re writeLinks ;
  11130         }
  11131  
  11132         retu rn this;
  11133       } else  {
  11134         retu rn html5Mo de;
  11135       }
  11136     };
  11137  
  11138     /**
  11139      * @ngdo c event
  11140      * @name  $location #$location ChangeStar t
  11141      * @even tType broa dcast on r oot scope
  11142      * @desc ription
  11143      * Broad casted bef ore a URL  will chang e.
  11144      *
  11145      * This  change can  be preven ted by cal ling
  11146      * `prev entDefault ` method o f the even t. See {@l ink ng.$ro otScope.Sc ope#$on} f or more
  11147      * detai ls about e vent objec t. Upon su ccessful c hange
  11148      * {@lin k ng.$loca tion#$loca tionChange Success $l ocationCha ngeSuccess } is fired .
  11149      *
  11150      * The ` newState`  and `oldSt ate` param eters may  be defined  only in H TML5 mode  and when
  11151      * the b rowser sup ports the  HTML5 Hist ory API.
  11152      *
  11153      * @para m {Object}  angularEv ent Synthe tic event  object.
  11154      * @para m {string}  newUrl Ne w URL
  11155      * @para m {string= } oldUrl U RL that wa s before i t was chan ged.
  11156      * @para m {string= } newState  New histo ry state o bject
  11157      * @para m {string= } oldState  History s tate objec t that was  before it  was chang ed.
  11158      */
  11159  
  11160     /**
  11161      * @ngdo c event
  11162      * @name  $location #$location ChangeSucc ess
  11163      * @even tType broa dcast on r oot scope
  11164      * @desc ription
  11165      * Broad casted aft er a URL w as changed .
  11166      *
  11167      * The ` newState`  and `oldSt ate` param eters may  be defined  only in H TML5 mode  and when
  11168      * the b rowser sup ports the  HTML5 Hist ory API.
  11169      *
  11170      * @para m {Object}  angularEv ent Synthe tic event  object.
  11171      * @para m {string}  newUrl Ne w URL
  11172      * @para m {string= } oldUrl U RL that wa s before i t was chan ged.
  11173      * @para m {string= } newState  New histo ry state o bject
  11174      * @para m {string= } oldState  History s tate objec t that was  before it  was chang ed.
  11175      */
  11176  
  11177     this.$ge t = ['$roo tScope', ' $browser',  '$sniffer ', '$rootE lement',
  11178         func tion($root Scope, $br owser, $sn iffer, $ro otElement)  {
  11179       var $l ocation,
  11180           Lo cationMode ,
  11181           ba seHref = $ browser.ba seHref(),  // if base [href] is  undefined,  it defaul ts to ''
  11182           in itialUrl =  $browser. url(),
  11183           ap pBase;
  11184  
  11185       if (ht ml5Mode.en abled) {
  11186         if ( !baseHref  && html5Mo de.require Base) {
  11187           th row $locat ionMinErr( 'nobase',
  11188              "$location  in HTML5  mode requi res a <bas e> tag to  be present !");
  11189         }
  11190         appB ase = serv erBase(ini tialUrl) +  (baseHref  || '/');
  11191         Loca tionMode =  $sniffer. history ?  LocationHt ml5Url : L ocationHas hbangInHtm l5Url;
  11192       } else  {
  11193         appB ase = stri pHash(init ialUrl);
  11194         Loca tionMode =  LocationH ashbangUrl ;
  11195       }
  11196       $locat ion = new  LocationMo de(appBase , '#' + ha shPrefix);
  11197       $locat ion.$$pars eLinkUrl(i nitialUrl,  initialUr l);
  11198  
  11199       $locat ion.$$stat e = $brows er.state() ;
  11200  
  11201       var IG NORE_URI_R EGEXP = /^ \s*(javasc ript|mailt o):/i;
  11202  
  11203       functi on setBrow serUrlWith Fallback(u rl, replac e, state)  {
  11204         var  oldUrl = $ location.u rl();
  11205         var  oldState =  $location .$$state;
  11206         try  {
  11207           $b rowser.url (url, repl ace, state );
  11208  
  11209           //  Make sure  $location .state() r eturns ref erentially  identical  (not just  deeply eq ual)
  11210           //  state obj ect; this  makes poss ible quick  checking  if the sta te changed  in the di gest
  11211           //  loop. Che cking deep  equality  would be t oo expensi ve.
  11212           $l ocation.$$ state = $b rowser.sta te();
  11213         } ca tch (e) {
  11214           //  Restore o ld values  if pushSta te fails
  11215           $l ocation.ur l(oldUrl);
  11216           $l ocation.$$ state = ol dState;
  11217  
  11218           th row e;
  11219         }
  11220       }
  11221  
  11222       $rootE lement.on( 'click', f unction(ev ent) {
  11223         // T ODO(vojta) : rewrite  link when  opening in  new tab/w indow (in  legacy bro wser)
  11224         // c urrently w e open nic e url link  and redir ect then
  11225  
  11226         if ( !html5Mode .rewriteLi nks || eve nt.ctrlKey  || event. metaKey ||  event.whi ch == 2) r eturn;
  11227  
  11228         var  elm = jqLi te(event.t arget);
  11229  
  11230         // t raverse th e DOM up t o find fir st A tag
  11231         whil e (nodeNam e_(elm[0])  !== 'a')  {
  11232           //  ignore re writing if  no A tag  (reached r oot elemen t, or no p arent - re moved from  document)
  11233           if  (elm[0] = == $rootEl ement[0] | | !(elm =  elm.parent ())[0]) re turn;
  11234         }
  11235  
  11236         var  absHref =  elm.prop(' href');
  11237         // g et the act ual href a ttribute -  see
  11238         // h ttp://msdn .microsoft .com/en-us /library/i e/dd347148 (v=vs.85). aspx
  11239         var  relHref =  elm.attr(' href') ||  elm.attr(' xlink:href ');
  11240  
  11241         if ( isObject(a bsHref) &&  absHref.t oString()  === '[obje ct SVGAnim atedString ]') {
  11242           //  SVGAnimat edString.a nimVal sho uld be ide ntical to  SVGAnimate dString.ba seVal, unl ess during
  11243           //  an animat ion.
  11244           ab sHref = ur lResolve(a bsHref.ani mVal).href ;
  11245         }
  11246  
  11247         // I gnore when  url is st arted with  javascrip t: or mail to:
  11248         if ( IGNORE_URI _REGEXP.te st(absHref )) return;
  11249  
  11250         if ( absHref &&  !elm.attr ('target')  && !event .isDefault Prevented( )) {
  11251           if  ($locatio n.$$parseL inkUrl(abs Href, relH ref)) {
  11252              // We do a  preventDe fault for  all urls t hat are pa rt of the  angular ap plication,
  11253              // in html 5mode and  also witho ut, so tha t we are a ble to abo rt navigat ion withou t
  11254              // getting  double en tries in t he locatio n history.
  11255              event.prev entDefault ();
  11256              // update  location m anually
  11257              if ($locat ion.absUrl () != $bro wser.url() ) {
  11258                $rootSco pe.$apply( );
  11259                // hack  to work ar ound FF6 b ug 684208  when scena rio runner  clicks on  links
  11260                window.a ngular['ff -684208-pr eventDefau lt'] = tru e;
  11261              }
  11262           }
  11263         }
  11264       });
  11265  
  11266  
  11267       // rew rite hashb ang url <>  html5 url
  11268       if ($l ocation.ab sUrl() !=  initialUrl ) {
  11269         $bro wser.url($ location.a bsUrl(), t rue);
  11270       }
  11271  
  11272       var in itializing  = true;
  11273  
  11274       // upd ate $locat ion when $ browser ur l changes
  11275       $brows er.onUrlCh ange(funct ion(newUrl , newState ) {
  11276           $rootScope .$e DNS    ync(functi on() {
  11277           va r oldUrl =  $location .absUrl();
  11278           va r oldState  = $locati on.$$state ;
  11279           va r defaultP revented;
  11280  
  11281           $l ocation.$$ parse(newU rl);
  11282           $l ocation.$$ state = ne wState;
  11283  
  11284           de faultPreve nted = $ro otScope.$b roadcast(' $locationC hangeStart ', newUrl,  oldUrl,
  11285                newState , oldState ).defaultP revented;
  11286  
  11287           //  if the lo cation was  changed b y a `$loca tionChange Start` han dler then  stop
  11288           //  processin g this loc ation chan ge
  11289           if  ($locatio n.absUrl()  !== newUr l) return;
  11290  
  11291           if  (defaultP revented)  {
  11292              $location. $$parse(ol dUrl);
  11293              $location. $$state =  oldState;
  11294              setBrowser UrlWithFal lback(oldU rl, false,  oldState) ;
  11295           }  else {
  11296              initializi ng = false ;
  11297              afterLocat ionChange( oldUrl, ol dState);
  11298           }
  11299         });
  11300         if ( !$rootScop e.$$phase)  $rootScop e.$digest( );
  11301       });
  11302  
  11303       // upd ate browse r
  11304       $rootS cope.$watc h(function  $location Watch() {
  11305         var  oldUrl = $ browser.ur l();
  11306         var  oldState =  $browser. state();
  11307         var  currentRep lace = $lo cation.$$r eplace;
  11308         var  urlOrState Changed =  oldUrl !==  $location .absUrl()  ||
  11309           ($ location.$ $html5 &&  $sniffer.h istory &&  oldState ! == $locati on.$$state );
  11310  
  11311         if ( initializi ng || urlO rStateChan ged) {
  11312           in itializing  = false;
  11313  
  11314             $rootScope .$e DNS    ync(functi on() {
  11315              var newUrl  = $locati on.absUrl( );
  11316              var defaul tPrevented  = $rootSc ope.$broad cast('$loc ationChang eStart', n ewUrl, old Url,
  11317                  $locat ion.$$stat e, oldStat e).default Prevented;
  11318  
  11319              // if the  location w as changed  by a `$lo cationChan geStart` h andler the n stop
  11320              // process ing this l ocation ch ange
  11321              if ($locat ion.absUrl () !== new Url) retur n;
  11322  
  11323              if (defaul tPrevented ) {
  11324                $locatio n.$$parse( oldUrl);
  11325                $locatio n.$$state  = oldState ;
  11326              } else {
  11327                if (urlO rStateChan ged) {
  11328                  setBro wserUrlWit hFallback( newUrl, cu rrentRepla ce,
  11329                                               oldState = == $locati on.$$state  ? null :  $location. $$state);
  11330                }
  11331                afterLoc ationChang e(oldUrl,  oldState);
  11332              }
  11333           }) ;
  11334         }
  11335  
  11336         $loc ation.$$re place = fa lse;
  11337  
  11338           // we don' t need to  return any thing beca use $e DNS    ync will m ake the di gest loop  dirty when
  11339         // t here is a  change
  11340       });
  11341  
  11342       return  $location ;
  11343  
  11344       functi on afterLo cationChan ge(oldUrl,  oldState)  {
  11345         $roo tScope.$br oadcast('$ locationCh angeSucces s', $locat ion.absUrl (), oldUrl ,
  11346           $l ocation.$$ state, old State);
  11347       }
  11348   }];
  11349   }
  11350  
  11351   /**
  11352    * @ngdoc  service
  11353    * @name $ log
  11354    * @requir es $window
  11355    *
  11356    * @descri ption
  11357    * Simple  service fo r logging.  Default i mplementat ion safely  writes th e message
  11358    * into th e browser' s console  (if presen t).
  11359    *
  11360    * The mai n purpose  of this se rvice is t o simplify  debugging  and troub leshooting .
  11361    *
  11362    * The def ault is to  log `debu g` message s. You can  use
  11363    * {@link  ng.$logPro vider ng.$ logProvide r#debugEna bled} to c hange this .
  11364    *
  11365    * @exampl e
  11366      <exampl e module=" logExample ">
  11367        <file  name="scr ipt.js">
  11368          ang ular.modul e('logExam ple', [])
  11369            . controller ('LogContr oller', [' $scope', ' $log', fun ction($sco pe, $log)  {
  11370               $scope.$l og = $log;
  11371               $scope.me ssage = 'H ello World !';
  11372            } ]);
  11373        </fil e>
  11374        <file  name="ind ex.html">
  11375          <di v ng-contr oller="Log Controller ">
  11376            < p>Reload t his page w ith open c onsole, en ter text a nd hit the  log butto n...</p>
  11377            M essage:
  11378            < input type ="text" ng -model="me ssage"/>
  11379            < button ng- click="$lo g.log(mess age)">log< /button>
  11380            < button ng- click="$lo g.warn(mes sage)">war n</button>
  11381            < button ng- click="$lo g.info(mes sage)">inf o</button>
  11382            < button ng- click="$lo g.error(me ssage)">er ror</butto n>
  11383          </d iv>
  11384        </fil e>
  11385      </examp le>
  11386    */
  11387  
  11388   /**
  11389    * @ngdoc  provider
  11390    * @name $ logProvide r
  11391    * @descri ption
  11392    * Use the  `$logProv ider` to c onfigure h ow the app lication l ogs messag es
  11393    */
  11394   function $ LogProvide r() {
  11395     var debu g = true,
  11396         self  = this;
  11397  
  11398     /**
  11399      * @ngdo c method
  11400      * @name  $logProvi der#debugE nabled
  11401      * @desc ription
  11402      * @para m {boolean =} flag en able or di sable debu g level me ssages
  11403      * @retu rns {*} cu rrent valu e if used  as getter  or itself  (chaining)  if used a s setter
  11404      */
  11405     this.deb ugEnabled  = function (flag) {
  11406       if (is Defined(fl ag)) {
  11407         debu g = flag;
  11408       return  this;
  11409       } else  {
  11410         retu rn debug;
  11411       }
  11412     };
  11413  
  11414     this.$ge t = ['$win dow', func tion($wind ow) {
  11415       return  {
  11416         /**
  11417          * @ ngdoc meth od
  11418          * @ name $log# log
  11419          *
  11420          * @ descriptio n
  11421          * W rite a log  message
  11422          */
  11423         log:  consoleLo g('log'),
  11424  
  11425         /**
  11426          * @ ngdoc meth od
  11427          * @ name $log# info
  11428          *
  11429          * @ descriptio n
  11430          * W rite an in formation  message
  11431          */
  11432         info : consoleL og('info') ,
  11433  
  11434         /**
  11435          * @ ngdoc meth od
  11436          * @ name $log# warn
  11437          *
  11438          * @ descriptio n
  11439          * W rite a war ning messa ge
  11440          */
  11441         warn : consoleL og('warn') ,
  11442  
  11443         /**
  11444          * @ ngdoc meth od
  11445          * @ name $log# error
  11446          *
  11447          * @ descriptio n
  11448          * W rite an er ror messag e
  11449          */
  11450         erro r: console Log('error '),
  11451  
  11452         /**
  11453          * @ ngdoc meth od
  11454          * @ name $log# debug
  11455          *
  11456          * @ descriptio n
  11457          * W rite a deb ug message
  11458          */
  11459         debu g: (functi on() {
  11460           va r fn = con soleLog('d ebug');
  11461  
  11462           re turn funct ion() {
  11463              if (debug)  {
  11464                fn.apply (self, arg uments);
  11465              }
  11466           };
  11467         }())
  11468       };
  11469  
  11470       functi on formatE rror(arg)  {
  11471         if ( arg instan ceof Error ) {
  11472           if  (arg.stac k) {
  11473              arg = (arg .message & & arg.stac k.indexOf( arg.messag e) === -1)
  11474                  ? 'Err or: ' + ar g.message  + '\n' + a rg.stack
  11475                  : arg. stack;
  11476           }  else if (a rg.sourceU RL) {
  11477              arg = arg. message +  '\n' + arg .sourceURL  + ':' + a rg.line;
  11478           }
  11479         }
  11480         retu rn arg;
  11481       }
  11482  
  11483       functi on console Log(type)  {
  11484         var  console =  $window.co nsole || { },
  11485              logFn = co nsole[type ] || conso le.log ||  noop,
  11486              hasApply =  false;
  11487  
  11488         // N ote: readi ng logFn.a pply throw s an error  in IE11 i n IE8 docu ment mode.
  11489         // T he reason  behind thi s is that  console.lo g has type  "object"  in IE8...
  11490         try  {
  11491           ha sApply = ! !logFn.app ly;
  11492         } ca tch (e) {}
  11493  
  11494         if ( hasApply)  {
  11495           re turn funct ion() {
  11496              var args =  [];
  11497              forEach(ar guments, f unction(ar g) {
  11498                args.pus h(formatEr ror(arg));
  11499              });
  11500              return log Fn.apply(c onsole, ar gs);
  11501           };
  11502         }
  11503  
  11504         // w e are IE w hich eithe r doesn't  have windo w.console  => this is  noop and  we do noth ing,
  11505         // o r we are I E where co nsole.log  doesn't ha ve apply s o we log a t least fi rst 2 args
  11506         retu rn functio n(arg1, ar g2) {
  11507           lo gFn(arg1,  arg2 == nu ll ? '' :  arg2);
  11508         };
  11509       }
  11510     }];
  11511   }
  11512  
  11513   var $parse MinErr = m inErr('$pa rse');
  11514  
  11515   // Sandbox ing Angula r Expressi ons
  11516   // ------- ---------- ---------- ---
  11517   // Angular  expressio ns are gen erally con sidered sa fe because  these exp ressions o nly have d irect
  11518   // access  to `$scope ` and loca ls. Howeve r, one can  obtain th e ability  to execute  arbitrary  JS code b y
  11519   // obtaini ng a refer ence to na tive JS fu nctions su ch as the  Function c onstructor .
  11520   //
  11521   // As an e xample, co nsider the  following  Angular e xpression:
  11522   //
  11523   //   {}.to String.con structor(' alert("evi l JS code" )')
  11524   //
  11525   // This sa ndboxing t echnique i s not perf ect and do esn't aim  to be. The  goal is t o prevent  exploits
  11526   // against  the expre ssion lang uage, but  not to pre vent explo its that w ere enable d by expos ing
  11527   // sensiti ve JavaScr ipt or bro wser APIs  on Scope.  Exposing s uch object s on a Sco pe is neve r a good
  11528   // practic e and ther efore we a re not eve n trying t o protect  against in teraction  with an ob ject
  11529   // explici tly expose d in this  way.
  11530   //
  11531   // In gene ral, it is  not possi ble to acc ess a Wind ow object  from an an gular expr ession unl ess a
  11532   // window  or some DO M object t hat has a  reference  to window  is publish ed onto a  Scope.
  11533   // Similar ly we prev ent invoca tions of f unction kn own to be  dangerous,  as well a s assignme nts to
  11534   // native  objects.
  11535   //
  11536   // See htt ps://docs. angularjs. org/guide/ security
  11537  
  11538  
  11539   function e nsureSafeM emberName( name, full Expression ) {
  11540     if (name  === "__de fineGetter __" || nam e === "__d efineSette r__"
  11541         || n ame === "_ _lookupGet ter__" ||  name === " __lookupSe tter__"
  11542         || n ame === "_ _proto__")  {
  11543       throw  $parseMinE rr('isecfl d',
  11544           'A ttempting  to access  a disallow ed field i n Angular  expression s! '
  11545           +  'Expressio n: {0}', f ullExpress ion);
  11546     }
  11547     return n ame;
  11548   }
  11549  
  11550   function e nsureSafeO bject(obj,  fullExpre ssion) {
  11551     // nifty  check if  obj is Fun ction that  is fast a nd works a cross ifra mes and ot her contex ts
  11552     if (obj)  {
  11553       if (ob j.construc tor === ob j) {
  11554         thro w $parseMi nErr('isec fn',
  11555              'Referenci ng Functio n in Angul ar express ions is di sallowed!  Expression : {0}',
  11556              fullExpres sion);
  11557       } else  if (// is Window(obj )
  11558           ob j.window = == obj) {
  11559         thro w $parseMi nErr('isec window',
  11560              'Referenci ng the Win dow in Ang ular expre ssions is  disallowed ! Expressi on: {0}',
  11561              fullExpres sion);
  11562       } else  if (// is Element(ob j)
  11563           ob j.children  && (obj.n odeName ||  (obj.prop  && obj.at tr && obj. find))) {
  11564         thro w $parseMi nErr('isec dom',
  11565              'Referenci ng DOM nod es in Angu lar expres sions is d isallowed!  Expressio n: {0}',
  11566              fullExpres sion);
  11567       } else  if (// bl ock Object  so that w e can't ge t hold of  dangerous  Object.* m ethods
  11568           ob j === Obje ct) {
  11569         thro w $parseMi nErr('isec obj',
  11570              'Referenci ng Object  in Angular  expressio ns is disa llowed! Ex pression:  {0}',
  11571              fullExpres sion);
  11572       }
  11573     }
  11574     return o bj;
  11575   }
  11576  
  11577   var CALL =  Function. prototype. call;
  11578   var APPLY  = Function .prototype .apply;
  11579   var BIND =  Function. prototype. bind;
  11580  
  11581   function e nsureSafeF unction(ob j, fullExp ression) {
  11582     if (obj)  {
  11583       if (ob j.construc tor === ob j) {
  11584         thro w $parseMi nErr('isec fn',
  11585           'R eferencing  Function  in Angular  expressio ns is disa llowed! Ex pression:  {0}',
  11586           fu llExpressi on);
  11587       } else  if (obj = == CALL ||  obj === A PPLY || ob j === BIND ) {
  11588         thro w $parseMi nErr('isec ff',
  11589           'R eferencing  call, app ly or bind  in Angula r expressi ons is dis allowed! E xpression:  {0}',
  11590           fu llExpressi on);
  11591       }
  11592     }
  11593   }
  11594  
  11595   //Keyword  constants
  11596   var CONSTA NTS = crea teMap();
  11597   forEach({
  11598     'null':  function()  { return  null; },
  11599     'true':  function()  { return  true; },
  11600     'false':  function( ) { return  false; },
  11601     'undefin ed': funct ion() {}
  11602   }, functio n(constant Getter, na me) {
  11603     constant Getter.con stant = co nstantGett er.literal  = constan tGetter.sh aredGetter  = true;
  11604     CONSTANT S[name] =  constantGe tter;
  11605   });
  11606  
  11607   //Not quit e a consta nt, but ca n be lex/p arsed the  same
  11608   CONSTANTS[ 'this'] =  function(s elf) { ret urn self;  };
  11609   CONSTANTS[ 'this'].sh aredGetter  = true;
  11610  
  11611  
  11612   //Operator s - will b e wrapped  by binaryF n/unaryFn/ assignment /filter
  11613   var OPERAT ORS = exte nd(createM ap(), {
  11614       '+':fu nction(sel f, locals,  a, b) {
  11615         a=a( self, loca ls); b=b(s elf, local s);
  11616         if ( isDefined( a)) {
  11617           if  (isDefine d(b)) {
  11618              return a +  b;
  11619           }
  11620           re turn a;
  11621         }
  11622         retu rn isDefin ed(b) ? b  : undefine d;},
  11623       '-':fu nction(sel f, locals,  a, b) {
  11624              a=a(self,  locals); b =b(self, l ocals);
  11625              return (is Defined(a)  ? a : 0)  - (isDefin ed(b) ? b  : 0);
  11626           },
  11627       '*':fu nction(sel f, locals,  a, b) {re turn a(sel f, locals)  * b(self,  locals);} ,
  11628       '/':fu nction(sel f, locals,  a, b) {re turn a(sel f, locals)  / b(self,  locals);} ,
  11629       '%':fu nction(sel f, locals,  a, b) {re turn a(sel f, locals)  % b(self,  locals);} ,
  11630       '===': function(s elf, local s, a, b) { return a(s elf, local s) === b(s elf, local s);},
  11631       '!==': function(s elf, local s, a, b) { return a(s elf, local s) !== b(s elf, local s);},
  11632       '==':f unction(se lf, locals , a, b) {r eturn a(se lf, locals ) == b(sel f, locals) ;},
  11633       '!=':f unction(se lf, locals , a, b) {r eturn a(se lf, locals ) != b(sel f, locals) ;},
  11634       '<':fu nction(sel f, locals,  a, b) {re turn a(sel f, locals)  < b(self,  locals);} ,
  11635       '>':fu nction(sel f, locals,  a, b) {re turn a(sel f, locals)  > b(self,  locals);} ,
  11636       '<=':f unction(se lf, locals , a, b) {r eturn a(se lf, locals ) <= b(sel f, locals) ;},
  11637       '>=':f unction(se lf, locals , a, b) {r eturn a(se lf, locals ) >= b(sel f, locals) ;},
  11638       '&&':f unction(se lf, locals , a, b) {r eturn a(se lf, locals ) && b(sel f, locals) ;},
  11639       '||':f unction(se lf, locals , a, b) {r eturn a(se lf, locals ) || b(sel f, locals) ;},
  11640       '!':fu nction(sel f, locals,  a) {retur n !a(self,  locals);} ,
  11641  
  11642       //Toke nized as o perators b ut parsed  as assignm ent/filter s
  11643       '=':tr ue,
  11644       '|':tr ue
  11645   });
  11646   var ESCAPE  = {"n":"\ n", "f":"\ f", "r":"\ r", "t":"\ t", "v":"\ v", "'":"' ", '"':'"' };
  11647  
  11648  
  11649   ////////// ////////// ////////// ////////// /
  11650  
  11651  
  11652   /**
  11653    * @constr uctor
  11654    */
  11655   var Lexer  = function (options)  {
  11656     this.opt ions = opt ions;
  11657   };
  11658  
  11659   Lexer.prot otype = {
  11660     construc tor: Lexer ,
  11661  
  11662     lex: fun ction(text ) {
  11663       this.t ext = text ;
  11664       this.i ndex = 0;
  11665       this.t okens = [] ;
  11666  
  11667       while  (this.inde x < this.t ext.length ) {
  11668         var  ch = this. text.charA t(this.ind ex);
  11669         if ( ch === '"'  || ch ===  "'") {
  11670           th is.readStr ing(ch);
  11671         } el se if (thi s.isNumber (ch) || ch  === '.' & & this.isN umber(this .peek()))  {
  11672           th is.readNum ber();
  11673         } el se if (thi s.isIdent( ch)) {
  11674           th is.readIde nt();
  11675         } el se if (thi s.is(ch, ' (){}[].,;: ?')) {
  11676           th is.tokens. push({inde x: this.in dex, text:  ch});
  11677           th is.index++ ;
  11678         } el se if (thi s.isWhites pace(ch))  {
  11679           th is.index++ ;
  11680         } el se {
  11681           va r ch2 = ch  + this.pe ek();
  11682           va r ch3 = ch 2 + this.p eek(2);
  11683           va r op1 = OP ERATORS[ch ];
  11684           va r op2 = OP ERATORS[ch 2];
  11685           va r op3 = OP ERATORS[ch 3];
  11686           if  (op1 || o p2 || op3)  {
  11687              var token  = op3 ? ch 3 : (op2 ?  ch2 : ch) ;
  11688              this.token s.push({in dex: this. index, tex t: token,  operator:  true});
  11689              this.index  += token. length;
  11690           }  else {
  11691              this.throw Error('Une xpected ne xt charact er ', this .index, th is.index +  1);
  11692           }
  11693         }
  11694       }
  11695       return  this.toke ns;
  11696     },
  11697  
  11698     is: func tion(ch, c hars) {
  11699       return  chars.ind exOf(ch) ! == -1;
  11700     },
  11701  
  11702     peek: fu nction(i)  {
  11703       var nu m = i || 1 ;
  11704       return  (this.ind ex + num <  this.text .length) ?  this.text .charAt(th is.index +  num) : fa lse;
  11705     },
  11706  
  11707     isNumber : function (ch) {
  11708       return  ('0' <= c h && ch <=  '9') && t ypeof ch = == "string ";
  11709     },
  11710  
  11711     isWhites pace: func tion(ch) {
  11712       // IE  treats non -breaking  space as \ u00A0
  11713       return  (ch === '  ' || ch = == '\r' ||  ch === '\ t' ||
  11714                ch === ' \n' || ch  === '\v' | | ch === ' \u00A0');
  11715     },
  11716  
  11717     isIdent:  function( ch) {
  11718       return  ('a' <= c h && ch <=  'z' ||
  11719                'A' <= c h && ch <=  'Z' ||
  11720                '_' ===  ch || ch = == '$');
  11721     },
  11722  
  11723     isExpOpe rator: fun ction(ch)  {
  11724       return  (ch === ' -' || ch = == '+' ||  this.isNum ber(ch));
  11725     },
  11726  
  11727     throwErr or: functi on(error,  start, end ) {
  11728       end =  end || thi s.index;
  11729       var co lStr = (is Defined(st art)
  11730                ? 's ' +  start +   '-' + this .index + '  [' + this .text.subs tring(star t, end) +  ']'
  11731                : ' ' +  end);
  11732       throw  $parseMinE rr('lexerr ', 'Lexer  Error: {0}  at column {1} in exp ression [{ 2}].',
  11733           er ror, colSt r, this.te xt);
  11734     },
  11735  
  11736     readNumb er: functi on() {
  11737       var nu mber = '';
  11738       var st art = this .index;
  11739       while  (this.inde x < this.t ext.length ) {
  11740         var  ch = lower case(this. text.charA t(this.ind ex));
  11741         if ( ch == '.'  || this.is Number(ch) ) {
  11742           nu mber += ch ;
  11743         } el se {
  11744           va r peekCh =  this.peek ();
  11745           if  (ch == 'e ' && this. isExpOpera tor(peekCh )) {
  11746              number +=  ch;
  11747           }  else if (t his.isExpO perator(ch ) &&
  11748                peekCh & & this.isN umber(peek Ch) &&
  11749                number.c harAt(numb er.length  - 1) == 'e ') {
  11750              number +=  ch;
  11751           }  else if (t his.isExpO perator(ch ) &&
  11752                (!peekCh  || !this. isNumber(p eekCh)) &&
  11753                number.c harAt(numb er.length  - 1) == 'e ') {
  11754              this.throw Error('Inv alid expon ent');
  11755           }  else {
  11756              break;
  11757           }
  11758         }
  11759         this .index++;
  11760       }
  11761       this.t okens.push ({
  11762         inde x: start,
  11763         text : number,
  11764         cons tant: true ,
  11765         valu e: Number( number)
  11766       });
  11767     },
  11768  
  11769     readIden t: functio n() {
  11770       var st art = this .index;
  11771       while  (this.inde x < this.t ext.length ) {
  11772         var  ch = this. text.charA t(this.ind ex);
  11773         if ( !(this.isI dent(ch) | | this.isN umber(ch)) ) {
  11774           br eak;
  11775         }
  11776         this .index++;
  11777       }
  11778       this.t okens.push ({
  11779         inde x: start,
  11780         text : this.tex t.slice(st art, this. index),
  11781         iden tifier: tr ue
  11782       });
  11783     },
  11784  
  11785     readStri ng: functi on(quote)  {
  11786       var st art = this .index;
  11787       this.i ndex++;
  11788       var st ring = '';
  11789       var ra wString =  quote;
  11790       var es cape = fal se;
  11791       while  (this.inde x < this.t ext.length ) {
  11792         var  ch = this. text.charA t(this.ind ex);
  11793         rawS tring += c h;
  11794         if ( escape) {
  11795           if  (ch === ' u') {
  11796              var hex =  this.text. substring( this.index  + 1, this .index + 5 );
  11797              if (!hex.m atch(/[\da -f]{4}/i))
  11798                this.thr owError('I nvalid uni code escap e [\\u' +  hex + ']') ;
  11799              this.index  += 4;
  11800              string +=  String.fro mCharCode( parseInt(h ex, 16));
  11801           }  else {
  11802              var rep =  ESCAPE[ch] ;
  11803              string = s tring + (r ep || ch);
  11804           }
  11805           es cape = fal se;
  11806         } el se if (ch  === '\\')  {
  11807           es cape = tru e;
  11808         } el se if (ch  === quote)  {
  11809           th is.index++ ;
  11810           th is.tokens. push({
  11811              index: sta rt,
  11812              text: rawS tring,
  11813              constant:  true,
  11814              value: str ing
  11815           }) ;
  11816           re turn;
  11817         } el se {
  11818           st ring += ch ;
  11819         }
  11820         this .index++;
  11821       }
  11822       this.t hrowError( 'Untermina ted quote' , start);
  11823     }
  11824   };
  11825  
  11826  
  11827   function i sConstant( exp) {
  11828     return e xp.constan t;
  11829   }
  11830  
  11831   /**
  11832    * @constr uctor
  11833    */
  11834   var Parser  = functio n(lexer, $ filter, op tions) {
  11835     this.lex er = lexer ;
  11836     this.$fi lter = $fi lter;
  11837     this.opt ions = opt ions;
  11838   };
  11839  
  11840   Parser.ZER O = extend (function( ) {
  11841     return 0 ;
  11842   }, {
  11843     sharedGe tter: true ,
  11844     constant : true
  11845   });
  11846  
  11847   Parser.pro totype = {
  11848     construc tor: Parse r,
  11849  
  11850     parse: f unction(te xt) {
  11851       this.t ext = text ;
  11852       this.t okens = th is.lexer.l ex(text);
  11853  
  11854       var va lue = this .statement s();
  11855  
  11856       if (th is.tokens. length !==  0) {
  11857         this .throwErro r('is an u nexpected  token', th is.tokens[ 0]);
  11858       }
  11859  
  11860       value. literal =  !!value.li teral;
  11861       value. constant =  !!value.c onstant;
  11862  
  11863       return  value;
  11864     },
  11865  
  11866     primary:  function( ) {
  11867       var pr imary;
  11868       if (th is.expect( '(')) {
  11869         prim ary = this .filterCha in();
  11870         this .consume(' )');
  11871       } else  if (this. expect('[' )) {
  11872         prim ary = this .arrayDecl aration();
  11873       } else  if (this. expect('{' )) {
  11874         prim ary = this .object();
  11875       } else  if (this. peek().ide ntifier) {
  11876         prim ary = this .identifie r();
  11877       } else  if (this. peek().con stant) {
  11878         prim ary = this .constant( );
  11879       } else  {
  11880         this .throwErro r('not a p rimary exp ression',  this.peek( ));
  11881       }
  11882  
  11883       var ne xt, contex t;
  11884       while  ((next = t his.expect ('(', '[',  '.'))) {
  11885         if ( next.text  === '(') {
  11886           pr imary = th is.functio nCall(prim ary, conte xt);
  11887           co ntext = nu ll;
  11888         } el se if (nex t.text ===  '[') {
  11889           co ntext = pr imary;
  11890           pr imary = th is.objectI ndex(prima ry);
  11891         } el se if (nex t.text ===  '.') {
  11892           co ntext = pr imary;
  11893           pr imary = th is.fieldAc cess(prima ry);
  11894         } el se {
  11895           th is.throwEr ror('IMPOS SIBLE');
  11896         }
  11897       }
  11898       return  primary;
  11899     },
  11900  
  11901     throwErr or: functi on(msg, to ken) {
  11902       throw  $parseMinE rr('syntax ',
  11903           'S yntax Erro r: Token \ '{0}\' {1}  at column  {2} of th e expressi on [{3}] s tarting at  [{4}].',
  11904              token.text , msg, (to ken.index  + 1), this .text, thi s.text.sub string(tok en.index)) ;
  11905     },
  11906  
  11907     peekToke n: functio n() {
  11908       if (th is.tokens. length ===  0)
  11909         thro w $parseMi nErr('ueoe ', 'Unexpe cted end o f expressi on: {0}',  this.text) ;
  11910       return  this.toke ns[0];
  11911     },
  11912  
  11913     peek: fu nction(e1,  e2, e3, e 4) {
  11914       return  this.peek Ahead(0, e 1, e2, e3,  e4);
  11915     },
  11916     peekAhea d: functio n(i, e1, e 2, e3, e4)  {
  11917       if (th is.tokens. length > i ) {
  11918         var  token = th is.tokens[ i];
  11919         var  t = token. text;
  11920         if ( t === e1 | | t === e2  || t ===  e3 || t == = e4 ||
  11921              (!e1 && !e 2 && !e3 & & !e4)) {
  11922           re turn token ;
  11923         }
  11924       }
  11925       return  false;
  11926     },
  11927  
  11928     expect:  function(e 1, e2, e3,  e4) {
  11929       var to ken = this .peek(e1,  e2, e3, e4 );
  11930       if (to ken) {
  11931         this .tokens.sh ift();
  11932         retu rn token;
  11933       }
  11934       return  false;
  11935     },
  11936  
  11937     consume:  function( e1) {
  11938       if (th is.tokens. length ===  0) {
  11939         thro w $parseMi nErr('ueoe ', 'Unexpe cted end o f expressi on: {0}',  this.text) ;
  11940       }
  11941  
  11942       var to ken = this .expect(e1 );
  11943       if (!t oken) {
  11944         this .throwErro r('is unex pected, ex pecting ['  + e1 + '] ', this.pe ek());
  11945       }
  11946       return  token;
  11947     },
  11948  
  11949     unaryFn:  function( op, right)  {
  11950       var fn  = OPERATO RS[op];
  11951       return  extend(fu nction $pa rseUnaryFn (self, loc als) {
  11952         retu rn fn(self , locals,  right);
  11953       }, {
  11954         cons tant:right .constant,
  11955         inpu ts: [right ]
  11956       });
  11957     },
  11958  
  11959     binaryFn : function (left, op,  right, is Branching)  {
  11960       var fn  = OPERATO RS[op];
  11961       return  extend(fu nction $pa rseBinaryF n(self, lo cals) {
  11962         retu rn fn(self , locals,  left, righ t);
  11963       }, {
  11964         cons tant: left .constant  && right.c onstant,
  11965         inpu ts: !isBra nching &&  [left, rig ht]
  11966       });
  11967     },
  11968  
  11969     identifi er: functi on() {
  11970       var id  = this.co nsume().te xt;
  11971  
  11972       //Cont inue readi ng each `. identifier ` unless i t is a met hod invoca tion
  11973       while  (this.peek ('.') && t his.peekAh ead(1).ide ntifier &&  !this.pee kAhead(2,  '(')) {
  11974         id + = this.con sume().tex t + this.c onsume().t ext;
  11975       }
  11976  
  11977       return  CONSTANTS [id] || ge tterFn(id,  this.opti ons, this. text);
  11978     },
  11979  
  11980     constant : function () {
  11981       var va lue = this .consume() .value;
  11982  
  11983       return  extend(fu nction $pa rseConstan t() {
  11984         retu rn value;
  11985       }, {
  11986         cons tant: true ,
  11987         lite ral: true
  11988       });
  11989     },
  11990  
  11991     statemen ts: functi on() {
  11992       var st atements =  [];
  11993       while  (true) {
  11994         if ( this.token s.length >  0 && !thi s.peek('}' , ')', ';' , ']'))
  11995           st atements.p ush(this.f ilterChain ());
  11996         if ( !this.expe ct(';')) {
  11997           //  optimize  for the co mmon case  where ther e is only  one statem ent.
  11998           //  TODO(size ): maybe w e should n ot support  multiple  statements ?
  11999           re turn (stat ements.len gth === 1)
  12000                ? statem ents[0]
  12001                : functi on $parseS tatements( self, loca ls) {
  12002                    var  value;
  12003                    for  (var i = 0 , ii = sta tements.le ngth; i <  ii; i++) {
  12004                      va lue = stat ements[i]( self, loca ls);
  12005                    }
  12006                    retu rn value;
  12007                  };
  12008         }
  12009       }
  12010     },
  12011  
  12012     filterCh ain: funct ion() {
  12013       var le ft = this. expression ();
  12014       var to ken;
  12015       while  ((token =  this.expec t('|'))) {
  12016         left  = this.fi lter(left) ;
  12017       }
  12018       return  left;
  12019     },
  12020  
  12021     filter:  function(i nputFn) {
  12022       var fn  = this.$f ilter(this .consume() .text);
  12023       var ar gsFn;
  12024       var ar gs;
  12025  
  12026       if (th is.peek(': ')) {
  12027         args Fn = [];
  12028         args  = []; //  we can saf ely reuse  the array
  12029         whil e (this.ex pect(':'))  {
  12030           ar gsFn.push( this.expre ssion());
  12031         }
  12032       }
  12033  
  12034       var in puts = [in putFn].con cat(argsFn  || []);
  12035  
  12036       return  extend(fu nction $pa rseFilter( self, loca ls) {
  12037         var  input = in putFn(self , locals);
  12038         if ( args) {
  12039           ar gs[0] = in put;
  12040  
  12041           va r i = args Fn.length;
  12042           wh ile (i--)  {
  12043              args[i + 1 ] = argsFn [i](self,  locals);
  12044           }
  12045  
  12046           re turn fn.ap ply(undefi ned, args) ;
  12047         }
  12048  
  12049         retu rn fn(inpu t);
  12050       }, {
  12051         cons tant: !fn. $stateful  && inputs. every(isCo nstant),
  12052         inpu ts: !fn.$s tateful &&  inputs
  12053       });
  12054     },
  12055  
  12056     expressi on: functi on() {
  12057       return  this.assi gnment();
  12058     },
  12059  
  12060     assignme nt: functi on() {
  12061       var le ft = this. ternary();
  12062       var ri ght;
  12063       var to ken;
  12064       if ((t oken = thi s.expect(' ='))) {
  12065         if ( !left.assi gn) {
  12066           th is.throwEr ror('impli es assignm ent but ['  +
  12067                this.tex t.substrin g(0, token .index) +  '] can not  be assign ed to', to ken);
  12068         }
  12069         righ t = this.t ernary();
  12070         retu rn extend( function $ parseAssig nment(scop e, locals)  {
  12071           re turn left. assign(sco pe, right( scope, loc als), loca ls);
  12072         }, {
  12073           in puts: [lef t, right]
  12074         });
  12075       }
  12076       return  left;
  12077     },
  12078  
  12079     ternary:  function( ) {
  12080       var le ft = this. logicalOR( );
  12081       var mi ddle;
  12082       var to ken;
  12083       if ((t oken = thi s.expect(' ?'))) {
  12084         midd le = this. assignment ();
  12085         if ( this.consu me(':')) {
  12086           va r right =  this.assig nment();
  12087  
  12088           re turn exten d(function  $parseTer nary(self,  locals) {
  12089              return lef t(self, lo cals) ? mi ddle(self,  locals) :  right(sel f, locals) ;
  12090           },  {
  12091              constant:  left.const ant && mid dle.consta nt && righ t.constant
  12092           }) ;
  12093         }
  12094       }
  12095  
  12096       return  left;
  12097     },
  12098  
  12099     logicalO R: functio n() {
  12100       var le ft = this. logicalAND ();
  12101       var to ken;
  12102       while  ((token =  this.expec t('||')))  {
  12103         left  = this.bi naryFn(lef t, token.t ext, this. logicalAND (), true);
  12104       }
  12105       return  left;
  12106     },
  12107  
  12108     logicalA ND: functi on() {
  12109       var le ft = this. equality() ;
  12110       var to ken;
  12111       if ((t oken = thi s.expect(' &&'))) {
  12112         left  = this.bi naryFn(lef t, token.t ext, this. logicalAND (), true);
  12113       }
  12114       return  left;
  12115     },
  12116  
  12117     equality : function () {
  12118       var le ft = this. relational ();
  12119       var to ken;
  12120       if ((t oken = thi s.expect(' ==','!=',' ===','!==' ))) {
  12121         left  = this.bi naryFn(lef t, token.t ext, this. equality() );
  12122       }
  12123       return  left;
  12124     },
  12125  
  12126     relation al: functi on() {
  12127       var le ft = this. additive() ;
  12128       var to ken;
  12129       if ((t oken = thi s.expect(' <', '>', ' <=', '>=') )) {
  12130         left  = this.bi naryFn(lef t, token.t ext, this. relational ());
  12131       }
  12132       return  left;
  12133     },
  12134  
  12135     additive : function () {
  12136       var le ft = this. multiplica tive();
  12137       var to ken;
  12138       while  ((token =  this.expec t('+','-') )) {
  12139         left  = this.bi naryFn(lef t, token.t ext, this. multiplica tive());
  12140       }
  12141       return  left;
  12142     },
  12143  
  12144     multipli cative: fu nction() {
  12145       var le ft = this. unary();
  12146       var to ken;
  12147       while  ((token =  this.expec t('*','/', '%'))) {
  12148         left  = this.bi naryFn(lef t, token.t ext, this. unary());
  12149       }
  12150       return  left;
  12151     },
  12152  
  12153     unary: f unction()  {
  12154       var to ken;
  12155       if (th is.expect( '+')) {
  12156         retu rn this.pr imary();
  12157       } else  if ((toke n = this.e xpect('-') )) {
  12158         retu rn this.bi naryFn(Par ser.ZERO,  token.text , this.una ry());
  12159       } else  if ((toke n = this.e xpect('!') )) {
  12160         retu rn this.un aryFn(toke n.text, th is.unary() );
  12161       } else  {
  12162         retu rn this.pr imary();
  12163       }
  12164     },
  12165  
  12166     fieldAcc ess: funct ion(object ) {
  12167       var ex pression =  this.text ;
  12168       var fi eld = this .consume() .text;
  12169       var ge tter = get terFn(fiel d, this.op tions, exp ression);
  12170  
  12171       return  extend(fu nction $pa rseFieldAc cess(scope , locals,  self) {
  12172         retu rn getter( self || ob ject(scope , locals)) ;
  12173       }, {
  12174         assi gn: functi on(scope,  value, loc als) {
  12175           va r o = obje ct(scope,  locals);
  12176           if  (!o) obje ct.assign( scope, o =  {});
  12177           re turn sette r(o, field , value, e xpression) ;
  12178         }
  12179       });
  12180     },
  12181  
  12182     objectIn dex: funct ion(obj) {
  12183       var ex pression =  this.text ;
  12184  
  12185       var in dexFn = th is.express ion();
  12186       this.c onsume(']' );
  12187  
  12188       return  extend(fu nction $pa rseObjectI ndex(self,  locals) {
  12189         var  o = obj(se lf, locals ),
  12190              i = indexF n(self, lo cals),
  12191              v;
  12192  
  12193         ensu reSafeMemb erName(i,  expression );
  12194         if ( !o) return  undefined ;
  12195         v =  ensureSafe Object(o[i ], express ion);
  12196         retu rn v;
  12197       }, {
  12198         assi gn: functi on(self, v alue, loca ls) {
  12199           va r key = en sureSafeMe mberName(i ndexFn(sel f, locals) , expressi on);
  12200           //  prevent o verwriting  of Functi on.constru ctor which  would bre ak ensureS afeObject  check
  12201           va r o = ensu reSafeObje ct(obj(sel f, locals) , expressi on);
  12202           if  (!o) obj. assign(sel f, o = {}) ;
  12203           re turn o[key ] = value;
  12204         }
  12205       });
  12206     },
  12207  
  12208     function Call: func tion(fnGet ter, conte xtGetter)  {
  12209       var ar gsFn = [];
  12210       if (th is.peekTok en().text  !== ')') {
  12211         do {
  12212           ar gsFn.push( this.expre ssion());
  12213         } wh ile (this. expect(',' ));
  12214       }
  12215       this.c onsume(')' );
  12216  
  12217       var ex pressionTe xt = this. text;
  12218       // we  can safely  reuse the  array acr oss invoca tions
  12219       var ar gs = argsF n.length ?  [] : null ;
  12220  
  12221       return  function  $parseFunc tionCall(s cope, loca ls) {
  12222         var  context =  contextGet ter ? cont extGetter( scope, loc als) : sco pe;
  12223         var  fn = fnGet ter(scope,  locals, c ontext) ||  noop;
  12224  
  12225         if ( args) {
  12226           va r i = args Fn.length;
  12227           wh ile (i--)  {
  12228              args[i] =  ensureSafe Object(arg sFn[i](sco pe, locals ), express ionText);
  12229           }
  12230         }
  12231  
  12232         ensu reSafeObje ct(context , expressi onText);
  12233         ensu reSafeFunc tion(fn, e xpressionT ext);
  12234  
  12235         // I E doesn't  have apply  for some  native fun ctions
  12236         var  v = fn.app ly
  12237                ? fn.app ly(context , args)
  12238                : fn(arg s[0], args [1], args[ 2], args[3 ], args[4] );
  12239  
  12240         retu rn ensureS afeObject( v, express ionText);
  12241         };
  12242     },
  12243  
  12244     // This  is used wi th json ar ray declar ation
  12245     arrayDec laration:  function()  {
  12246       var el ementFns =  [];
  12247       if (th is.peekTok en().text  !== ']') {
  12248         do {
  12249           if  (this.pee k(']')) {
  12250              // Support  trailing  commas per  ES5.1.
  12251              break;
  12252           }
  12253           el ementFns.p ush(this.e xpression( ));
  12254         } wh ile (this. expect(',' ));
  12255       }
  12256       this.c onsume(']' );
  12257  
  12258       return  extend(fu nction $pa rseArrayLi teral(self , locals)  {
  12259         var  array = [] ;
  12260         for  (var i = 0 , ii = ele mentFns.le ngth; i <  ii; i++) {
  12261           ar ray.push(e lementFns[ i](self, l ocals));
  12262         }
  12263         retu rn array;
  12264       }, {
  12265         lite ral: true,
  12266         cons tant: elem entFns.eve ry(isConst ant),
  12267         inpu ts: elemen tFns
  12268       });
  12269     },
  12270  
  12271     object:  function()  {
  12272       var ke ys = [], v alueFns =  [];
  12273       if (th is.peekTok en().text  !== '}') {
  12274         do {
  12275           if  (this.pee k('}')) {
  12276              // Support  trailing  commas per  ES5.1.
  12277              break;
  12278           }
  12279           va r token =  this.consu me();
  12280           if  (token.co nstant) {
  12281              keys.push( token.valu e);
  12282           }  else if (t oken.ident ifier) {
  12283              keys.push( token.text );
  12284           }  else {
  12285              this.throw Error("inv alid key",  token);
  12286           }
  12287           th is.consume (':');
  12288           va lueFns.pus h(this.exp ression()) ;
  12289         } wh ile (this. expect(',' ));
  12290       }
  12291       this.c onsume('}' );
  12292  
  12293       return  extend(fu nction $pa rseObjectL iteral(sel f, locals)  {
  12294         var  object = { };
  12295         for  (var i = 0 , ii = val ueFns.leng th; i < ii ; i++) {
  12296           ob ject[keys[ i]] = valu eFns[i](se lf, locals );
  12297         }
  12298         retu rn object;
  12299       }, {
  12300         lite ral: true,
  12301         cons tant: valu eFns.every (isConstan t),
  12302         inpu ts: valueF ns
  12303       });
  12304     }
  12305   };
  12306  
  12307  
  12308   ////////// ////////// ////////// ////////// //////////
  12309   // Parser  helper fun ctions
  12310   ////////// ////////// ////////// ////////// //////////
  12311  
  12312   function s etter(obj,  path, set Value, ful lExp) {
  12313     ensureSa feObject(o bj, fullEx p);
  12314  
  12315     var elem ent = path .split('.' ), key;
  12316     for (var  i = 0; el ement.leng th > 1; i+ +) {
  12317       key =  ensureSafe MemberName (element.s hift(), fu llExp);
  12318       var pr opertyObj  = ensureSa feObject(o bj[key], f ullExp);
  12319       if (!p ropertyObj ) {
  12320         prop ertyObj =  {};
  12321         obj[ key] = pro pertyObj;
  12322       }
  12323       obj =  propertyOb j;
  12324     }
  12325     key = en sureSafeMe mberName(e lement.shi ft(), full Exp);
  12326     ensureSa feObject(o bj[key], f ullExp);
  12327     obj[key]  = setValu e;
  12328     return s etValue;
  12329   }
  12330  
  12331   var getter FnCacheDef ault = cre ateMap();
  12332   var getter FnCacheExp ensive = c reateMap() ;
  12333  
  12334   function i sPossiblyD angerousMe mberName(n ame) {
  12335     return n ame == 'co nstructor' ;
  12336   }
  12337  
  12338   /**
  12339    * Impleme ntation of  the "Blac k Hole" va riant from :
  12340    * - http: //jsperf.c om/angular js-parse-g etter/4
  12341    * - http: //jsperf.c om/path-ev aluation-s implified/ 7
  12342    */
  12343   function c spSafeGett erFn(key0,  key1, key 2, key3, k ey4, fullE xp, expens iveChecks)  {
  12344     ensureSa feMemberNa me(key0, f ullExp);
  12345     ensureSa feMemberNa me(key1, f ullExp);
  12346     ensureSa feMemberNa me(key2, f ullExp);
  12347     ensureSa feMemberNa me(key3, f ullExp);
  12348     ensureSa feMemberNa me(key4, f ullExp);
  12349     var eso  = function (o) {
  12350       return  ensureSaf eObject(o,  fullExp);
  12351     };
  12352     var eso0  = (expens iveChecks  || isPossi blyDangero usMemberNa me(key0))  ? eso : id entity;
  12353     var eso1  = (expens iveChecks  || isPossi blyDangero usMemberNa me(key1))  ? eso : id entity;
  12354     var eso2  = (expens iveChecks  || isPossi blyDangero usMemberNa me(key2))  ? eso : id entity;
  12355     var eso3  = (expens iveChecks  || isPossi blyDangero usMemberNa me(key3))  ? eso : id entity;
  12356     var eso4  = (expens iveChecks  || isPossi blyDangero usMemberNa me(key4))  ? eso : id entity;
  12357  
  12358     return f unction cs pSafeGette r(scope, l ocals) {
  12359       var pa thVal = (l ocals && l ocals.hasO wnProperty (key0)) ?  locals : s cope;
  12360  
  12361       if (pa thVal == n ull) retur n pathVal;
  12362       pathVa l = eso0(p athVal[key 0]);
  12363  
  12364       if (!k ey1) retur n pathVal;
  12365       if (pa thVal == n ull) retur n undefine d;
  12366       pathVa l = eso1(p athVal[key 1]);
  12367  
  12368       if (!k ey2) retur n pathVal;
  12369       if (pa thVal == n ull) retur n undefine d;
  12370       pathVa l = eso2(p athVal[key 2]);
  12371  
  12372       if (!k ey3) retur n pathVal;
  12373       if (pa thVal == n ull) retur n undefine d;
  12374       pathVa l = eso3(p athVal[key 3]);
  12375  
  12376       if (!k ey4) retur n pathVal;
  12377       if (pa thVal == n ull) retur n undefine d;
  12378       pathVa l = eso4(p athVal[key 4]);
  12379  
  12380       return  pathVal;
  12381     };
  12382   }
  12383  
  12384   function g etterFnWit hEnsureSaf eObject(fn , fullExpr ession) {
  12385     return f unction(s,  l) {
  12386       return  fn(s, l,  ensureSafe Object, fu llExpressi on);
  12387     };
  12388   }
  12389  
  12390   function g etterFn(pa th, option s, fullExp ) {
  12391     var expe nsiveCheck s = option s.expensiv eChecks;
  12392     var gett erFnCache  = (expensi veChecks ?  getterFnC acheExpens ive : gett erFnCacheD efault);
  12393     var fn =  getterFnC ache[path] ;
  12394     if (fn)  return fn;
  12395  
  12396  
  12397     var path Keys = pat h.split('. '),
  12398         path KeysLength  = pathKey s.length;
  12399  
  12400     // http: //jsperf.c om/angular js-parse-g etter/6
  12401     if (opti ons.csp) {
  12402       if (pa thKeysLeng th < 6) {
  12403         fn =  cspSafeGe tterFn(pat hKeys[0],  pathKeys[1 ], pathKey s[2], path Keys[3], p athKeys[4] , fullExp,  expensive Checks);
  12404       } else  {
  12405         fn =  function  cspSafeGet ter(scope,  locals) {
  12406           va r i = 0, v al;
  12407           do  {
  12408              val = cspS afeGetterF n(pathKeys [i++], pat hKeys[i++] , pathKeys [i++], pat hKeys[i++] ,
  12409                                      pathKeys [i++], ful lExp, expe nsiveCheck s)(scope,  locals);
  12410  
  12411              locals = u ndefined;  // clear a fter first  iteration
  12412              scope = va l;
  12413           }  while (i <  pathKeysL ength);
  12414           re turn val;
  12415         };
  12416       }
  12417     } else {
  12418       var co de = '';
  12419       if (ex pensiveChe cks) {
  12420         code  += 's = e so(s, fe); \nl = eso( l, fe);\n' ;
  12421       }
  12422       var ne edsEnsureS afeObject  = expensiv eChecks;
  12423       forEac h(pathKeys , function (key, inde x) {
  12424         ensu reSafeMemb erName(key , fullExp) ;
  12425         var  lookupJs =  (index
  12426                           // we si mply deref erence 's'  on any .d ot notatio n
  12427                           ? 's'
  12428                           // but i f we are f irst then  we check l ocals firs t, and if  so read it  first
  12429                           : '((l&& l.hasOwnPr operty("'  + key + '" ))?l:s)')  + '.' + ke y;
  12430         if ( expensiveC hecks || i sPossiblyD angerousMe mberName(k ey)) {
  12431           lo okupJs = ' eso(' + lo okupJs + ' , fe)';
  12432           ne edsEnsureS afeObject  = true;
  12433         }
  12434         code  += 'if(s  == null) r eturn unde fined;\n'  +
  12435                  's=' +  lookupJs  + ';\n';
  12436       });
  12437       code + = 'return  s;';
  12438  
  12439       /* jsh int -W054  */
  12440       var ev aledFnGett er = new F unction('s ', 'l', 'e so', 'fe',  code); //  s=scope,  l=locals,  eso=ensure SafeObject
  12441       /* jsh int +W054  */
  12442       evaled FnGetter.t oString =  valueFn(co de);
  12443       if (ne edsEnsureS afeObject)  {
  12444         eval edFnGetter  = getterF nWithEnsur eSafeObjec t(evaledFn Getter, fu llExp);
  12445       }
  12446       fn = e valedFnGet ter;
  12447     }
  12448  
  12449     fn.share dGetter =  true;
  12450     fn.assig n = functi on(self, v alue) {
  12451       return  setter(se lf, path,  value, pat h);
  12452     };
  12453     getterFn Cache[path ] = fn;
  12454     return f n;
  12455   }
  12456  
  12457   var object ValueOf =  Object.pro totype.val ueOf;
  12458  
  12459   function g etValueOf( value) {
  12460     return i sFunction( value.valu eOf) ? val ue.valueOf () : objec tValueOf.c all(value) ;
  12461   }
  12462  
  12463   ////////// ////////// ////////// /////
  12464  
  12465   /**
  12466    * @ngdoc  service
  12467    * @name $ parse
  12468    * @kind f unction
  12469    *
  12470    * @descri ption
  12471    *
  12472    * Convert s Angular  {@link gui de/express ion expres sion} into  a functio n.
  12473    *
  12474    * ```js
  12475    *   var g etter = $p arse('user .name');
  12476    *   var s etter = ge tter.assig n;
  12477    *   var c ontext = { user:{name :'angular' }};
  12478    *   var l ocals = {u ser:{name: 'local'}};
  12479    *
  12480    *   expec t(getter(c ontext)).t oEqual('an gular');
  12481    *   sette r(context,  'newValue ');
  12482    *   expec t(context. user.name) .toEqual(' newValue') ;
  12483    *   expec t(getter(c ontext, lo cals)).toE qual('loca l');
  12484    * ```
  12485    *
  12486    *
  12487    * @param  {string} e xpression  String exp ression to  compile.
  12488    * @return s {functio n(context,  locals)}  a function  which rep resents th e compiled  expressio n:
  12489    *
  12490    *    * `c ontext` â€ “ `{object }` â€“ an  object aga inst which  any expre ssions emb edded in t he strings
  12491    *      ar e evaluate d against  (typically  a scope o bject).
  12492    *    * `l ocals` â€“  `{object= }` â€“ loc al variabl es context  object, u seful for  overriding  values in
  12493    *      `c ontext`.
  12494    *
  12495    *    The  returned f unction al so has the  following  propertie s:
  12496    *      *  `literal`  – `{bool ean}` â€“  whether th e expressi on's top-l evel node  is a JavaS cript
  12497    *         literal.
  12498    *      *  `constant`  â€“ `{boo lean}` â€“  whether t he express ion is mad e entirely  of JavaSc ript
  12499    *         constant l iterals.
  12500    *      *  `assign` â €“ `{?func tion(conte xt, value) }` â€“ if  the expres sion is as signable,  this will  be
  12501    *         set to a f unction to  change it s value on  the given  context.
  12502    *
  12503    */
  12504  
  12505  
  12506   /**
  12507    * @ngdoc  provider
  12508    * @name $ parseProvi der
  12509    *
  12510    * @descri ption
  12511    * `$parse Provider`  can be use d for conf iguring th e default  behavior o f the {@li nk ng.$par se $parse}
  12512    *  servic e.
  12513    */
  12514   function $ ParseProvi der() {
  12515     var cach eDefault =  createMap ();
  12516     var cach eExpensive  = createM ap();
  12517  
  12518  
  12519  
  12520     this.$ge t = ['$fil ter', '$sn iffer', fu nction($fi lter, $sni ffer) {
  12521       var $p arseOption s = {
  12522              csp: $snif fer.csp,
  12523              expensiveC hecks: fal se
  12524           },
  12525           $p arseOption sExpensive  = {
  12526              csp: $snif fer.csp,
  12527              expensiveC hecks: tru e
  12528           };
  12529  
  12530       functi on wrapSha redExpress ion(exp) {
  12531         var  wrapped =  exp;
  12532  
  12533         if ( exp.shared Getter) {
  12534           wr apped = fu nction $pa rseWrapper (self, loc als) {
  12535              return exp (self, loc als);
  12536           };
  12537           wr apped.lite ral = exp. literal;
  12538           wr apped.cons tant = exp .constant;
  12539           wr apped.assi gn = exp.a ssign;
  12540         }
  12541  
  12542         retu rn wrapped ;
  12543       }
  12544  
  12545       return  function  $parse(exp , intercep torFn, exp ensiveChec ks) {
  12546         var  parsedExpr ession, on eTime, cac heKey;
  12547  
  12548         swit ch (typeof  exp) {
  12549           ca se 'string ':
  12550              cacheKey =  exp = exp .trim();
  12551  
  12552              var cache  = (expensi veChecks ?  cacheExpe nsive : ca cheDefault );
  12553              parsedExpr ession = c ache[cache Key];
  12554  
  12555              if (!parse dExpressio n) {
  12556                if (exp. charAt(0)  === ':' &&  exp.charA t(1) === ' :') {
  12557                  oneTim e = true;
  12558                  exp =  exp.substr ing(2);
  12559                }
  12560  
  12561                var pars eOptions =  expensive Checks ? $ parseOptio nsExpensiv e : $parse Options;
  12562                var lexe r = new Le xer(parseO ptions);
  12563                var pars er = new P arser(lexe r, $filter , parseOpt ions);
  12564                parsedEx pression =  parser.pa rse(exp);
  12565  
  12566                if (pars edExpressi on.constan t) {
  12567                  parsed Expression .$$watchDe legate = c onstantWat chDelegate ;
  12568                } else i f (oneTime ) {
  12569                  //oneT ime is not  part of t he exp pas sed to the  Parser so  we may ha ve to
  12570                  //wrap  the parse dExpressio n before a dding a $$ watchDeleg ate
  12571                  parsed Expression  = wrapSha redExpress ion(parsed Expression );
  12572                  parsed Expression .$$watchDe legate = p arsedExpre ssion.lite ral ?
  12573                    oneT imeLiteral WatchDeleg ate : oneT imeWatchDe legate;
  12574                } else i f (parsedE xpression. inputs) {
  12575                  parsed Expression .$$watchDe legate = i nputsWatch Delegate;
  12576                }
  12577  
  12578                cache[ca cheKey] =  parsedExpr ession;
  12579              }
  12580              return add Intercepto r(parsedEx pression,  intercepto rFn);
  12581  
  12582           ca se 'functi on':
  12583              return add Intercepto r(exp, int erceptorFn );
  12584  
  12585           de fault:
  12586              return add Intercepto r(noop, in terceptorF n);
  12587         }
  12588       };
  12589  
  12590       functi on collect Expression Inputs(inp uts, list)  {
  12591         for  (var i = 0 , ii = inp uts.length ; i < ii;  i++) {
  12592           va r input =  inputs[i];
  12593           if  (!input.c onstant) {
  12594              if (input. inputs) {
  12595                collectE xpressionI nputs(inpu t.inputs,  list);
  12596              } else if  (list.inde xOf(input)  === -1) {  // TODO(p erf) can w e do bette r?
  12597                list.pus h(input);
  12598              }
  12599           }
  12600         }
  12601  
  12602         retu rn list;
  12603       }
  12604  
  12605       functi on express ionInputDi rtyCheck(n ewValue, o ldValueOfV alue) {
  12606  
  12607         if ( newValue = = null ||  oldValueOf Value == n ull) { //  null/undef ined
  12608           re turn newVa lue === ol dValueOfVa lue;
  12609         }
  12610  
  12611         if ( typeof new Value ===  'object')  {
  12612  
  12613           //  attempt t o convert  the value  to a primi tive type
  12614           //  TODO(docs ): add a n ote to doc s that by  implementi ng valueOf  even obje cts and ar rays can
  12615           //               be chea ply dirty- checked
  12616           ne wValue = g etValueOf( newValue);
  12617  
  12618           if  (typeof n ewValue == = 'object' ) {
  12619              // objects /arrays ar e not supp orted - de ep-watchin g them wou ld be too  expensive
  12620              return fal se;
  12621           }
  12622  
  12623           //  fall-thro ugh to the  primitive  equality  check
  12624         }
  12625  
  12626         //Pr imitive or  NaN
  12627         retu rn newValu e === oldV alueOfValu e || (newV alue !== n ewValue &&  oldValueO fValue !==  oldValueO fValue);
  12628       }
  12629  
  12630       functi on inputsW atchDelega te(scope,  listener,  objectEqua lity, pars edExpressi on) {
  12631         var  inputExpre ssions = p arsedExpre ssion.$$in puts ||
  12632                         (parsedExp ression.$$ inputs = c ollectExpr essionInpu ts(parsedE xpression. inputs, [] ));
  12633  
  12634         var  lastResult ;
  12635  
  12636         if ( inputExpre ssions.len gth === 1)  {
  12637           va r oldInput Value = ex pressionIn putDirtyCh eck; // in it to some thing uniq ue so that  equals ch eck fails
  12638           in putExpress ions = inp utExpressi ons[0];
  12639           re turn scope .$watch(fu nction exp ressionInp utWatch(sc ope) {
  12640              var newInp utValue =  inputExpre ssions(sco pe);
  12641              if (!expre ssionInput DirtyCheck (newInputV alue, oldI nputValue) ) {
  12642                lastResu lt = parse dExpressio n(scope);
  12643                oldInput Value = ne wInputValu e && getVa lueOf(newI nputValue) ;
  12644              }
  12645              return las tResult;
  12646           },  listener,  objectEqu ality);
  12647         }
  12648  
  12649         var  oldInputVa lueOfValue s = [];
  12650         for  (var i = 0 , ii = inp utExpressi ons.length ; i < ii;  i++) {
  12651           ol dInputValu eOfValues[ i] = expre ssionInput DirtyCheck ; // init  to somethi ng unique  so that eq uals check  fails
  12652         }
  12653  
  12654         retu rn scope.$ watch(func tion expre ssionInput sWatch(sco pe) {
  12655           va r changed  = false;
  12656  
  12657           fo r (var i =  0, ii = i nputExpres sions.leng th; i < ii ; i++) {
  12658              var newInp utValue =  inputExpre ssions[i]( scope);
  12659              if (change d || (chan ged = !exp ressionInp utDirtyChe ck(newInpu tValue, ol dInputValu eOfValues[ i]))) {
  12660                oldInput ValueOfVal ues[i] = n ewInputVal ue && getV alueOf(new InputValue );
  12661              }
  12662           }
  12663  
  12664           if  (changed)  {
  12665              lastResult  = parsedE xpression( scope);
  12666           }
  12667  
  12668           re turn lastR esult;
  12669         }, l istener, o bjectEqual ity);
  12670       }
  12671  
  12672       functi on oneTime WatchDeleg ate(scope,  listener,  objectEqu ality, par sedExpress ion) {
  12673         var  unwatch, l astValue;
  12674         retu rn unwatch  = scope.$ watch(func tion oneTi meWatch(sc ope) {
  12675           re turn parse dExpressio n(scope);
  12676         }, f unction on eTimeListe ner(value,  old, scop e) {
  12677           la stValue =  value;
  12678           if  (isFuncti on(listene r)) {
  12679              listener.a pply(this,  arguments );
  12680           }
  12681           if  (isDefine d(value))  {
  12682              scope.$$po stDigest(f unction()  {
  12683                if (isDe fined(last Value)) {
  12684                  unwatc h();
  12685                }
  12686              });
  12687           }
  12688         }, o bjectEqual ity);
  12689       }
  12690  
  12691       functi on oneTime LiteralWat chDelegate (scope, li stener, ob jectEquali ty, parsed Expression ) {
  12692         var  unwatch, l astValue;
  12693         retu rn unwatch  = scope.$ watch(func tion oneTi meWatch(sc ope) {
  12694           re turn parse dExpressio n(scope);
  12695         }, f unction on eTimeListe ner(value,  old, scop e) {
  12696           la stValue =  value;
  12697           if  (isFuncti on(listene r)) {
  12698              listener.c all(this,  value, old , scope);
  12699           }
  12700           if  (isAllDef ined(value )) {
  12701              scope.$$po stDigest(f unction()  {
  12702                if (isAl lDefined(l astValue))  unwatch() ;
  12703              });
  12704           }
  12705         }, o bjectEqual ity);
  12706  
  12707         func tion isAll Defined(va lue) {
  12708           va r allDefin ed = true;
  12709           fo rEach(valu e, functio n(val) {
  12710              if (!isDef ined(val))  allDefine d = false;
  12711           }) ;
  12712           re turn allDe fined;
  12713         }
  12714       }
  12715  
  12716       functi on constan tWatchDele gate(scope , listener , objectEq uality, pa rsedExpres sion) {
  12717         var  unwatch;
  12718         retu rn unwatch  = scope.$ watch(func tion const antWatch(s cope) {
  12719           re turn parse dExpressio n(scope);
  12720         }, f unction co nstantList ener(value , old, sco pe) {
  12721           if  (isFuncti on(listene r)) {
  12722              listener.a pply(this,  arguments );
  12723           }
  12724           un watch();
  12725         }, o bjectEqual ity);
  12726       }
  12727  
  12728       functi on addInte rceptor(pa rsedExpres sion, inte rceptorFn)  {
  12729         if ( !intercept orFn) retu rn parsedE xpression;
  12730         var  watchDeleg ate = pars edExpressi on.$$watch Delegate;
  12731  
  12732         var  regularWat ch =
  12733              watchDeleg ate !== on eTimeLiter alWatchDel egate &&
  12734              watchDeleg ate !== on eTimeWatch Delegate;
  12735  
  12736         var  fn = regul arWatch ?  function r egularInte rceptedExp ression(sc ope, local s) {
  12737           va r value =  parsedExpr ession(sco pe, locals );
  12738           re turn inter ceptorFn(v alue, scop e, locals) ;
  12739         } :  function o neTimeInte rceptedExp ression(sc ope, local s) {
  12740           va r value =  parsedExpr ession(sco pe, locals );
  12741           va r result =  intercept orFn(value , scope, l ocals);
  12742           //  we only r eturn the  intercepto r's result  if the
  12743           //  initial v alue is de fined (for  bind-once )
  12744           re turn isDef ined(value ) ? result  : value;
  12745         };
  12746  
  12747         // P ropagate $ $watchDele gates othe r then inp utsWatchDe legate
  12748         if ( parsedExpr ession.$$w atchDelega te &&
  12749              parsedExpr ession.$$w atchDelega te !== inp utsWatchDe legate) {
  12750           fn .$$watchDe legate = p arsedExpre ssion.$$wa tchDelegat e;
  12751         } el se if (!in terceptorF n.$statefu l) {
  12752           //  If there  is an inte rceptor, b ut no watc hDelegate  then treat  the inter ceptor lik e
  12753           //  we treat  filters -  it is assu med to be  a pure fun ction unle ss flagged  with $sta teful
  12754           fn .$$watchDe legate = i nputsWatch Delegate;
  12755           fn .inputs =  [parsedExp ression];
  12756         }
  12757  
  12758         retu rn fn;
  12759       }
  12760     }];
  12761   }
  12762  
  12763   /**
  12764    * @ngdoc  service
  12765    * @name $ q
  12766    * @requir es $rootSc ope
  12767    *
  12768    * @descri ption
  12769    * A servi ce that he lps you ru n function s asynchro nously, an d use thei r return v alues (or  exceptions )
  12770    * when th ey are don e processi ng.
  12771    *
  12772    * This is  an implem entation o f promises /deferred  objects in spired by
  12773    * [Kris K owal's Q]( https://gi thub.com/k riskowal/q ).
  12774    *
  12775    * $q can  be used in  two fashi ons --- on e which is  more simi lar to Kri s Kowal's  Q or jQuer y's Deferr ed
  12776    * impleme ntations,  and the ot her which  resembles  ES6 promis es to some  degree.
  12777    *
  12778    * # $q co nstructor
  12779    *
  12780    * The str eamlined E S6 style p romise is  essentiall y just usi ng $q as a  construct or which t akes a `re solver`
  12781    * functio n as the f irst argum ent. This  is similar  to the na tive Promi se impleme ntation fr om ES6 Har mony,
  12782    * see [MD N](https:/ /developer .mozilla.o rg/en-US/d ocs/Web/Ja vaScript/R eference/G lobal_Obje cts/Promis e).
  12783    *
  12784    * While t he constru ctor-style  use is su pported, n ot all of  the suppor ting metho ds from ES 6 Harmony  promises a re
  12785    * availab le yet.
  12786    *
  12787    * It can  be used li ke so:
  12788    *
  12789    * ```js
  12790    *   // fo r the purp ose of thi s example  let's assu me that va riables `$ q` and `ok ToGreet`
  12791    *   // ar e availabl e in the c urrent lex ical scope  (they cou ld have be en injecte d or passe d in).
  12792    *
  12793    *   funct ion asyncG reet(name)  {
  12794    *     //  perform so me asynchr onous oper ation, res olve or re ject the p romise whe n appropri ate.
  12795    *     ret urn $q(fun ction(reso lve, rejec t) {
  12796    *       s etTimeout( function()  {
  12797    *          if (okToG reet(name) ) {
  12798    *            resolve ('Hello, '  + name +  '!');
  12799    *          } else {
  12800    *            reject( 'Greeting  ' + name +  ' is not  allowed.') ;
  12801    *          }
  12802    *       } , 1000);
  12803    *     });
  12804    *   }
  12805    *
  12806    *   var p romise = a syncGreet( 'Robin Hoo d');
  12807    *   promi se.then(fu nction(gre eting) {
  12808    *     ale rt('Succes s: ' + gre eting);
  12809    *   }, fu nction(rea son) {
  12810    *     ale rt('Failed : ' + reas on);
  12811    *   });
  12812    * ```
  12813    *
  12814    * Note: p rogress/no tify callb acks are n ot current ly support ed via the  ES6-style  interface .
  12815    *
  12816    * However , the more  tradition al CommonJ S-style us age is sti ll availab le, and do cumented b elow.
  12817    *
  12818    * [The Co mmonJS Pro mise propo sal](http: //wiki.com monjs.org/ wiki/Promi ses) descr ibes a pro mise as an
  12819    * interfa ce for int eracting w ith an obj ect that r epresents  the result  of an act ion that i s
  12820    * perform ed asynchr onously, a nd may or  may not be  finished  at any giv en point i n time.
  12821    *
  12822    * From th e perspect ive of dea ling with  error hand ling, defe rred and p romise API s are to
  12823    * asynchr onous prog ramming wh at `try`,  `catch` an d `throw`  keywords a re to sync hronous pr ogramming.
  12824    *
  12825    * ```js
  12826    *   // fo r the purp ose of thi s example  let's assu me that va riables `$ q` and `ok ToGreet`
  12827    *   // ar e availabl e in the c urrent lex ical scope  (they cou ld have be en injecte d or passe d in).
  12828    *
  12829    *   funct ion asyncG reet(name)  {
  12830    *     var  deferred  = $q.defer ();
  12831    *
  12832    *     set Timeout(fu nction() {
  12833    *       d eferred.no tify('Abou t to greet  ' + name  + '.');
  12834    *
  12835    *       i f (okToGre et(name))  {
  12836    *          deferred. resolve('H ello, ' +  name + '!' );
  12837    *       }  else {
  12838    *          deferred. reject('Gr eeting ' +  name + '  is not all owed.');
  12839    *       }
  12840    *     },  1000);
  12841    *
  12842    *     ret urn deferr ed.promise ;
  12843    *   }
  12844    *
  12845    *   var p romise = a syncGreet( 'Robin Hoo d');
  12846    *   promi se.then(fu nction(gre eting) {
  12847    *     ale rt('Succes s: ' + gre eting);
  12848    *   }, fu nction(rea son) {
  12849    *     ale rt('Failed : ' + reas on);
  12850    *   }, fu nction(upd ate) {
  12851    *     ale rt('Got no tification : ' + upda te);
  12852    *   });
  12853    * ```
  12854    *
  12855    * At firs t it might  not be ob vious why  this extra  complexit y is worth  the troub le. The pa yoff
  12856    * comes i n the way  of guarant ees that p romise and  deferred  APIs make,  see
  12857    * https:/ /github.co m/kriskowa l/uncommon js/blob/ma ster/promi ses/specif ication.md .
  12858    *
  12859    * Additio nally the  promise ap i allows f or composi tion that  is very ha rd to do w ith the
  12860    * traditi onal callb ack ([CPS] (http://en .wikipedia .org/wiki/ Continuati on-passing _style)) a pproach.
  12861    * For mor e on this  please see  the [Q do cumentatio n](https:/ /github.co m/kriskowa l/q) espec ially the
  12862    * section  on serial  or parall el joining  of promis es.
  12863    *
  12864    * # The D eferred AP I
  12865    *
  12866    * A new i nstance of  deferred  is constru cted by ca lling `$q. defer()`.
  12867    *
  12868    * The pur pose of th e deferred  object is  to expose  the assoc iated Prom ise instan ce as well  as APIs
  12869    * that ca n be used  for signal ing the su ccessful o r unsucces sful compl etion, as  well as th e status
  12870    * of the  task.
  12871    *
  12872    * **Metho ds**
  12873    *
  12874    * - `reso lve(value) ` â€“ reso lves the d erived pro mise with  the `value `. If the  value is a  rejection
  12875    *   const ructed via  `$q.rejec t`, the pr omise will  be reject ed instead .
  12876    * - `reje ct(reason) ` â€“ reje cts the de rived prom ise with t he `reason `. This is  equivalen t to
  12877    *   resol ving it wi th a rejec tion const ructed via  `$q.rejec t`.
  12878    * - `noti fy(value)`  - provide s updates  on the sta tus of the  promise's  execution . This may  be called
  12879    *   multi ple times  before the  promise i s either r esolved or  rejected.
  12880    *
  12881    * **Prope rties**
  12882    *
  12883    * - promi se â€“ `{P romise}` â €“ promise  object as sociated w ith this d eferred.
  12884    *
  12885    *
  12886    * # The P romise API
  12887    *
  12888    * A new p romise ins tance is c reated whe n a deferr ed instanc e is creat ed and can  be retrie ved by
  12889    * calling  `deferred .promise`.
  12890    *
  12891    * The pur pose of th e promise  object is  to allow f or interes ted partie s to get a ccess to t he result
  12892    * of the  deferred t ask when i t complete s.
  12893    *
  12894    * **Metho ds**
  12895    *
  12896    * - `then (successCa llback, er rorCallbac k, notifyC allback)`  – regard less of wh en the pro mise was o r
  12897    *   will  be resolve d or rejec ted, `then ` calls on e of the s uccess or  error call backs asyn chronously
  12898    *   as so on as the  result is  available.  The callb acks are c alled with  a single  argument:  the result
  12899    *   or re jection re ason. Addi tionally,  the notify  callback  may be cal led zero o r more tim es to
  12900    *   provi de a progr ess indica tion, befo re the pro mise is re solved or  rejected.
  12901    *
  12902    *   This  method *re turns a ne w promise*  which is  resolved o r rejected  via the r eturn valu e of the
  12903    *   `succ essCallbac k`, `error Callback`.  It also n otifies vi a the retu rn value o f the
  12904    *   `noti fyCallback ` method.  The promis e cannot b e resolved  or reject ed from th e notifyCa llback
  12905    *   metho d.
  12906    *
  12907    * - `catc h(errorCal lback)` â€ “ shorthan d for `pro mise.then( null, erro rCallback) `
  12908    *
  12909    * - `fina lly(callba ck, notify Callback)`  â€“ allow s you to o bserve eit her the fu lfillment  or rejecti on of a pr omise,
  12910    *   but t o do so wi thout modi fying the  final valu e. This is  useful to  release r esources o r do some
  12911    *   clean -up that n eeds to be  done whet her the pr omise was  rejected o r resolved . See the  [full
  12912    *   speci fication]( https://gi thub.com/k riskowal/q /wiki/API- Reference# promisefin allycallba ck) for
  12913    *   more  informatio n.
  12914    *
  12915    * # Chain ing promis es
  12916    *
  12917    * Because  calling t he `then`  method of  a promise  returns a  new derive d promise,  it is eas ily
  12918    * possibl e to creat e a chain  of promise s:
  12919    *
  12920    * ```js
  12921    *   promi seB = prom iseA.then( function(r esult) {
  12922    *     ret urn result  + 1;
  12923    *   });
  12924    *
  12925    *   // pr omiseB wil l be resol ved immedi ately afte r promiseA  is resolv ed and its  value
  12926    *   // wi ll be the  result of  promiseA i ncremented  by 1
  12927    * ```
  12928    *
  12929    * It is p ossible to  create ch ains of an y length a nd since a  promise c an be reso lved with  another
  12930    * promise  (which wi ll defer i ts resolut ion furthe r), it is  possible t o pause/de fer resolu tion of
  12931    * the pro mises at a ny point i n the chai n. This ma kes it pos sible to i mplement p owerful AP Is like
  12932    * $http's  response  intercepto rs.
  12933    *
  12934    *
  12935    * # Diffe rences bet ween Kris  Kowal's Q  and $q
  12936    *
  12937    *  There  are two ma in differe nces:
  12938    *
  12939    * - $q is  integrate d with the  {@link ng .$rootScop e.Scope} S cope model  observati on
  12940    *   mecha nism in an gular, whi ch means f aster prop agation of  resolutio n or rejec tion into  your
  12941    *   model s and avoi ding unnec essary bro wser repai nts, which  would res ult in fli ckering UI .
  12942    * - Q has  many more  features  than $q, b ut that co mes at a c ost of byt es. $q is  tiny, but  contains
  12943    *   all t he importa nt functio nality nee ded for co mmon async  tasks.
  12944    *
  12945    *  # Test ing
  12946    *
  12947    *  ```js
  12948    *    it(' should sim ulate prom ise', inje ct(functio n($q, $roo tScope) {
  12949    *      va r deferred  = $q.defe r();
  12950    *      va r promise  = deferred .promise;
  12951    *      va r resolved Value;
  12952    *
  12953    *      pr omise.then (function( value) { r esolvedVal ue = value ; });
  12954    *      ex pect(resol vedValue). toBeUndefi ned();
  12955    *
  12956    *      //  Simulate  resolving  of promise
  12957    *      de ferred.res olve(123);
  12958    *      //  Note that  the 'then ' function  does not  get called  synchrono usly.
  12959    *      //  This is b ecause we  want the p romise API  to always  be async,  whether o r not
  12960    *      //  it got ca lled synch ronously o r asynchro nously.
  12961    *      ex pect(resol vedValue). toBeUndefi ned();
  12962    *
  12963    *      //  Propagate  promise r esolution  to 'then'  functions  using $app ly().
  12964    *      $r ootScope.$ apply();
  12965    *      ex pect(resol vedValue). toEqual(12 3);
  12966    *    }));
  12967    *  ```
  12968    *
  12969    * @param  {function( function,  function)}  resolver  Function w hich is re sponsible  for resolv ing or
  12970    *   rejec ting the n ewly creat ed promise . The firs t paramete r is a fun ction whic h resolves  the
  12971    *   promi se, the se cond param eter is a  function w hich rejec ts the pro mise.
  12972    *
  12973    * @return s {Promise } The newl y created  promise.
  12974    */
  12975   function $ QProvider( ) {
  12976  
  12977     this.$ge t = ['$roo tScope', ' $exception Handler',  function($ rootScope,  $exceptio nHandler)  {
  12978       return  qFactory( function(c allback) {
  12979           $rootScope .$e DNS    ync(callba ck);
  12980       }, $ex ceptionHan dler);
  12981     }];
  12982   }
  12983  
  12984   function $ $QProvider () {
  12985     this.$ge t = ['$bro wser', '$e xceptionHa ndler', fu nction($br owser, $ex ceptionHan dler) {
  12986       return  qFactory( function(c allback) {
  12987         $bro wser.defer (callback) ;
  12988       }, $ex ceptionHan dler);
  12989     }];
  12990   }
  12991  
  12992   /**
  12993    * Constru cts a prom ise manage r.
  12994    *
  12995    * @param  {function( function)}  nextTick  Function f or executi ng functio ns in the  next turn.
  12996    * @param  {function( ...*)} exc eptionHand ler Functi on into wh ich unexpe cted excep tions are  passed for
  12997    *     deb ugging pur poses.
  12998    * @return s {object}  Promise m anager.
  12999    */
  13000   function q Factory(ne xtTick, ex ceptionHan dler) {
  13001     var $qMi nErr = min Err('$q',  TypeError) ;
  13002     function  callOnce( self, reso lveFn, rej ectFn) {
  13003       var ca lled = fal se;
  13004       functi on wrap(fn ) {
  13005         retu rn functio n(value) {
  13006           if  (called)  return;
  13007           ca lled = tru e;
  13008           fn .call(self , value);
  13009         };
  13010       }
  13011  
  13012       return  [wrap(res olveFn), w rap(reject Fn)];
  13013     }
  13014  
  13015     /**
  13016      * @ngdo c method
  13017      * @name  ng.$q#def er
  13018      * @kind  function
  13019      *
  13020      * @desc ription
  13021      * Creat es a `Defe rred` obje ct which r epresents  a task whi ch will fi nish in th e future.
  13022      *
  13023      * @retu rns {Defer red} Retur ns a new i nstance of  deferred.
  13024      */
  13025     var defe r = functi on() {
  13026       return  new Defer red();
  13027     };
  13028  
  13029     function  Promise()  {
  13030       this.$ $state = {  status: 0  };
  13031     }
  13032  
  13033     Promise. prototype  = {
  13034       then:  function(o nFulfilled , onReject ed, progre ssBack) {
  13035         var  result = n ew Deferre d();
  13036  
  13037         this .$$state.p ending = t his.$$stat e.pending  || [];
  13038         this .$$state.p ending.pus h([result,  onFulfill ed, onReje cted, prog ressBack]) ;
  13039         if ( this.$$sta te.status  > 0) sched uleProcess Queue(this .$$state);
  13040  
  13041         retu rn result. promise;
  13042       },
  13043  
  13044       "catch ": functio n(callback ) {
  13045         retu rn this.th en(null, c allback);
  13046       },
  13047  
  13048       "final ly": funct ion(callba ck, progre ssBack) {
  13049         retu rn this.th en(functio n(value) {
  13050           re turn handl eCallback( value, tru e, callbac k);
  13051         }, f unction(er ror) {
  13052           re turn handl eCallback( error, fal se, callba ck);
  13053         }, p rogressBac k);
  13054       }
  13055     };
  13056  
  13057     //Faster , more bas ic than an gular.bind  http://js perf.com/a ngular-bin d-vs-custo m-vs-nativ e
  13058     function  simpleBin d(context,  fn) {
  13059       return  function( value) {
  13060         fn.c all(contex t, value);
  13061       };
  13062     }
  13063  
  13064     function  processQu eue(state)  {
  13065       var fn , promise,  pending;
  13066  
  13067       pendin g = state. pending;
  13068       state. processSch eduled = f alse;
  13069       state. pending =  undefined;
  13070       for (v ar i = 0,  ii = pendi ng.length;  i < ii; + +i) {
  13071         prom ise = pend ing[i][0];
  13072         fn =  pending[i ][state.st atus];
  13073         try  {
  13074           if  (isFuncti on(fn)) {
  13075              promise.re solve(fn(s tate.value ));
  13076           }  else if (s tate.statu s === 1) {
  13077              promise.re solve(stat e.value);
  13078           }  else {
  13079              promise.re ject(state .value);
  13080           }
  13081         } ca tch (e) {
  13082           pr omise.reje ct(e);
  13083           ex ceptionHan dler(e);
  13084         }
  13085       }
  13086     }
  13087  
  13088     function  scheduleP rocessQueu e(state) {
  13089       if (st ate.proces sScheduled  || !state .pending)  return;
  13090       state. processSch eduled = t rue;
  13091       nextTi ck(functio n() { proc essQueue(s tate); });
  13092     }
  13093  
  13094     function  Deferred( ) {
  13095       this.p romise = n ew Promise ();
  13096       //Nece ssary to s upport unb ound execu tion :/
  13097       this.r esolve = s impleBind( this, this .resolve);
  13098       this.r eject = si mpleBind(t his, this. reject);
  13099       this.n otify = si mpleBind(t his, this. notify);
  13100     }
  13101  
  13102     Deferred .prototype  = {
  13103       resolv e: functio n(val) {
  13104         if ( this.promi se.$$state .status) r eturn;
  13105         if ( val === th is.promise ) {
  13106           th is.$$rejec t($qMinErr (
  13107              'qcycle',
  13108              "Expected  promise to  be resolv ed with va lue other  than itsel f '{0}'",
  13109              val));
  13110         }
  13111         else  {
  13112           th is.$$resol ve(val);
  13113         }
  13114  
  13115       },
  13116  
  13117       $$reso lve: funct ion(val) {
  13118         var  then, fns;
  13119  
  13120         fns  = callOnce (this, thi s.$$resolv e, this.$$ reject);
  13121         try  {
  13122           if  ((isObjec t(val) ||  isFunction (val))) th en = val & & val.then ;
  13123           if  (isFuncti on(then))  {
  13124              this.promi se.$$state .status =  -1;
  13125              then.call( val, fns[0 ], fns[1],  this.noti fy);
  13126           }  else {
  13127              this.promi se.$$state .value = v al;
  13128              this.promi se.$$state .status =  1;
  13129              schedulePr ocessQueue (this.prom ise.$$stat e);
  13130           }
  13131         } ca tch (e) {
  13132           fn s[1](e);
  13133           ex ceptionHan dler(e);
  13134         }
  13135       },
  13136  
  13137       reject : function (reason) {
  13138         if ( this.promi se.$$state .status) r eturn;
  13139         this .$$reject( reason);
  13140       },
  13141  
  13142       $$reje ct: functi on(reason)  {
  13143         this .promise.$ $state.val ue = reaso n;
  13144         this .promise.$ $state.sta tus = 2;
  13145         sche duleProces sQueue(thi s.promise. $$state);
  13146       },
  13147  
  13148       notify : function (progress)  {
  13149         var  callbacks  = this.pro mise.$$sta te.pending ;
  13150  
  13151         if ( (this.prom ise.$$stat e.status < = 0) && ca llbacks &&  callbacks .length) {
  13152           ne xtTick(fun ction() {
  13153              var callba ck, result ;
  13154              for (var i  = 0, ii =  callbacks .length; i  < ii; i++ ) {
  13155                result =  callbacks [i][0];
  13156                callback  = callbac ks[i][3];
  13157                try {
  13158                  result .notify(is Function(c allback) ?  callback( progress)  : progress );
  13159                } catch  (e) {
  13160                  except ionHandler (e);
  13161                }
  13162              }
  13163           }) ;
  13164         }
  13165       }
  13166     };
  13167  
  13168     /**
  13169      * @ngdo c method
  13170      * @name  $q#reject
  13171      * @kind  function
  13172      *
  13173      * @desc ription
  13174      * Creat es a promi se that is  resolved  as rejecte d with the  specified  `reason`.  This api  should be
  13175      * used  to forward  rejection  in a chai n of promi ses. If yo u are deal ing with t he last pr omise in
  13176      * a pro mise chain , you don' t need to  worry abou t it.
  13177      *
  13178      * When  comparing  deferreds/ promises t o the fami liar behav ior of try /catch/thr ow, think  of
  13179      * `reje ct` as the  `throw` k eyword in  JavaScript . This als o means th at if you  "catch" an  error via
  13180      * a pro mise error  callback  and you wa nt to forw ard the er ror to the  promise d erived fro m the
  13181      * curre nt promise , you have  to "rethr ow" the er ror by ret urning a r ejection c onstructed  via
  13182      * `reje ct`.
  13183      *
  13184      * ```js
  13185      *   pro miseB = pr omiseA.the n(function (result) {
  13186      *     / / success:  do someth ing and re solve prom iseB
  13187      *     / /           with the  old or a n ew result
  13188      *     r eturn resu lt;
  13189      *   },  function(r eason) {
  13190      *     / / error: h andle the  error if p ossible an d
  13191      *     / /        r esolve pro miseB with  newPromis eOrValue,
  13192      *     / /        o therwise f orward the  rejection  to promis eB
  13193      *     i f (canHand le(reason) ) {
  13194      *       // handle  the error  and recove r
  13195      *       return new PromiseOrV alue;
  13196      *     }
  13197      *     r eturn $q.r eject(reas on);
  13198      *   });
  13199      * ```
  13200      *
  13201      * @para m {*} reas on Constan t, message , exceptio n or an ob ject repre senting th e rejectio n reason.
  13202      * @retu rns {Promi se} Return s a promis e that was  already r esolved as  rejected  with the ` reason`.
  13203      */
  13204     var reje ct = funct ion(reason ) {
  13205       var re sult = new  Deferred( );
  13206       result .reject(re ason);
  13207       return  result.pr omise;
  13208     };
  13209  
  13210     var make Promise =  function m akePromise (value, re solved) {
  13211       var re sult = new  Deferred( );
  13212       if (re solved) {
  13213         resu lt.resolve (value);
  13214       } else  {
  13215         resu lt.reject( value);
  13216       }
  13217       return  result.pr omise;
  13218     };
  13219  
  13220     var hand leCallback  = functio n handleCa llback(val ue, isReso lved, call back) {
  13221       var ca llbackOutp ut = null;
  13222       try {
  13223         if ( isFunction (callback) ) callback Output = c allback();
  13224       } catc h (e) {
  13225         retu rn makePro mise(e, fa lse);
  13226       }
  13227       if (is PromiseLik e(callback Output)) {
  13228         retu rn callbac kOutput.th en(functio n() {
  13229           re turn makeP romise(val ue, isReso lved);
  13230         }, f unction(er ror) {
  13231           re turn makeP romise(err or, false) ;
  13232         });
  13233       } else  {
  13234         retu rn makePro mise(value , isResolv ed);
  13235       }
  13236     };
  13237  
  13238     /**
  13239      * @ngdo c method
  13240      * @name  $q#when
  13241      * @kind  function
  13242      *
  13243      * @desc ription
  13244      * Wraps  an object  that migh t be a val ue or a (3 rd party)  then-able  promise in to a $q pr omise.
  13245      * This  is useful  when you a re dealing  with an o bject that  might or  might not  be a promi se, or if
  13246      * the p romise com es from a  source tha t can't be  trusted.
  13247      *
  13248      * @para m {*} valu e Value or  a promise
  13249      * @retu rns {Promi se} Return s a promis e of the p assed valu e or promi se
  13250      */
  13251  
  13252  
  13253     var when  = functio n(value, c allback, e rrback, pr ogressBack ) {
  13254       var re sult = new  Deferred( );
  13255       result .resolve(v alue);
  13256       return  result.pr omise.then (callback,  errback,  progressBa ck);
  13257     };
  13258  
  13259     /**
  13260      * @ngdo c method
  13261      * @name  $q#all
  13262      * @kind  function
  13263      *
  13264      * @desc ription
  13265      * Combi nes multip le promise s into a s ingle prom ise that i s resolved  when all  of the inp ut
  13266      * promi ses are re solved.
  13267      *
  13268      * @para m {Array.< Promise>|O bject.<Pro mise>} pro mises An a rray or ha sh of prom ises.
  13269      * @retu rns {Promi se} Return s a single  promise t hat will b e resolved  with an a rray/hash  of values,
  13270      *   eac h value co rrespondin g to the p romise at  the same i ndex/key i n the `pro mises` arr ay/hash.
  13271      *   If  any of the  promises  is resolve d with a r ejection,  this resul ting promi se will be  rejected
  13272      *   wit h the same  rejection  value.
  13273      */
  13274  
  13275     function  all(promi ses) {
  13276       var de ferred = n ew Deferre d(),
  13277           co unter = 0,
  13278           re sults = is Array(prom ises) ? []  : {};
  13279  
  13280       forEac h(promises , function (promise,  key) {
  13281         coun ter++;
  13282         when (promise). then(funct ion(value)  {
  13283           if  (results. hasOwnProp erty(key))  return;
  13284           re sults[key]  = value;
  13285           if  (!(--coun ter)) defe rred.resol ve(results );
  13286         }, f unction(re ason) {
  13287           if  (results. hasOwnProp erty(key))  return;
  13288           de ferred.rej ect(reason );
  13289         });
  13290       });
  13291  
  13292       if (co unter ===  0) {
  13293         defe rred.resol ve(results );
  13294       }
  13295  
  13296       return  deferred. promise;
  13297     }
  13298  
  13299     var $Q =  function  Q(resolver ) {
  13300       if (!i sFunction( resolver))  {
  13301         thro w $qMinErr ('norslvr' , "Expecte d resolver Fn, got '{ 0}'", reso lver);
  13302       }
  13303  
  13304       if (!( this insta nceof Q))  {
  13305         // M ore useful  when $Q i s the Prom ise itself .
  13306         retu rn new Q(r esolver);
  13307       }
  13308  
  13309       var de ferred = n ew Deferre d();
  13310  
  13311       functi on resolve Fn(value)  {
  13312         defe rred.resol ve(value);
  13313       }
  13314  
  13315       functi on rejectF n(reason)  {
  13316         defe rred.rejec t(reason);
  13317       }
  13318  
  13319       resolv er(resolve Fn, reject Fn);
  13320  
  13321       return  deferred. promise;
  13322     };
  13323  
  13324     $Q.defer  = defer;
  13325     $Q.rejec t = reject ;
  13326     $Q.when  = when;
  13327     $Q.all =  all;
  13328  
  13329     return $ Q;
  13330   }
  13331  
  13332   function $ $RAFProvid er() { //r AF
  13333     this.$ge t = ['$win dow', '$ti meout', fu nction($wi ndow, $tim eout) {
  13334       var re questAnima tionFrame  = $window. requestAni mationFram e ||
  13335                                      $window. webkitRequ estAnimati onFrame ||
  13336                                      $window. mozRequest AnimationF rame;
  13337  
  13338       var ca ncelAnimat ionFrame =  $window.c ancelAnima tionFrame  ||
  13339                                     $window.w ebkitCance lAnimation Frame ||
  13340                                     $window.m ozCancelAn imationFra me ||
  13341                                     $window.w ebkitCance lRequestAn imationFra me;
  13342  
  13343       var ra fSupported  = !!reque stAnimatio nFrame;
  13344       var ra f = rafSup ported
  13345         ? fu nction(fn)  {
  13346              var id = r equestAnim ationFrame (fn);
  13347              return fun ction() {
  13348                cancelAn imationFra me(id);
  13349              };
  13350           }
  13351         : fu nction(fn)  {
  13352              var timer  = $timeout (fn, 16.66 , false);  // 1000 /  60 = 16.66 6
  13353              return fun ction() {
  13354                $timeout .cancel(ti mer);
  13355              };
  13356           };
  13357  
  13358       raf.su pported =  rafSupport ed;
  13359  
  13360       return  raf;
  13361     }];
  13362   }
  13363  
  13364   /**
  13365    * DESIGN  NOTES
  13366    *
  13367    * The des ign decisi ons behind  the scope  are heavi ly favored  for speed  and memor y consumpt ion.
  13368    *
  13369    * The typ ical use o f scope is  to watch  the expres sions, whi ch most of  the time  return the  same
  13370    * value a s last tim e so we op timize the  operation .
  13371    *
  13372    * Closure s construc tion is ex pensive in  terms of  speed as w ell as mem ory:
  13373    *   - No  closures,  instead us e prototyp ical inher itance for  API
  13374    *   - Int ernal stat e needs to  be stored  on scope  directly,  which mean s that pri vate state  is
  13375    *     exp osed as $$ ____ prope rties
  13376    *
  13377    * Loop op erations a re optimiz ed by usin g while(co unt--) { . .. }
  13378    *   - thi s means th at in orde r to keep  the same o rder of ex ecution as  addition  we have to  add
  13379    *     ite ms to the  array at t he beginni ng (unshif t) instead  of at the  end (push )
  13380    *
  13381    * Child s copes are  created an d removed  often
  13382    *   - Usi ng an arra y would be  slow sinc e inserts  in middle  are expens ive so we  use linked  list
  13383    *
  13384    * There a re few wat ches then  a lot of o bservers.  This is wh y you don' t want the  observer  to be
  13385    * impleme nted in th e same way  as watch.  Watch req uires retu rn of init ialization  function  which
  13386    * are exp ensive to  construct.
  13387    */
  13388  
  13389  
  13390   /**
  13391    * @ngdoc  provider
  13392    * @name $ rootScopeP rovider
  13393    * @descri ption
  13394    *
  13395    * Provide r for the  $rootScope  service.
  13396    */
  13397  
  13398   /**
  13399    * @ngdoc  method
  13400    * @name $ rootScopeP rovider#di gestTtl
  13401    * @descri ption
  13402    *
  13403    * Sets th e number o f `$digest ` iteratio ns the sco pe should  attempt to  execute b efore givi ng up and
  13404    * assumin g that the  model is  unstable.
  13405    *
  13406    * The cur rent defau lt is 10 i terations.
  13407    *
  13408    * In comp lex applic ations it' s possible  that the  dependenci es between  `$watch`s  will resu lt in
  13409    * several  digest it erations.  However if  an applic ation need s more tha n the defa ult 10 dig est
  13410    * iterati ons for it s model to  stabilize  then you  should inv estigate w hat is cau sing the m odel to
  13411    * continu ously chan ge during  the digest .
  13412    *
  13413    * Increas ing the TT L could ha ve perform ance impli cations, s o you shou ld not cha nge it wit hout
  13414    * proper  justificat ion.
  13415    *
  13416    * @param  {number} l imit The n umber of d igest iter ations.
  13417    */
  13418  
  13419  
  13420   /**
  13421    * @ngdoc  service
  13422    * @name $ rootScope
  13423    * @descri ption
  13424    *
  13425    * Every a pplication  has a sin gle root { @link ng.$ rootScope. Scope scop e}.
  13426    * All oth er scopes  are descen dant scope s of the r oot scope.  Scopes pr ovide sepa ration
  13427    * between  the model  and the v iew, via a  mechanism  for watch ing the mo del for ch anges.
  13428    * They al so provide  an event  emission/b roadcast a nd subscri ption faci lity. See  the
  13429    * {@link  guide/scop e develope r guide on  scopes}.
  13430    */
  13431   function $ RootScopeP rovider()  {
  13432     var TTL  = 10;
  13433     var $roo tScopeMinE rr = minEr r('$rootSc ope');
  13434     var last DirtyWatch  = null;
  13435     var appl yAsyncId =  null;
  13436  
  13437     this.dig estTtl = f unction(va lue) {
  13438       if (ar guments.le ngth) {
  13439         TTL  = value;
  13440       }
  13441       return  TTL;
  13442     };
  13443  
  13444     this.$ge t = ['$inj ector', '$ exceptionH andler', ' $parse', ' $browser',
  13445         func tion($inje ctor, $exc eptionHand ler, $pars e, $browse r) {
  13446  
  13447       /**
  13448        * @ng doc type
  13449        * @na me $rootSc ope.Scope
  13450        *
  13451        * @de scription
  13452        * A r oot scope  can be ret rieved usi ng the {@l ink ng.$ro otScope $r ootScope}  key from t he
  13453        * {@l ink auto.$ injector $ injector}.  Child sco pes are cr eated usin g the
  13454        * {@l ink ng.$ro otScope.Sc ope#$new $ new()} met hod. (Most  scopes ar e created  automatica lly when
  13455        * com piled HTML  template  is execute d.)
  13456        *
  13457        * Her e is a sim ple scope  snippet to  show how  you can in teract wit h the scop e.
  13458        * ``` html
  13459        * <fi le src="./ test/ng/ro otScopeSpe c.js" tag= "docs1" />
  13460        * ```
  13461        *
  13462        * # I nheritance
  13463        * A s cope can i nherit fro m a parent  scope, as  in this e xample:
  13464        * ``` js
  13465            v ar parent  = $rootSco pe;
  13466            v ar child =  parent.$n ew();
  13467  
  13468            p arent.salu tation = " Hello";
  13469            c hild.name  = "World";
  13470            e xpect(chil d.salutati on).toEqua l('Hello') ;
  13471  
  13472            c hild.salut ation = "W elcome";
  13473            e xpect(chil d.salutati on).toEqua l('Welcome ');
  13474            e xpect(pare nt.salutat ion).toEqu al('Hello' );
  13475        * ```
  13476        *
  13477        * Whe n interact ing with ` Scope` in  tests, add itional he lper metho ds are ava ilable on  the
  13478        * ins tances of  `Scope` ty pe. See {@ link ngMoc k.$rootSco pe.Scope n gMock Scop e} for add itional
  13479        * det ails.
  13480        *
  13481        *
  13482        * @pa ram {Objec t.<string,  function( )>=} provi ders Map o f service  factory wh ich need t o be
  13483        *                                           provi ded for th e current  scope. Def aults to { @link ng}.
  13484        * @pa ram {Objec t.<string,  *>=} inst anceCache  Provides p re-instant iated serv ices which  should
  13485        *                                 appe nd/overrid e services  provided  by `provid ers`. This  is handy
  13486        *                                 when  unit-test ing and ha ving the n eed to ove rride a de fault
  13487        *                                 serv ice.
  13488        * @re turns {Obj ect} Newly  created s cope.
  13489        *
  13490        */
  13491       functi on Scope()  {
  13492         this .$id = nex tUid();
  13493         this .$$phase =  this.$par ent = this .$$watcher s =
  13494                          this.$$ne xtSibling  = this.$$p revSibling  =
  13495                          this.$$ch ildHead =  this.$$chi ldTail = n ull;
  13496         this .$root = t his;
  13497         this .$$destroy ed = false ;
  13498         this .$$listene rs = {};
  13499         this .$$listene rCount = { };
  13500         this .$$isolate Bindings =  null;
  13501       }
  13502  
  13503       /**
  13504        * @ng doc proper ty
  13505        * @na me $rootSc ope.Scope# $id
  13506        *
  13507        * @de scription
  13508        * Uni que scope  ID (monoto nically in creasing)  useful for  debugging .
  13509        */
  13510  
  13511        /**
  13512         * @n gdoc prope rty
  13513         * @n ame $rootS cope.Scope #$parent
  13514         *
  13515         * @d escription
  13516         * Re ference to  the paren t scope.
  13517         */
  13518  
  13519         /**
  13520          * @ ngdoc prop erty
  13521          * @ name $root Scope.Scop e#$root
  13522          *
  13523          * @ descriptio n
  13524          * R eference t o the root  scope.
  13525          */
  13526  
  13527       Scope. prototype  = {
  13528         cons tructor: S cope,
  13529         /**
  13530          * @ ngdoc meth od
  13531          * @ name $root Scope.Scop e#$new
  13532          * @ kind funct ion
  13533          *
  13534          * @ descriptio n
  13535          * C reates a n ew child { @link ng.$ rootScope. Scope scop e}.
  13536          *
  13537          * T he parent  scope will  propagate  the {@lin k ng.$root Scope.Scop e#$digest  $digest()}  event.
  13538          * T he scope c an be remo ved from t he scope h ierarchy u sing {@lin k ng.$root Scope.Scop e#$destroy  $destroy( )}.
  13539          *
  13540          * { @link ng.$ rootScope. Scope#$des troy $dest roy()} mus t be calle d on a sco pe when it  is
  13541          * d esired for  the scope  and its c hild scope s to be pe rmanently  detached f rom the pa rent and
  13542          * t hus stop p articipati ng in mode l change d etection a nd listene r notifica tion by in voking.
  13543          *
  13544          * @ param {boo lean} isol ate If tru e, then th e scope do es not pro totypicall y inherit  from the
  13545          *          par ent scope.  The scope  is isolat ed, as it  can not se e parent s cope prope rties.
  13546          *          Whe n creating  widgets,  it is usef ul for the  widget to  not accid entally re ad parent
  13547          *          sta te.
  13548          *
  13549          * @ param {Sco pe} [paren t=this] Th e {@link n g.$rootSco pe.Scope ` Scope`} th at will be  the `$par ent`
  13550          *                                 of  the newly  created s cope. Defa ults to `t his` scope  if not pr ovided.
  13551          *                                 Th is is used  when crea ting a tra nsclude sc ope to cor rectly pla ce it
  13552          *                                 in  the scope  hierarchy  while mai ntaining t he correct  prototypi cal
  13553          *                                 in heritance.
  13554          *
  13555          * @ returns {O bject} The  newly cre ated child  scope.
  13556          *
  13557          */
  13558         $new : function (isolate,  parent) {
  13559           va r child;
  13560  
  13561           pa rent = par ent || thi s;
  13562  
  13563           if  (isolate)  {
  13564              child = ne w Scope();
  13565              child.$roo t = this.$ root;
  13566           }  else {
  13567              // Only cr eate a chi ld scope c lass if so mebody ask s for one,
  13568              // but cac he it to a llow the V M to optim ize lookup s.
  13569              if (!this. $$ChildSco pe) {
  13570                this.$$C hildScope  = function  ChildScop e() {
  13571                  this.$ $watchers  = this.$$n extSibling  =
  13572                      th is.$$child Head = thi s.$$childT ail = null ;
  13573                  this.$ $listeners  = {};
  13574                  this.$ $listenerC ount = {};
  13575                  this.$ id = nextU id();
  13576                  this.$ $ChildScop e = null;
  13577                };
  13578                this.$$C hildScope. prototype  = this;
  13579              }
  13580              child = ne w this.$$C hildScope( );
  13581           }
  13582           ch ild.$paren t = parent ;
  13583           ch ild.$$prev Sibling =  parent.$$c hildTail;
  13584           if  (parent.$ $childHead ) {
  13585              parent.$$c hildTail.$ $nextSibli ng = child ;
  13586              parent.$$c hildTail =  child;
  13587           }  else {
  13588              parent.$$c hildHead =  parent.$$ childTail  = child;
  13589           }
  13590  
  13591           //  When the  new scope  is not iso lated or w e inherit  from `this `, and
  13592           //  the paren t scope is  destroyed , the prop erty `$$de stroyed` i s inherite d
  13593           //  prototypi cally. In  all other  cases, thi s property  needs to  be set
  13594           //  when the  parent sco pe is dest royed.
  13595           //  The liste ner needs  to be adde d after th e parent i s set
  13596           if  (isolate  || parent  != this) c hild.$on(' $destroy',  destroyCh ild);
  13597  
  13598           re turn child ;
  13599  
  13600           fu nction des troyChild( ) {
  13601              child.$$de stroyed =  true;
  13602           }
  13603         },
  13604  
  13605         /**
  13606          * @ ngdoc meth od
  13607          * @ name $root Scope.Scop e#$watch
  13608          * @ kind funct ion
  13609          *
  13610          * @ descriptio n
  13611          * R egisters a  `listener ` callback  to be exe cuted when ever the ` watchExpre ssion` cha nges.
  13612          *
  13613          * -  The `watc hExpressio n` is call ed on ever y call to  {@link ng. $rootScope .Scope#$di gest
  13614          *    $digest() } and shou ld return  the value  that will  be watched . (Since
  13615          *    {@link ng .$rootScop e.Scope#$d igest $dig est()} rer uns when i t detects  changes th e
  13616          *    `watchExp ression` c an execute  multiple  times per
  13617          *    {@link ng .$rootScop e.Scope#$d igest $dig est()} and  should be  idempoten t.)
  13618          * -  The `list ener` is c alled only  when the  value from  the curre nt `watchE xpression`  and the
  13619          *    previous  call to `w atchExpres sion` are  not equal  (with the  exception  of the ini tial run,
  13620          *    see below ). Inequal ity is det ermined ac cording to  reference  inequalit y,
  13621          *    [strict c omparison] (https://d eveloper.m ozilla.org /en-US/doc s/Web/Java Script/Ref erence/Ope rators/Com parison_Op erators)
  13622          *     via the  `!==` Java script ope rator, unl ess `objec tEquality  == true`
  13623          *    (see next  point)
  13624          * -  When `obj ectEqualit y == true` , inequali ty of the  `watchExpr ession` is  determine d
  13625          *    according  to the {@ link angul ar.equals}  function.  To save t he value o f the obje ct for
  13626          *    later com parison, t he {@link  angular.co py} functi on is used . This the refore mea ns that
  13627          *    watching  complex ob jects will  have adve rse memory  and perfo rmance imp lications.
  13628          * -  The watch  `listener ` may chan ge the mod el, which  may trigge r other `l istener`s  to fire.
  13629          *    This is a chieved by  rerunning  the watch ers until  no changes  are detec ted. The r erun
  13630          *    iteration  limit is  10 to prev ent an inf inite loop  deadlock.
  13631          *
  13632          *
  13633          * I f you want  to be not ified when ever {@lin k ng.$root Scope.Scop e#$digest  $digest} i s called,
  13634          * y ou can reg ister a `w atchExpres sion` func tion with  no `listen er`. (Sinc e `watchEx pression`
  13635          * c an execute  multiple  times per  {@link ng. $rootScope .Scope#$di gest $dige st} cycle  when a
  13636          * c hange is d etected, b e prepared  for multi ple calls  to your li stener.)
  13637          *
  13638          * A fter a wat cher is re gistered w ith the sc ope, the ` listener`  fn is call ed asynchr onously
  13639            * (via {@l ink ng.$ro otScope.Sc ope#$e DNS    ync $e DNS    ync}) to i nitialize  the
  13640          * w atcher. In  rare case s, this is  undesirab le because  the liste ner is cal led when t he result
  13641          * o f `watchEx pression`  didn't cha nge. To de tect this  scenario w ithin the  `listener`  fn, you
  13642          * c an compare  the `newV al` and `o ldVal`. If  these two  values ar e identica l (`===`)  then the
  13643          * l istener wa s called d ue to init ialization .
  13644          *
  13645          *
  13646          *
  13647          * #  Example
  13648          * ` ``js
  13649               // let's  assume tha t scope wa s dependen cy injecte d as the $ rootScope
  13650               var scope  = $rootSc ope;
  13651               scope.nam e = 'misko ';
  13652               scope.cou nter = 0;
  13653  
  13654               expect(sc ope.counte r).toEqual (0);
  13655               scope.$wa tch('name' , function (newValue,  oldValue)  {
  13656                 scope.c ounter = s cope.count er + 1;
  13657               });
  13658               expect(sc ope.counte r).toEqual (0);
  13659  
  13660               scope.$di gest();
  13661               // the li stener is  always cal led during  the first  $digest l oop after  it was reg istered
  13662               expect(sc ope.counte r).toEqual (1);
  13663  
  13664               scope.$di gest();
  13665               // but no w it will  not be cal led unless  the value  changes
  13666               expect(sc ope.counte r).toEqual (1);
  13667  
  13668               scope.nam e = 'adam' ;
  13669               scope.$di gest();
  13670               expect(sc ope.counte r).toEqual (2);
  13671  
  13672  
  13673  
  13674               // Using  a function  as a watc hExpressio n
  13675               var food;
  13676               scope.foo dCounter =  0;
  13677               expect(sc ope.foodCo unter).toE qual(0);
  13678               scope.$wa tch(
  13679                 // This  function  returns th e value be ing watche d. It is c alled for  each turn  of the $di gest loop
  13680                 functio n() { retu rn food; } ,
  13681                 // This  is the ch ange liste ner, calle d when the  value ret urned from  the above  function  changes
  13682                 functio n(newValue , oldValue ) {
  13683                   if (  newValue ! == oldValu e ) {
  13684                     //  Only incre ment the c ounter if  the value  changed
  13685                     sco pe.foodCou nter = sco pe.foodCou nter + 1;
  13686                   }
  13687                 }
  13688               );
  13689               // No dig est has be en run so  the counte r will be  zero
  13690               expect(sc ope.foodCo unter).toE qual(0);
  13691  
  13692               // Run th e digest b ut since f ood has no t changed  count will  still be  zero
  13693               scope.$di gest();
  13694               expect(sc ope.foodCo unter).toE qual(0);
  13695  
  13696               // Update  food and  run digest .  Now the  counter w ill increm ent
  13697               food = 'c heeseburge r';
  13698               scope.$di gest();
  13699               expect(sc ope.foodCo unter).toE qual(1);
  13700  
  13701          * ` ``
  13702          *
  13703          *
  13704          *
  13705          * @ param {(fu nction()|s tring)} wa tchExpress ion Expres sion that  is evaluat ed on each
  13706          *     {@link n g.$rootSco pe.Scope#$ digest $di gest} cycl e. A chang e in the r eturn valu e triggers
  13707          *     a call t o the `lis tener`.
  13708          *
  13709          *     - `strin g`: Evalua ted as {@l ink guide/ expression  expressio n}
  13710          *     - `funct ion(scope) `: called  with curre nt `scope`  as a para meter.
  13711          * @ param {fun ction(newV al, oldVal , scope)}  listener C allback ca lled whene ver the va lue
  13712          *     of `watc hExpressio n` changes .
  13713          *
  13714          *     - `newVa l` contain s the curr ent value  of the `wa tchExpress ion`
  13715          *     - `oldVa l` contain s the prev ious value  of the `w atchExpres sion`
  13716          *     - `scope ` refers t o the curr ent scope
  13717          * @ param {boo lean=} obj ectEqualit y Compare  for object  equality  using {@li nk angular .equals} i nstead of
  13718          *      compari ng for ref erence equ ality.
  13719          * @ returns {f unction()}  Returns a  deregistr ation func tion for t his listen er.
  13720          */
  13721         $wat ch: functi on(watchEx p, listene r, objectE quality) {
  13722           va r get = $p arse(watch Exp);
  13723  
  13724           if  (get.$$wa tchDelegat e) {
  13725              return get .$$watchDe legate(thi s, listene r, objectE quality, g et);
  13726           }
  13727           va r scope =  this,
  13728                array =  scope.$$wa tchers,
  13729                watcher  = {
  13730                  fn: li stener,
  13731                  last:  initWatchV al,
  13732                  get: g et,
  13733                  exp: w atchExp,
  13734                  eq: !! objectEqua lity
  13735                };
  13736  
  13737           la stDirtyWat ch = null;
  13738  
  13739           if  (!isFunct ion(listen er)) {
  13740              watcher.fn  = noop;
  13741           }
  13742  
  13743           if  (!array)  {
  13744              array = sc ope.$$watc hers = [];
  13745           }
  13746           //  we use un shift sinc e we use a  while loo p in $dige st for spe ed.
  13747           //  the while  loop read s in rever se order.
  13748           ar ray.unshif t(watcher) ;
  13749  
  13750           re turn funct ion deregi sterWatch( ) {
  13751              arrayRemov e(array, w atcher);
  13752              lastDirtyW atch = nul l;
  13753           };
  13754         },
  13755  
  13756         /**
  13757          * @ ngdoc meth od
  13758          * @ name $root Scope.Scop e#$watchGr oup
  13759          * @ kind funct ion
  13760          *
  13761          * @ descriptio n
  13762          * A  variant o f {@link n g.$rootSco pe.Scope#$ watch $wat ch()} wher e it watch es an arra y of `watc hExpressio ns`.
  13763          * I f any one  expression  in the co llection c hanges the  `listener ` is execu ted.
  13764          *
  13765          * -  The items  in the `w atchExpres sions` arr ay are obs erved via  standard $ watch oper ation and  are examin ed on ever y
  13766          *    call to $ digest() t o see if a ny items c hanges.
  13767          * -  The `list ener` is c alled when ever any e xpression  in the `wa tchExpress ions` arra y changes.
  13768          *
  13769          * @ param {Arr ay.<string |Function( scope)>} w atchExpres sions Arra y of expre ssions tha t will be  individual ly
  13770          * w atched usi ng {@link  ng.$rootSc ope.Scope# $watch $wa tch()}
  13771          *
  13772          * @ param {fun ction(newV alues, old Values, sc ope)} list ener Callb ack called  whenever  the return  value of  any
  13773          *     expressi on in `wat chExpressi ons` chang es
  13774          *     The `new Values` ar ray contai ns the cur rent value s of the ` watchExpre ssions`, w ith the in dexes matc hing
  13775          *     those of  `watchExp ression`
  13776          *     and the  `oldValues ` array co ntains the  previous  values of  the `watch Expression s`, with t he indexes  matching
  13777          *     those of  `watchExp ression`
  13778          *     The `sco pe` refers  to the cu rrent scop e.
  13779          * @ returns {f unction()}  Returns a  de-regist ration fun ction for  all listen ers.
  13780          */
  13781         $wat chGroup: f unction(wa tchExpress ions, list ener) {
  13782           va r oldValue s = new Ar ray(watchE xpressions .length);
  13783           va r newValue s = new Ar ray(watchE xpressions .length);
  13784           va r deregist erFns = [] ;
  13785           va r self = t his;
  13786           va r changeRe actionSche duled = fa lse;
  13787           va r firstRun  = true;
  13788  
  13789           if  (!watchEx pressions. length) {
  13790              // No expr essions me ans we cal l the list ener ASAP
  13791              var should Call = tru e;
  13792               self.$e DNS    ync(functi on() {
  13793                if (shou ldCall) li stener(new Values, ne wValues, s elf);
  13794              });
  13795              return fun ction dere gisterWatc hGroup() {
  13796                shouldCa ll = false ;
  13797              };
  13798           }
  13799  
  13800           if  (watchExp ressions.l ength ===  1) {
  13801              // Special  case size  of one
  13802              return thi s.$watch(w atchExpres sions[0],  function w atchGroupA ction(valu e, oldValu e, scope)  {
  13803                newValue s[0] = val ue;
  13804                oldValue s[0] = old Value;
  13805                listener (newValues , (value = == oldValu e) ? newVa lues : old Values, sc ope);
  13806              });
  13807           }
  13808  
  13809           fo rEach(watc hExpressio ns, functi on(expr, i ) {
  13810              var unwatc hFn = self .$watch(ex pr, functi on watchGr oupSubActi on(value,  oldValue)  {
  13811                newValue s[i] = val ue;
  13812                oldValue s[i] = old Value;
  13813                if (!cha ngeReactio nScheduled ) {
  13814                  change ReactionSc heduled =  true;
  13815                    self.$e DNS    ync(watchG roupAction );
  13816                }
  13817              });
  13818              deregister Fns.push(u nwatchFn);
  13819           }) ;
  13820  
  13821           fu nction wat chGroupAct ion() {
  13822              changeReac tionSchedu led = fals e;
  13823  
  13824              if (firstR un) {
  13825                firstRun  = false;
  13826                listener (newValues , newValue s, self);
  13827              } else {
  13828                listener (newValues , oldValue s, self);
  13829              }
  13830           }
  13831  
  13832           re turn funct ion deregi sterWatchG roup() {
  13833              while (der egisterFns .length) {
  13834                deregist erFns.shif t()();
  13835              }
  13836           };
  13837         },
  13838  
  13839  
  13840         /**
  13841          * @ ngdoc meth od
  13842          * @ name $root Scope.Scop e#$watchCo llection
  13843          * @ kind funct ion
  13844          *
  13845          * @ descriptio n
  13846          * S hallow wat ches the p roperties  of an obje ct and fir es wheneve r any of t he propert ies change
  13847          * ( for arrays , this imp lies watch ing the ar ray items;  for objec t maps, th is implies  watching
  13848          * t he propert ies). If a  change is  detected,  the `list ener` call back is fi red.
  13849          *
  13850          * -  The `obj`  collectio n is obser ved via st andard $wa tch operat ion and is  examined  on every
  13851          *    call to $ digest() t o see if a ny items h ave been a dded, remo ved, or mo ved.
  13852          * -  The `list ener` is c alled when ever anyth ing within  the `obj`  has chang ed. Exampl es include
  13853          *    adding, r emoving, a nd moving  items belo nging to a n object o r array.
  13854          *
  13855          *
  13856          * #  Example
  13857          * ` ``js
  13858              $scope.nam es = ['igo r', 'matia s', 'misko ', 'james' ];
  13859              $scope.dat aCount = 4 ;
  13860  
  13861              $scope.$wa tchCollect ion('names ', functio n(newNames , oldNames ) {
  13862                $scope.d ataCount =  newNames. length;
  13863              });
  13864  
  13865              expect($sc ope.dataCo unt).toEqu al(4);
  13866              $scope.$di gest();
  13867  
  13868              //still at  4 ... no  changes
  13869              expect($sc ope.dataCo unt).toEqu al(4);
  13870  
  13871              $scope.nam es.pop();
  13872              $scope.$di gest();
  13873  
  13874              //now ther e's been a  change
  13875              expect($sc ope.dataCo unt).toEqu al(3);
  13876          * ` ``
  13877          *
  13878          *
  13879          * @ param {str ing|functi on(scope)}  obj Evalu ated as {@ link guide /expressio n expressi on}. The
  13880          *     expressi on value s hould eval uate to an  object or  an array  which is o bserved on  each
  13881          *     {@link n g.$rootSco pe.Scope#$ digest $di gest} cycl e. Any sha llow chang e within t he
  13882          *     collecti on will tr igger a ca ll to the  `listener` .
  13883          *
  13884          * @ param {fun ction(newC ollection,  oldCollec tion, scop e)} listen er a callb ack functi on called
  13885          *     when a c hange is d etected.
  13886          *     - The `n ewCollecti on` object  is the ne wly modifi ed data ob tained fro m the `obj ` expressi on
  13887          *     - The `o ldCollecti on` object  is a copy  of the fo rmer colle ction data .
  13888          *       Due to  performan ce conside rations, t he`oldColl ection` va lue is com puted only  if the
  13889          *       `liste ner` funct ion declar es two or  more argum ents.
  13890          *     - The `s cope` argu ment refer s to the c urrent sco pe.
  13891          *
  13892          * @ returns {f unction()}  Returns a  de-regist ration fun ction for  this liste ner. When  the
  13893          *     de-regis tration fu nction is  executed,  the intern al watch o peration i s terminat ed.
  13894          */
  13895         $wat chCollecti on: functi on(obj, li stener) {
  13896           $w atchCollec tionInterc eptor.$sta teful = tr ue;
  13897  
  13898           va r self = t his;
  13899           //  the curre nt value,  updated on  each dirt y-check ru n
  13900           va r newValue ;
  13901           //  a shallow  copy of t he newValu e from the  last dirt y-check ru n,
  13902           //  updated t o match ne wValue dur ing dirty- check run
  13903           va r oldValue ;
  13904           //  a shallow  copy of t he newValu e from whe n the last  change ha ppened
  13905           va r veryOldV alue;
  13906           //  only trac k veryOldV alue if th e listener  is asking  for it
  13907           va r trackVer yOldValue  = (listene r.length >  1);
  13908           va r changeDe tected = 0 ;
  13909           va r changeDe tector = $ parse(obj,  $watchCol lectionInt erceptor);
  13910           va r internal Array = [] ;
  13911           va r internal Object = { };
  13912           va r initRun  = true;
  13913           va r oldLengt h = 0;
  13914  
  13915           fu nction $wa tchCollect ionInterce ptor(_valu e) {
  13916              newValue =  _value;
  13917              var newLen gth, key,  bothNaN, n ewItem, ol dItem;
  13918  
  13919              // If the  new value  is undefin ed, then r eturn unde fined as t he watch m ay be a on e-time wat ch
  13920              if (isUnde fined(newV alue)) ret urn;
  13921  
  13922              if (!isObj ect(newVal ue)) { //  if primiti ve
  13923                if (oldV alue !== n ewValue) {
  13924                  oldVal ue = newVa lue;
  13925                  change Detected++ ;
  13926                }
  13927              } else if  (isArrayLi ke(newValu e)) {
  13928                if (oldV alue !== i nternalArr ay) {
  13929                  // we  are transi tioning fr om somethi ng which w as not an  array into  array.
  13930                  oldVal ue = inter nalArray;
  13931                  oldLen gth = oldV alue.lengt h = 0;
  13932                  change Detected++ ;
  13933                }
  13934  
  13935                newLengt h = newVal ue.length;
  13936  
  13937                if (oldL ength !==  newLength)  {
  13938                  // if  lengths do  not match  we need t o trigger  change not ification
  13939                  change Detected++ ;
  13940                  oldVal ue.length  = oldLengt h = newLen gth;
  13941                }
  13942                // copy  the items  to oldValu e and look  for chang es.
  13943                for (var  i = 0; i  < newLengt h; i++) {
  13944                  oldIte m = oldVal ue[i];
  13945                  newIte m = newVal ue[i];
  13946  
  13947                  bothNa N = (oldIt em !== old Item) && ( newItem != = newItem) ;
  13948                  if (!b othNaN &&  (oldItem ! == newItem )) {
  13949                    chan geDetected ++;
  13950                    oldV alue[i] =  newItem;
  13951                  }
  13952                }
  13953              } else {
  13954                if (oldV alue !== i nternalObj ect) {
  13955                  // we  are transi tioning fr om somethi ng which w as not an  object int o object.
  13956                  oldVal ue = inter nalObject  = {};
  13957                  oldLen gth = 0;
  13958                  change Detected++ ;
  13959                }
  13960                // copy  the items  to oldValu e and look  for chang es.
  13961                newLengt h = 0;
  13962                for (key  in newVal ue) {
  13963                  if (ne wValue.has OwnPropert y(key)) {
  13964                    newL ength++;
  13965                    newI tem = newV alue[key];
  13966                    oldI tem = oldV alue[key];
  13967  
  13968                    if ( key in old Value) {
  13969                      bo thNaN = (o ldItem !==  oldItem)  && (newIte m !== newI tem);
  13970                      if  (!bothNaN  && (oldIt em !== new Item)) {
  13971                         changeDete cted++;
  13972                         oldValue[k ey] = newI tem;
  13973                      }
  13974                    } el se {
  13975                      ol dLength++;
  13976                      ol dValue[key ] = newIte m;
  13977                      ch angeDetect ed++;
  13978                    }
  13979                  }
  13980                }
  13981                if (oldL ength > ne wLength) {
  13982                  // we  used to ha ve more ke ys, need t o find the m and dest roy them.
  13983                  change Detected++ ;
  13984                  for (k ey in oldV alue) {
  13985                    if ( !newValue. hasOwnProp erty(key))  {
  13986                      ol dLength--;
  13987                      de lete oldVa lue[key];
  13988                    }
  13989                  }
  13990                }
  13991              }
  13992              return cha ngeDetecte d;
  13993           }
  13994  
  13995           fu nction $wa tchCollect ionAction( ) {
  13996              if (initRu n) {
  13997                initRun  = false;
  13998                listener (newValue,  newValue,  self);
  13999              } else {
  14000                listener (newValue,  veryOldVa lue, self) ;
  14001              }
  14002  
  14003              // make a  copy for t he next ti me a colle ction is c hanged
  14004              if (trackV eryOldValu e) {
  14005                if (!isO bject(newV alue)) {
  14006                  //prim itive
  14007                  veryOl dValue = n ewValue;
  14008                } else i f (isArray Like(newVa lue)) {
  14009                  veryOl dValue = n ew Array(n ewValue.le ngth);
  14010                  for (v ar i = 0;  i < newVal ue.length;  i++) {
  14011                    very OldValue[i ] = newVal ue[i];
  14012                  }
  14013                } else {  // if obj ect
  14014                  veryOl dValue = { };
  14015                  for (v ar key in  newValue)  {
  14016                    if ( hasOwnProp erty.call( newValue,  key)) {
  14017                      ve ryOldValue [key] = ne wValue[key ];
  14018                    }
  14019                  }
  14020                }
  14021              }
  14022           }
  14023  
  14024           re turn this. $watch(cha ngeDetecto r, $watchC ollectionA ction);
  14025         },
  14026  
  14027         /**
  14028          * @ ngdoc meth od
  14029          * @ name $root Scope.Scop e#$digest
  14030          * @ kind funct ion
  14031          *
  14032          * @ descriptio n
  14033          * P rocesses a ll of the  {@link ng. $rootScope .Scope#$wa tch watche rs} of the  current s cope and
  14034          * i ts childre n. Because  a {@link  ng.$rootSc ope.Scope# $watch wat cher}'s li stener can  change
  14035          * t he model,  the `$dige st()` keep s calling  the {@link  ng.$rootS cope.Scope #$watch wa tchers}
  14036          * u ntil no mo re listene rs are fir ing. This  means that  it is pos sible to g et into an  infinite
  14037          * l oop. This  function w ill throw  `'Maximum  iteration  limit exce eded.'` if  the numbe r of
  14038          * i terations  exceeds 10 .
  14039          *
  14040          * U sually, yo u don't ca ll `$diges t()` direc tly in
  14041          * { @link ng.d irective:n gControlle r controll ers} or in
  14042          * { @link ng.$ compilePro vider#dire ctive dire ctives}.
  14043          * I nstead, yo u should c all {@link  ng.$rootS cope.Scope #$apply $a pply()} (t ypically f rom within
  14044          * a  {@link ng .$compileP rovider#di rective di rective}),  which wil l force a  `$digest() `.
  14045          *
  14046          * I f you want  to be not ified when ever `$dig est()` is  called,
  14047          * y ou can reg ister a `w atchExpres sion` func tion with
  14048          * { @link ng.$ rootScope. Scope#$wat ch $watch( )} with no  `listener `.
  14049          *
  14050          * I n unit tes ts, you ma y need to  call `$dig est()` to  simulate t he scope l ife cycle.
  14051          *
  14052          * #  Example
  14053          * ` ``js
  14054               var scope  = ...;
  14055               scope.nam e = 'misko ';
  14056               scope.cou nter = 0;
  14057  
  14058               expect(sc ope.counte r).toEqual (0);
  14059               scope.$wa tch('name' , function (newValue,  oldValue)  {
  14060                 scope.c ounter = s cope.count er + 1;
  14061               });
  14062               expect(sc ope.counte r).toEqual (0);
  14063  
  14064               scope.$di gest();
  14065               // the li stener is  always cal led during  the first  $digest l oop after  it was reg istered
  14066               expect(sc ope.counte r).toEqual (1);
  14067  
  14068               scope.$di gest();
  14069               // but no w it will  not be cal led unless  the value  changes
  14070               expect(sc ope.counte r).toEqual (1);
  14071  
  14072               scope.nam e = 'adam' ;
  14073               scope.$di gest();
  14074               expect(sc ope.counte r).toEqual (2);
  14075          * ` ``
  14076          *
  14077          */
  14078         $dig est: funct ion() {
  14079           va r watch, v alue, last ,
  14080                watchers ,
  14081                length,
  14082                dirty, t tl = TTL,
  14083                next, cu rrent, tar get = this ,
  14084                watchLog  = [],
  14085                logIdx,  logMsg, as yncTask;
  14086  
  14087           be ginPhase(' $digest');
  14088           //  Check for  changes t o browser  url that h appened in  sync befo re the cal l to $dige st
  14089           $b rowser.$$c heckUrlCha nge();
  14090  
  14091           if  (this ===  $rootScop e && apply AsyncId != = null) {
  14092              // If this  is the ro ot scope,  and $apply Async has  scheduled  a deferred  $apply(),  then
  14093              // cancel  the schedu led $apply  and flush  the queue  of expres sions to b e evaluate d.
  14094              $browser.d efer.cance l(applyAsy ncId);
  14095              flushApply Async();
  14096           }
  14097  
  14098           la stDirtyWat ch = null;
  14099  
  14100           do  { // "whi le dirty"  loop
  14101              dirty = fa lse;
  14102              current =  target;
  14103  
  14104              while (asy ncQueue.le ngth) {
  14105                try {
  14106                  asyncT ask = asyn cQueue.shi ft();
  14107                  asyncT ask.scope. $eval(asyn cTask.expr ession);
  14108                } catch  (e) {
  14109                  $excep tionHandle r(e);
  14110                }
  14111                lastDirt yWatch = n ull;
  14112              }
  14113  
  14114              traverseSc opesLoop:
  14115              do { // "t raverse th e scopes"  loop
  14116                if ((wat chers = cu rrent.$$wa tchers)) {
  14117                  // pro cess our w atches
  14118                  length  = watcher s.length;
  14119                  while  (length--)  {
  14120                    try  {
  14121                      wa tch = watc hers[lengt h];
  14122                      //  Most comm on watches  are on pr imitives,  in which c ase we can  short
  14123                      //  circuit i t with ===  operator,  only when  === fails  do we use  .equals
  14124                      if  (watch) {
  14125                         if ((value  = watch.g et(current )) !== (la st = watch .last) &&
  14126                             !(watc h.eq
  14127                                 ?  equals(val ue, last)
  14128                                 :  (typeof va lue === 'n umber' &&  typeof las t === 'num ber'
  14129                                     && isNaN( value) &&  isNaN(last )))) {
  14130                           dirty =  true;
  14131                           lastDirt yWatch = w atch;
  14132                           watch.la st = watch .eq ? copy (value, nu ll) : valu e;
  14133                           watch.fn (value, (( last === i nitWatchVa l) ? value  : last),  current);
  14134                           if (ttl  < 5) {
  14135                             logIdx  = 4 - ttl ;
  14136                             if (!w atchLog[lo gIdx]) wat chLog[logI dx] = [];
  14137                             watchL og[logIdx] .push({
  14138                               msg:  isFunctio n(watch.ex p) ? 'fn:  ' + (watch .exp.name  || watch.e xp.toStrin g()) : wat ch.exp,
  14139                               newV al: value,
  14140                               oldV al: last
  14141                             });
  14142                           }
  14143                         } else if  (watch ===  lastDirty Watch) {
  14144                           // If th e most rec ently dirt y watcher  is now cle an, short  circuit si nce the re maining wa tchers
  14145                           // have  already be en tested.
  14146                           dirty =  false;
  14147                           break tr averseScop esLoop;
  14148                         }
  14149                      }
  14150                    } ca tch (e) {
  14151                      $e xceptionHa ndler(e);
  14152                    }
  14153                  }
  14154                }
  14155  
  14156                // Insan ity Warnin g: scope d epth-first  traversal
  14157                // yes,  this code  is a bit c razy, but  it works a nd we have  tests to  prove it!
  14158                // this  piece shou ld be kept  in sync w ith the tr aversal in  $broadcas t
  14159                if (!(ne xt = (curr ent.$$chil dHead ||
  14160                    (cur rent !== t arget && c urrent.$$n extSibling )))) {
  14161                  while  (current ! == target  && !(next  = current. $$nextSibl ing)) {
  14162                    curr ent = curr ent.$paren t;
  14163                  }
  14164                }
  14165              } while (( current =  next));
  14166  
  14167              // `break  traverseSc opesLoop;`  takes us  to here
  14168  
  14169              if ((dirty  || asyncQ ueue.lengt h) && !(tt l--)) {
  14170                clearPha se();
  14171                throw $r ootScopeMi nErr('infd ig',
  14172                    '{0}  $digest()  iteration s reached.  Aborting! \n' +
  14173                    'Wat chers fire d in the l ast 5 iter ations: {1 }',
  14174                    TTL,  watchLog) ;
  14175              }
  14176  
  14177           }  while (dir ty || asyn cQueue.len gth);
  14178  
  14179           cl earPhase() ;
  14180  
  14181           wh ile (postD igestQueue .length) {
  14182              try {
  14183                postDige stQueue.sh ift()();
  14184              } catch (e ) {
  14185                $excepti onHandler( e);
  14186              }
  14187           }
  14188         },
  14189  
  14190  
  14191         /**
  14192          * @ ngdoc even t
  14193          * @ name $root Scope.Scop e#$destroy
  14194          * @ eventType  broadcast  on scope b eing destr oyed
  14195          *
  14196          * @ descriptio n
  14197          * B roadcasted  when a sc ope and it s children  are being  destroyed .
  14198          *
  14199          * N ote that,  in Angular JS, there  is also a  `$destroy`  jQuery ev ent, which  can be us ed to
  14200          * c lean up DO M bindings  before an  element i s removed  from the D OM.
  14201          */
  14202  
  14203         /**
  14204          * @ ngdoc meth od
  14205          * @ name $root Scope.Scop e#$destroy
  14206          * @ kind funct ion
  14207          *
  14208          * @ descriptio n
  14209          * R emoves the  current s cope (and  all of its  children)  from the  parent sco pe. Remova l implies
  14210          * t hat calls  to {@link  ng.$rootSc ope.Scope# $digest $d igest()} w ill no lon ger
  14211          * p ropagate t o the curr ent scope  and its ch ildren. Re moval also  implies t hat the cu rrent
  14212          * s cope is el igible for  garbage c ollection.
  14213          *
  14214          * T he `$destr oy()` is u sually use d by direc tives such  as
  14215          * { @link ng.d irective:n gRepeat ng Repeat} fo r managing  the
  14216          * u nrolling o f the loop .
  14217          *
  14218          * J ust before  a scope i s destroye d, a `$des troy` even t is broad casted on  this scope .
  14219          * A pplication  code can  register a  `$destroy ` event ha ndler that  will give  it a chan ce to
  14220          * p erform any  necessary  cleanup.
  14221          *
  14222          * N ote that,  in Angular JS, there  is also a  `$destroy`  jQuery ev ent, which  can be us ed to
  14223          * c lean up DO M bindings  before an  element i s removed  from the D OM.
  14224          */
  14225         $des troy: func tion() {
  14226           //  we can't  destroy th e root sco pe or a sc ope that h as been al ready dest royed
  14227           if  (this.$$d estroyed)  return;
  14228           va r parent =  this.$par ent;
  14229  
  14230           th is.$broadc ast('$dest roy');
  14231           th is.$$destr oyed = tru e;
  14232           if  (this ===  $rootScop e) return;
  14233  
  14234           fo r (var eve ntName in  this.$$lis tenerCount ) {
  14235              decrementL istenerCou nt(this, t his.$$list enerCount[ eventName] , eventNam e);
  14236           }
  14237  
  14238           //  sever all  the refer ences to p arent scop es (after  this clean up, the cu rrent scop e should
  14239           //  not be re tained by  any of our  reference s and shou ld be elig ible for g arbage col lection)
  14240           if  (parent.$ $childHead  == this)  parent.$$c hildHead =  this.$$ne xtSibling;
  14241           if  (parent.$ $childTail  == this)  parent.$$c hildTail =  this.$$pr evSibling;
  14242           if  (this.$$p revSibling ) this.$$p revSibling .$$nextSib ling = thi s.$$nextSi bling;
  14243           if  (this.$$n extSibling ) this.$$n extSibling .$$prevSib ling = thi s.$$prevSi bling;
  14244  
  14245           //  Disable l isteners,  watchers a nd apply/d igest meth ods
  14246             this.$dest roy = this .$digest =  this.$app ly = this. $e DNS    ync = this .$applyAsy nc = noop;
  14247           th is.$on = t his.$watch  = this.$w atchGroup  = function () { retur n noop; };
  14248           th is.$$liste ners = {};
  14249  
  14250           //  All of th e code bel ow is bogu s code tha t works ar ound V8's  memory lea k via opti mized code
  14251           //  and inlin e caches.
  14252           //
  14253           //  see:
  14254           //  - https:/ /code.goog le.com/p/v 8/issues/d etail?id=2 073#c26
  14255           //  - https:/ /github.co m/angular/ angular.js /issues/67 94#issueco mment-3864 8909
  14256           //  - https:/ /github.co m/angular/ angular.js /issues/13 13#issueco mment-1037 8451
  14257  
  14258           th is.$parent  = this.$$ nextSiblin g = this.$ $prevSibli ng = this. $$childHea d =
  14259                this.$$c hildTail =  this.$roo t = this.$ $watchers  = null;
  14260         },
  14261  
  14262         /**
  14263          * @ ngdoc meth od
  14264          * @ name $root Scope.Scop e#$eval
  14265          * @ kind funct ion
  14266          *
  14267          * @ descriptio n
  14268          * E xecutes th e `express ion` on th e current  scope and  returns th e result.  Any except ions in
  14269          * t he express ion are pr opagated ( uncaught).  This is u seful when  evaluatin g Angular
  14270          * e xpressions .
  14271          *
  14272          * #  Example
  14273          * ` ``js
  14274               var scope  = ng.$roo tScope.Sco pe();
  14275               scope.a =  1;
  14276               scope.b =  2;
  14277  
  14278               expect(sc ope.$eval( 'a+b')).to Equal(3);
  14279               expect(sc ope.$eval( function(s cope){ ret urn scope. a + scope. b; })).toE qual(3);
  14280          * ` ``
  14281          *
  14282          * @ param {(st ring|funct ion())=} e xpression  An angular  expressio n to be ex ecuted.
  14283          *
  14284          *     - `strin g`: execut e using th e rules as  defined i n  {@link  guide/expr ession exp ression}.
  14285          *     - `funct ion(scope) `: execute  the funct ion with t he current  `scope` p arameter.
  14286          *
  14287          * @ param {(ob ject)=} lo cals Local  variables  object, u seful for  overriding  values in  scope.
  14288          * @ returns {* } The resu lt of eval uating the  expressio n.
  14289          */
  14290         $eva l: functio n(expr, lo cals) {
  14291           re turn $pars e(expr)(th is, locals );
  14292         },
  14293  
  14294         /**
  14295          * @ ngdoc meth od
  14296            * @name $r ootScope.S cope#$e DNS    ync
  14297          * @ kind funct ion
  14298          *
  14299          * @ descriptio n
  14300          * E xecutes th e expressi on on the  current sc ope at a l ater point  in time.
  14301          *
  14302            * The `$e DNS    ync` makes  no guaran tees as to  when the  `expressio n` will be  executed,  only
  14303          * t hat:
  14304          *
  14305          *    - it will  execute a fter the f unction th at schedul ed the eva luation (p referably  before DOM
  14306          *      renderi ng).
  14307          *    - at leas t one {@li nk ng.$roo tScope.Sco pe#$digest  $digest c ycle} will  be perfor med after
  14308          *      `expres sion` exec ution.
  14309          *
  14310          * A ny excepti ons from t he executi on of the  expression  are forwa rded to th e
  14311          * { @link ng.$ exceptionH andler $ex ceptionHan dler} serv ice.
  14312          *
  14313          * _ _Note:__ i f this fun ction is c alled outs ide of a ` $digest` c ycle, a ne w `$digest ` cycle
  14314          * w ill be sch eduled. Ho wever, it  is encoura ged to alw ays call c ode that c hanges the  model
  14315            * from wit hin an `$a pply` call . That inc ludes code  evaluated  via `$e DNS    ync`.
  14316          *
  14317          * @ param {(st ring|funct ion())=} e xpression  An angular  expressio n to be ex ecuted.
  14318          *
  14319          *     - `strin g`: execut e using th e rules as  defined i n {@link g uide/expre ssion expr ession}.
  14320          *     - `funct ion(scope) `: execute  the funct ion with t he current  `scope` p arameter.
  14321          *
  14322          */
  14323           $e DNS    ync: funct ion(expr)  {
  14324           //  if we are  outside o f an $dige st loop an d this is  the first  time we ar e scheduli ng async
  14325           //  task also  schedule  async auto -flush
  14326           if  (!$rootSc ope.$$phas e && !asyn cQueue.len gth) {
  14327              $browser.d efer(funct ion() {
  14328                if (asyn cQueue.len gth) {
  14329                  $rootS cope.$dige st();
  14330                }
  14331              });
  14332           }
  14333  
  14334           as yncQueue.p ush({scope : this, ex pression:  expr});
  14335         },
  14336  
  14337         $$po stDigest:  function(f n) {
  14338           po stDigestQu eue.push(f n);
  14339         },
  14340  
  14341         /**
  14342          * @ ngdoc meth od
  14343          * @ name $root Scope.Scop e#$apply
  14344          * @ kind funct ion
  14345          *
  14346          * @ descriptio n
  14347          * ` $apply()`  is used to  execute a n expressi on in angu lar from o utside of  the angula r
  14348          * f ramework.  (For examp le from br owser DOM  events, se tTimeout,  XHR or thi rd party l ibraries).
  14349          * B ecause we  are callin g into the  angular f ramework w e need to  perform pr oper scope  life
  14350          * c ycle of {@ link ng.$e xceptionHa ndler exce ption hand ling},
  14351          * { @link ng.$ rootScope. Scope#$dig est execut ing watche s}.
  14352          *
  14353          * # # Life cyc le
  14354          *
  14355          * #  Pseudo-Co de of `$ap ply()`
  14356          * ` ``js
  14357               function  $apply(exp r) {
  14358                 try {
  14359                   retur n $eval(ex pr);
  14360                 } catch  (e) {
  14361                   $exce ptionHandl er(e);
  14362                 } final ly {
  14363                   $root .$digest() ;
  14364                 }
  14365               }
  14366          * ` ``
  14367          *
  14368          *
  14369          * S cope's `$a pply()` me thod trans itions thr ough the f ollowing s tages:
  14370          *
  14371          * 1 . The {@li nk guide/e xpression  expression } is execu ted using  the
  14372          *     {@link n g.$rootSco pe.Scope#$ eval $eval ()} method .
  14373          * 2 . Any exce ptions fro m the exec ution of t he express ion are fo rwarded to  the
  14374          *     {@link n g.$excepti onHandler  $exception Handler} s ervice.
  14375          * 3 . The {@li nk ng.$roo tScope.Sco pe#$watch  watch} lis teners are  fired imm ediately a fter the
  14376          *     expressi on was exe cuted usin g the {@li nk ng.$roo tScope.Sco pe#$digest  $digest() } method.
  14377          *
  14378          *
  14379          * @ param {(st ring|funct ion())=} e xp An angu lar expres sion to be  executed.
  14380          *
  14381          *     - `strin g`: execut e using th e rules as  defined i n {@link g uide/expre ssion expr ession}.
  14382          *     - `funct ion(scope) `: execute  the funct ion with c urrent `sc ope` param eter.
  14383          *
  14384          * @ returns {* } The resu lt of eval uating the  expressio n.
  14385          */
  14386         $app ly: functi on(expr) {
  14387           tr y {
  14388              beginPhase ('$apply') ;
  14389              return thi s.$eval(ex pr);
  14390           }  catch (e)  {
  14391              $exception Handler(e) ;
  14392           }  finally {
  14393              clearPhase ();
  14394              try {
  14395                $rootSco pe.$digest ();
  14396              } catch (e ) {
  14397                $excepti onHandler( e);
  14398                throw e;
  14399              }
  14400           }
  14401         },
  14402  
  14403         /**
  14404          * @ ngdoc meth od
  14405          * @ name $root Scope.Scop e#$applyAs ync
  14406          * @ kind funct ion
  14407          *
  14408          * @ descriptio n
  14409          * S chedule th e invokati on of $app ly to occu r at a lat er time. T he actual  time diffe rence
  14410          * v aries acro ss browser s, but is  typically  around ~10  milliseco nds.
  14411          *
  14412          * T his can be  used to q ueue up mu ltiple exp ressions w hich need  to be eval uated in t he same
  14413          * d igest.
  14414          *
  14415          * @ param {(st ring|funct ion())=} e xp An angu lar expres sion to be  executed.
  14416          *
  14417          *     - `strin g`: execut e using th e rules as  defined i n {@link g uide/expre ssion expr ession}.
  14418          *     - `funct ion(scope) `: execute  the funct ion with c urrent `sc ope` param eter.
  14419          */
  14420         $app lyAsync: f unction(ex pr) {
  14421           va r scope =  this;
  14422           ex pr && appl yAsyncQueu e.push($ap plyAsyncEx pression);
  14423           sc heduleAppl yAsync();
  14424  
  14425           fu nction $ap plyAsyncEx pression()  {
  14426              scope.$eva l(expr);
  14427           }
  14428         },
  14429  
  14430         /**
  14431          * @ ngdoc meth od
  14432          * @ name $root Scope.Scop e#$on
  14433          * @ kind funct ion
  14434          *
  14435          * @ descriptio n
  14436          * L istens on  events of  a given ty pe. See {@ link ng.$r ootScope.S cope#$emit  $emit} fo r
  14437          * d iscussion  of event l ife cycle.
  14438          *
  14439          * T he event l istener fu nction for mat is: `f unction(ev ent, args. ..)`. The  `event` ob ject
  14440          * p assed into  the liste ner has th e followin g attribut es:
  14441          *
  14442          *    - `target Scope` - ` {Scope}`:  the scope  on which t he event w as `$emit` -ed or
  14443          *      `$broad cast`-ed.
  14444          *    - `curren tScope` -  `{Scope}`:  the scope  that is c urrently h andling th e event. O nce the
  14445          *      event p ropagates  through th e scope hi erarchy, t his proper ty is set  to null.
  14446          *    - `name`  - `{string }`: name o f the even t.
  14447          *    - `stopPr opagation`  - `{funct ion=}`: ca lling `sto pPropagati on` functi on will ca ncel
  14448          *      further  event pro pagation ( available  only for e vents that  were `$em it`-ed).
  14449          *    - `preven tDefault`  - `{functi on}`: call ing `preve ntDefault`  sets `def aultPreven ted` flag
  14450          *      to true .
  14451          *    - `defaul tPrevented ` - `{bool ean}`: tru e if `prev entDefault ` was call ed.
  14452          *
  14453          * @ param {str ing} name  Event name  to listen  on.
  14454          * @ param {fun ction(even t, ...args )} listene r Function  to call w hen the ev ent is emi tted.
  14455          * @ returns {f unction()}  Returns a  deregistr ation func tion for t his listen er.
  14456          */
  14457         $on:  function( name, list ener) {
  14458           va r namedLis teners = t his.$$list eners[name ];
  14459           if  (!namedLi steners) {
  14460              this.$$lis teners[nam e] = named Listeners  = [];
  14461           }
  14462           na medListene rs.push(li stener);
  14463  
  14464           va r current  = this;
  14465           do  {
  14466              if (!curre nt.$$liste nerCount[n ame]) {
  14467                current. $$listener Count[name ] = 0;
  14468              }
  14469              current.$$ listenerCo unt[name]+ +;
  14470           }  while ((cu rrent = cu rrent.$par ent));
  14471  
  14472           va r self = t his;
  14473           re turn funct ion() {
  14474              var indexO fListener  = namedLis teners.ind exOf(liste ner);
  14475              if (indexO fListener  !== -1) {
  14476                namedLis teners[ind exOfListen er] = null ;
  14477                decremen tListenerC ount(self,  1, name);
  14478              }
  14479           };
  14480         },
  14481  
  14482  
  14483         /**
  14484          * @ ngdoc meth od
  14485          * @ name $root Scope.Scop e#$emit
  14486          * @ kind funct ion
  14487          *
  14488          * @ descriptio n
  14489          * D ispatches  an event ` name` upwa rds throug h the scop e hierarch y notifyin g the
  14490          * r egistered  {@link ng. $rootScope .Scope#$on } listener s.
  14491          *
  14492          * T he event l ife cycle  starts at  the scope  on which ` $emit` was  called. A ll
  14493          * { @link ng.$ rootScope. Scope#$on  listeners}  listening  for `name ` event on  this scop e get
  14494          * n otified. A fterwards,  the event  traverses  upwards t oward the  root scope  and calls  all
  14495          * r egistered  listeners  along the  way. The e vent will  stop propa gating if  one of the  listeners
  14496          * c ancels it.
  14497          *
  14498          * A ny excepti on emitted  from the  {@link ng. $rootScope .Scope#$on  listeners } will be  passed
  14499          * o nto the {@ link ng.$e xceptionHa ndler $exc eptionHand ler} servi ce.
  14500          *
  14501          * @ param {str ing} name  Event name  to emit.
  14502          * @ param {... *} args Op tional one  or more a rguments w hich will  be passed  onto the e vent liste ners.
  14503          * @ return {Ob ject} Even t object ( see {@link  ng.$rootS cope.Scope #$on}).
  14504          */
  14505         $emi t: functio n(name, ar gs) {
  14506           va r empty =  [],
  14507                namedLis teners,
  14508                scope =  this,
  14509                stopProp agation =  false,
  14510                event =  {
  14511                  name:  name,
  14512                  target Scope: sco pe,
  14513                  stopPr opagation:  function( ) {stopPro pagation =  true;},
  14514                  preven tDefault:  function()  {
  14515                    even t.defaultP revented =  true;
  14516                  },
  14517                  defaul tPrevented : false
  14518                },
  14519                listener Args = con cat([event ], argumen ts, 1),
  14520                i, lengt h;
  14521  
  14522           do  {
  14523              namedListe ners = sco pe.$$liste ners[name]  || empty;
  14524              event.curr entScope =  scope;
  14525              for (i = 0 , length =  namedList eners.leng th; i < le ngth; i++)  {
  14526  
  14527                // if li steners we re deregis tered, def ragment th e array
  14528                if (!nam edListener s[i]) {
  14529                  namedL isteners.s plice(i, 1 );
  14530                  i--;
  14531                  length --;
  14532                  contin ue;
  14533                }
  14534                try {
  14535                  //allo w all list eners atta ched to th e current  scope to r un
  14536                  namedL isteners[i ].apply(nu ll, listen erArgs);
  14537                } catch  (e) {
  14538                  $excep tionHandle r(e);
  14539                }
  14540              }
  14541              //if any l istener on  the curre nt scope s tops propa gation, pr event bubb ling
  14542              if (stopPr opagation)  {
  14543                event.cu rrentScope  = null;
  14544                return e vent;
  14545              }
  14546              //traverse  upwards
  14547              scope = sc ope.$paren t;
  14548           }  while (sco pe);
  14549  
  14550           ev ent.curren tScope = n ull;
  14551  
  14552           re turn event ;
  14553         },
  14554  
  14555  
  14556         /**
  14557          * @ ngdoc meth od
  14558          * @ name $root Scope.Scop e#$broadca st
  14559          * @ kind funct ion
  14560          *
  14561          * @ descriptio n
  14562          * D ispatches  an event ` name` down wards to a ll child s copes (and  their chi ldren) not ifying the
  14563          * r egistered  {@link ng. $rootScope .Scope#$on } listener s.
  14564          *
  14565          * T he event l ife cycle  starts at  the scope  on which ` $broadcast ` was call ed. All
  14566          * { @link ng.$ rootScope. Scope#$on  listeners}  listening  for `name ` event on  this scop e get
  14567          * n otified. A fterwards,  the event  propagate s to all d irect and  indirect s copes of t he current
  14568          * s cope and c alls all r egistered  listeners  along the  way. The e vent canno t be cance led.
  14569          *
  14570          * A ny excepti on emitted  from the  {@link ng. $rootScope .Scope#$on  listeners } will be  passed
  14571          * o nto the {@ link ng.$e xceptionHa ndler $exc eptionHand ler} servi ce.
  14572          *
  14573          * @ param {str ing} name  Event name  to broadc ast.
  14574          * @ param {... *} args Op tional one  or more a rguments w hich will  be passed  onto the e vent liste ners.
  14575          * @ return {Ob ject} Even t object,  see {@link  ng.$rootS cope.Scope #$on}
  14576          */
  14577         $bro adcast: fu nction(nam e, args) {
  14578           va r target =  this,
  14579                current  = target,
  14580                next = t arget,
  14581                event =  {
  14582                  name:  name,
  14583                  target Scope: tar get,
  14584                  preven tDefault:  function()  {
  14585                    even t.defaultP revented =  true;
  14586                  },
  14587                  defaul tPrevented : false
  14588                };
  14589  
  14590           if  (!target. $$listener Count[name ]) return  event;
  14591  
  14592           va r listener Args = con cat([event ], argumen ts, 1),
  14593                listener s, i, leng th;
  14594  
  14595           // down while  you can,  then up an d next sib ling or up  and next  sibling un til back a t root
  14596           wh ile ((curr ent = next )) {
  14597              event.curr entScope =  current;
  14598              listeners  = current. $$listener s[name] ||  [];
  14599              for (i = 0 , length =  listeners .length; i  < length;  i++) {
  14600                // if li steners we re deregis tered, def ragment th e array
  14601                if (!lis teners[i])  {
  14602                  listen ers.splice (i, 1);
  14603                  i--;
  14604                  length --;
  14605                  contin ue;
  14606                }
  14607  
  14608                try {
  14609                  listen ers[i].app ly(null, l istenerArg s);
  14610                } catch  (e) {
  14611                  $excep tionHandle r(e);
  14612                }
  14613              }
  14614  
  14615              // Insanit y Warning:  scope dep th-first t raversal
  14616              // yes, th is code is  a bit cra zy, but it  works and  we have t ests to pr ove it!
  14617              // this pi ece should  be kept i n sync wit h the trav ersal in $ digest
  14618              // (though  it differ s due to h aving the  extra chec k for $$li stenerCoun t)
  14619              if (!(next  = ((curre nt.$$liste nerCount[n ame] && cu rrent.$$ch ildHead) | |
  14620                  (curre nt !== tar get && cur rent.$$nex tSibling)) )) {
  14621                while (c urrent !==  target &&  !(next =  current.$$ nextSiblin g)) {
  14622                  curren t = curren t.$parent;
  14623                }
  14624              }
  14625           }
  14626  
  14627           ev ent.curren tScope = n ull;
  14628           re turn event ;
  14629         }
  14630       };
  14631  
  14632       var $r ootScope =  new Scope ();
  14633  
  14634       //The  internal q ueues. Exp ose them o n the $roo tScope for  debugging /testing p urposes.
  14635       var as yncQueue =  $rootScop e.$$asyncQ ueue = [];
  14636       var po stDigestQu eue = $roo tScope.$$p ostDigestQ ueue = [];
  14637       var ap plyAsyncQu eue = $roo tScope.$$a pplyAsyncQ ueue = [];
  14638  
  14639       return  $rootScop e;
  14640  
  14641  
  14642       functi on beginPh ase(phase)  {
  14643         if ( $rootScope .$$phase)  {
  14644           th row $rootS copeMinErr ('inprog',  '{0} alre ady in pro gress', $r ootScope.$ $phase);
  14645         }
  14646  
  14647         $roo tScope.$$p hase = pha se;
  14648       }
  14649  
  14650       functi on clearPh ase() {
  14651         $roo tScope.$$p hase = nul l;
  14652       }
  14653  
  14654  
  14655       functi on decreme ntListener Count(curr ent, count , name) {
  14656         do {
  14657           cu rrent.$$li stenerCoun t[name] -=  count;
  14658  
  14659           if  (current. $$listener Count[name ] === 0) {
  14660              delete cur rent.$$lis tenerCount [name];
  14661           }
  14662         } wh ile ((curr ent = curr ent.$paren t));
  14663       }
  14664  
  14665       /**
  14666        * fun ction used  as an ini tial value  for watch ers.
  14667        * bec ause it's  unique we  can easily  tell it a part from  other valu es
  14668        */
  14669       functi on initWat chVal() {}
  14670  
  14671       functi on flushAp plyAsync()  {
  14672         whil e (applyAs yncQueue.l ength) {
  14673           tr y {
  14674              applyAsync Queue.shif t()();
  14675           }  catch (e)  {
  14676              $exception Handler(e) ;
  14677           }
  14678         }
  14679         appl yAsyncId =  null;
  14680       }
  14681  
  14682       functi on schedul eApplyAsyn c() {
  14683         if ( applyAsync Id === nul l) {
  14684           ap plyAsyncId  = $browse r.defer(fu nction() {
  14685              $rootScope .$apply(fl ushApplyAs ync);
  14686           }) ;
  14687         }
  14688       }
  14689     }];
  14690   }
  14691  
  14692   /**
  14693    * @descri ption
  14694    * Private  service t o sanitize  uris for  links and  images. Us ed by $com pile and $ sanitize.
  14695    */
  14696   function $ $SanitizeU riProvider () {
  14697     var aHre fSanitizat ionWhiteli st = /^\s* (https?|ft p|mailto|t el|file):/ ,
  14698       imgSrc Sanitizati onWhitelis t = /^\s*( (https?|ft p|file|blo b):|data:i mage\/)/;
  14699  
  14700     /**
  14701      * @desc ription
  14702      * Retri eves or ov errides th e default  regular ex pression t hat is use d for whit elisting o f safe
  14703      * urls  during a[h ref] sanit ization.
  14704      *
  14705      * The s anitizatio n is a sec urity meas ure aimed  at prevent  XSS attac ks via htm l links.
  14706      *
  14707      * Any u rl about t o be assig ned to a[h ref] via d ata-bindin g is first  normalize d and turn ed into
  14708      * an ab solute url . Afterwar ds, the ur l is match ed against  the `aHre fSanitizat ionWhiteli st`
  14709      * regul ar express ion. If a  match is f ound, the  original u rl is writ ten into t he dom. Ot herwise,
  14710      * the a bsolute ur l is prefi xed with ` 'unsafe:'`  string an d only the n is it wr itten into  the DOM.
  14711      *
  14712      * @para m {RegExp= } regexp N ew regexp  to whiteli st urls wi th.
  14713      * @retu rns {RegEx p|ng.$comp ileProvide r} Current  RegExp if  called wi thout valu e or self  for
  14714      *    ch aining oth erwise.
  14715      */
  14716     this.aHr efSanitiza tionWhitel ist = func tion(regex p) {
  14717       if (is Defined(re gexp)) {
  14718         aHre fSanitizat ionWhiteli st = regex p;
  14719         retu rn this;
  14720       }
  14721       return  aHrefSani tizationWh itelist;
  14722     };
  14723  
  14724  
  14725     /**
  14726      * @desc ription
  14727      * Retri eves or ov errides th e default  regular ex pression t hat is use d for whit elisting o f safe
  14728      * urls  during img [src] sani tization.
  14729      *
  14730      * The s anitizatio n is a sec urity meas ure aimed  at prevent  XSS attac ks via htm l links.
  14731      *
  14732      * Any u rl about t o be assig ned to img [src] via  data-bindi ng is firs t normaliz ed and tur ned into
  14733      * an ab solute url . Afterwar ds, the ur l is match ed against  the `imgS rcSanitiza tionWhitel ist`
  14734      * regul ar express ion. If a  match is f ound, the  original u rl is writ ten into t he dom. Ot herwise,
  14735      * the a bsolute ur l is prefi xed with ` 'unsafe:'`  string an d only the n is it wr itten into  the DOM.
  14736      *
  14737      * @para m {RegExp= } regexp N ew regexp  to whiteli st urls wi th.
  14738      * @retu rns {RegEx p|ng.$comp ileProvide r} Current  RegExp if  called wi thout valu e or self  for
  14739      *    ch aining oth erwise.
  14740      */
  14741     this.img SrcSanitiz ationWhite list = fun ction(rege xp) {
  14742       if (is Defined(re gexp)) {
  14743         imgS rcSanitiza tionWhitel ist = rege xp;
  14744         retu rn this;
  14745       }
  14746       return  imgSrcSan itizationW hitelist;
  14747     };
  14748  
  14749     this.$ge t = functi on() {
  14750       return  function  sanitizeUr i(uri, isI mage) {
  14751         var  regex = is Image ? im gSrcSaniti zationWhit elist : aH refSanitiz ationWhite list;
  14752         var  normalized Val;
  14753         norm alizedVal  = urlResol ve(uri).hr ef;
  14754         if ( normalized Val !== ''  && !norma lizedVal.m atch(regex )) {
  14755           re turn 'unsa fe:' + nor malizedVal ;
  14756         }
  14757         retu rn uri;
  14758       };
  14759     };
  14760   }
  14761  
  14762   var $sceMi nErr = min Err('$sce' );
  14763  
  14764   var SCE_CO NTEXTS = {
  14765     HTML: 'h tml',
  14766     CSS: 'cs s',
  14767     URL: 'ur l',
  14768     // RESOU RCE_URL is  a subtype  of URL us ed in cont exts where  a privile ged resour ce is sour ced from a
  14769     // url.   (e.g. ng- include, s cript src,  templateU rl)
  14770     RESOURCE _URL: 'res ourceUrl',
  14771     JS: 'js'
  14772   };
  14773  
  14774   // Helper  functions  follow.
  14775  
  14776   function a djustMatch er(matcher ) {
  14777     if (matc her === 's elf') {
  14778       return  matcher;
  14779     } else i f (isStrin g(matcher) ) {
  14780       // Str ings match  exactly e xcept for  2 wildcard s - '*' an d '**'.
  14781       // '*'  matches a ny charact er except  those from  the set ' :/.?&'.
  14782       // '** ' matches  any charac ter (like  .* in a Re gExp).
  14783       // Mor e than 2 * 's raises  an error a s it's ill  defined.
  14784       if (ma tcher.inde xOf('***')  > -1) {
  14785         thro w $sceMinE rr('iwcard ',
  14786              'Illegal s equence ** * in strin g matcher.   String:  {0}', matc her);
  14787       }
  14788       matche r = escape ForRegexp( matcher).
  14789                      re place('\\* \\*', '.*' ).
  14790                      re place('\\* ', '[^:/.? &;]*');
  14791       return  new RegEx p('^' + ma tcher + '$ ');
  14792     } else i f (isRegEx p(matcher) ) {
  14793       // The  only othe r type of  matcher al lowed is a  Regexp.
  14794       // Mat ch entire  URL / disa llow parti al matches .
  14795       // Fla gs are res et (i.e. n o global,  ignoreCase  or multil ine)
  14796       return  new RegEx p('^' + ma tcher.sour ce + '$');
  14797     } else {
  14798       throw  $sceMinErr ('imatcher ',
  14799           'M atchers ma y only be  "self", st ring patte rns or Reg Exp object s');
  14800     }
  14801   }
  14802  
  14803  
  14804   function a djustMatch ers(matche rs) {
  14805     var adju stedMatche rs = [];
  14806     if (isDe fined(matc hers)) {
  14807       forEac h(matchers , function (matcher)  {
  14808         adju stedMatche rs.push(ad justMatche r(matcher) );
  14809       });
  14810     }
  14811     return a djustedMat chers;
  14812   }
  14813  
  14814  
  14815   /**
  14816    * @ngdoc  service
  14817    * @name $ sceDelegat e
  14818    * @kind f unction
  14819    *
  14820    * @descri ption
  14821    *
  14822    * `$sceDe legate` is  a service  that is u sed by the  `$sce` se rvice to p rovide {@l ink ng.$sc e Strict
  14823    * Context ual Escapi ng (SCE)}  services t o AngularJ S.
  14824    *
  14825    * Typical ly, you wo uld config ure or ove rride the  {@link ng. $sceDelega te $sceDel egate} ins tead of
  14826    * the `$s ce` servic e to custo mize the w ay Strict  Contextual  Escaping  works in A ngularJS.   This is
  14827    * because , while th e `$sce` p rovides nu merous sho rthand met hods, etc. , you real ly only ne ed to
  14828    * overrid e 3 core f unctions ( `trustAs`,  `getTrust ed` and `v alueOf`) t o replace  the way th ings
  14829    * work be cause `$sc e` delegat es to `$sc eDelegate`  for these  operation s.
  14830    *
  14831    * Refer { @link ng.$ sceDelegat eProvider  $sceDelega teProvider } to confi gure this  service.
  14832    *
  14833    * The def ault insta nce of `$s ceDelegate ` should w ork out of  the box w ith little  pain.  Wh ile you
  14834    * can ove rride it c ompletely  to change  the behavi or of `$sc e`, the co mmon case  would
  14835    * involve  configuri ng the {@l ink ng.$sc eDelegateP rovider $s ceDelegate Provider}  instead by  setting
  14836    * your ow n whitelis ts and bla cklists fo r trusting  URLs used  for loadi ng Angular JS resourc es such as
  14837    * templat es.  Refer  {@link ng .$sceDeleg ateProvide r#resource UrlWhiteli st
  14838    * $sceDel egateProvi der.resour ceUrlWhite list} and  {@link
  14839    * ng.$sce DelegatePr ovider#res ourceUrlBl acklist $s ceDelegate Provider.r esourceUrl Blacklist}
  14840    */
  14841  
  14842   /**
  14843    * @ngdoc  provider
  14844    * @name $ sceDelegat eProvider
  14845    * @descri ption
  14846    *
  14847    * The `$s ceDelegate Provider`  provider a llows deve lopers to  configure  the {@link  ng.$sceDe legate
  14848    * $sceDel egate} ser vice.  Thi s allows o ne to get/ set the wh itelists a nd blackli sts used t o ensure
  14849    * that th e URLs use d for sour cing Angul ar templat es are saf e.  Refer  {@link
  14850    * ng.$sce DelegatePr ovider#res ourceUrlWh itelist $s ceDelegate Provider.r esourceUrl Whitelist}  and
  14851    * {@link  ng.$sceDel egateProvi der#resour ceUrlBlack list $sceD elegatePro vider.reso urceUrlBla cklist}
  14852    *
  14853    * For the  general d etails abo ut this se rvice in A ngular, re ad the mai n page for  {@link ng .$sce
  14854    * Strict  Contextual  Escaping  (SCE)}.
  14855    *
  14856    * **Examp le**:  Con sider the  following  case. <a n ame="examp le"></a>
  14857    *
  14858    * - your  app is hos ted at url  `http://m yapp.examp le.com/`
  14859    * - but s ome of you r template s are host ed on othe r domains  you contro l such as
  14860    *   `http ://srv01.a ssets.exam ple.com/`,   `http:/ /srv02.ass ets.exampl e.com/`, e tc.
  14861    * - and y ou have an  open redi rect at `h ttp://myap p.example. com/clickT hru?...`.
  14862    *
  14863    * Here is  what a se cure confi guration f or this sc enario mig ht look li ke:
  14864    *
  14865    * ```
  14866    *  angula r.module(' myApp', [] ).config(f unction($s ceDelegate Provider)  {
  14867    *    $sce DelegatePr ovider.res ourceUrlWh itelist([
  14868    *      //  Allow sam e origin r esource lo ads.
  14869    *      's elf',
  14870    *      //  Allow loa ding from  our assets  domain.   Notice the  differenc e between  * and **.
  14871    *      'h ttp://srv* .assets.ex ample.com/ **'
  14872    *    ]);
  14873    *
  14874    *    // T he blackli st overrid es the whi telist so  the open r edirect he re is bloc ked.
  14875    *    $sce DelegatePr ovider.res ourceUrlBl acklist([
  14876    *      'h ttp://myap p.example. com/clickT hru**'
  14877    *    ]);
  14878    *  });
  14879    * ```
  14880    */
  14881  
  14882   function $ SceDelegat eProvider( ) {
  14883     this.SCE _CONTEXTS  = SCE_CONT EXTS;
  14884  
  14885     // Resou rce URLs c an also be  trusted b y policy.
  14886     var reso urceUrlWhi telist = [ 'self'],
  14887         reso urceUrlBla cklist = [ ];
  14888  
  14889     /**
  14890      * @ngdo c method
  14891      * @name  $sceDeleg ateProvide r#resource UrlWhiteli st
  14892      * @kind  function
  14893      *
  14894      * @para m {Array=}  whitelist  When prov ided, repl aces the r esourceUrl Whitelist  with the v alue
  14895      *     p rovided.   This must  be an arra y or null.   A snapsh ot of this  array is  used so fu rther
  14896      *     c hanges to  the array  are ignore d.
  14897      *
  14898      *     F ollow {@li nk ng.$sce #resourceU rlPatternI tem this l ink} for a  descripti on of the  items
  14899      *     a llowed in  this array .
  14900      *
  14901      *     N ote: **an  empty whit elist arra y will blo ck all URL s**!
  14902      *
  14903      * @retu rn {Array}  the curre ntly set w hitelist a rray.
  14904      *
  14905      * The * *default v alue** whe n no white list has b een explic itly set i s `['self' ]` allowin g only
  14906      * same  origin res ource requ ests.
  14907      *
  14908      * @desc ription
  14909      * Sets/ Gets the w hitelist o f trusted  resource U RLs.
  14910      */
  14911     this.res ourceUrlWh itelist =  function(v alue) {
  14912       if (ar guments.le ngth) {
  14913         reso urceUrlWhi telist = a djustMatch ers(value) ;
  14914       }
  14915       return  resourceU rlWhitelis t;
  14916     };
  14917  
  14918     /**
  14919      * @ngdo c method
  14920      * @name  $sceDeleg ateProvide r#resource UrlBlackli st
  14921      * @kind  function
  14922      *
  14923      * @para m {Array=}  blacklist  When prov ided, repl aces the r esourceUrl Blacklist  with the v alue
  14924      *     p rovided.   This must  be an arra y or null.   A snapsh ot of this  array is  used so fu rther
  14925      *     c hanges to  the array  are ignore d.
  14926      *
  14927      *     F ollow {@li nk ng.$sce #resourceU rlPatternI tem this l ink} for a  descripti on of the  items
  14928      *     a llowed in  this array .
  14929      *
  14930      *     T he typical  usage for  the black list is to  **block
  14931      *     [ open redir ects](http ://cwe.mit re.org/dat a/definiti ons/601.ht ml)** serv ed by your  domain as
  14932      *     t hese would  otherwise  be truste d but actu ally retur n content  from the r edirected  domain.
  14933      *
  14934      *     F inally, ** the blackl ist overri des the wh itelist**  and has th e final sa y.
  14935      *
  14936      * @retu rn {Array}  the curre ntly set b lacklist a rray.
  14937      *
  14938      * The * *default v alue** whe n no white list has b een explic itly set i s the empt y array (i .e. there
  14939      * is no  blacklist .)
  14940      *
  14941      * @desc ription
  14942      * Sets/ Gets the b lacklist o f trusted  resource U RLs.
  14943      */
  14944  
  14945     this.res ourceUrlBl acklist =  function(v alue) {
  14946       if (ar guments.le ngth) {
  14947         reso urceUrlBla cklist = a djustMatch ers(value) ;
  14948       }
  14949       return  resourceU rlBlacklis t;
  14950     };
  14951  
  14952     this.$ge t = ['$inj ector', fu nction($in jector) {
  14953  
  14954       var ht mlSanitize r = functi on htmlSan itizer(htm l) {
  14955         thro w $sceMinE rr('unsafe ', 'Attemp ting to us e an unsaf e value in  a safe co ntext.');
  14956       };
  14957  
  14958       if ($i njector.ha s('$saniti ze')) {
  14959         html Sanitizer  = $injecto r.get('$sa nitize');
  14960       }
  14961  
  14962  
  14963       functi on matchUr l(matcher,  parsedUrl ) {
  14964         if ( matcher == = 'self')  {
  14965           re turn urlIs SameOrigin (parsedUrl );
  14966         } el se {
  14967           //  definitel y a regex.   See adju stMatchers ()
  14968           re turn !!mat cher.exec( parsedUrl. href);
  14969         }
  14970       }
  14971  
  14972       functi on isResou rceUrlAllo wedByPolic y(url) {
  14973         var  parsedUrl  = urlResol ve(url.toS tring());
  14974         var  i, n, allo wed = fals e;
  14975         // E nsure that  at least  one item f rom the wh itelist al lows this  url.
  14976         for  (i = 0, n  = resource UrlWhiteli st.length;  i < n; i+ +) {
  14977           if  (matchUrl (resourceU rlWhitelis t[i], pars edUrl)) {
  14978              allowed =  true;
  14979              break;
  14980           }
  14981         }
  14982         if ( allowed) {
  14983           //  Ensure th at no item  from the  blacklist  blocked th is url.
  14984           fo r (i = 0,  n = resour ceUrlBlack list.lengt h; i < n;  i++) {
  14985              if (matchU rl(resourc eUrlBlackl ist[i], pa rsedUrl))  {
  14986                allowed  = false;
  14987                break;
  14988              }
  14989           }
  14990         }
  14991         retu rn allowed ;
  14992       }
  14993  
  14994       functi on generat eHolderTyp e(Base) {
  14995         var  holderType  = functio n TrustedV alueHolder Type(trust edValue) {
  14996           th is.$$unwra pTrustedVa lue = func tion() {
  14997              return tru stedValue;
  14998           };
  14999         };
  15000         if ( Base) {
  15001           ho lderType.p rototype =  new Base( );
  15002         }
  15003         hold erType.pro totype.val ueOf = fun ction sceV alueOf() {
  15004           re turn this. $$unwrapTr ustedValue ();
  15005         };
  15006         hold erType.pro totype.toS tring = fu nction sce ToString()  {
  15007           re turn this. $$unwrapTr ustedValue ().toStrin g();
  15008         };
  15009         retu rn holderT ype;
  15010       }
  15011  
  15012       var tr ustedValue HolderBase  = generat eHolderTyp e(),
  15013           by Type = {};
  15014  
  15015       byType [SCE_CONTE XTS.HTML]  = generate HolderType (trustedVa lueHolderB ase);
  15016       byType [SCE_CONTE XTS.CSS] =  generateH olderType( trustedVal ueHolderBa se);
  15017       byType [SCE_CONTE XTS.URL] =  generateH olderType( trustedVal ueHolderBa se);
  15018       byType [SCE_CONTE XTS.JS] =  generateHo lderType(t rustedValu eHolderBas e);
  15019       byType [SCE_CONTE XTS.RESOUR CE_URL] =  generateHo lderType(b yType[SCE_ CONTEXTS.U RL]);
  15020  
  15021       /**
  15022        * @ng doc method
  15023        * @na me $sceDel egate#trus tAs
  15024        *
  15025        * @de scription
  15026        * Ret urns an ob ject that  is trusted  by angula r for use  in specifi ed strict
  15027        * con textual es caping con texts (suc h as ng-bi nd-html, n g-include,  any src
  15028        * att ribute int erpolation , any dom  event bind ing attrib ute interp olation
  15029        * suc h as for o nclick,  e tc.) that  uses the p rovided va lue.
  15030        * See  {@link ng .$sce $sce } for enab ling stric t contextu al escapin g.
  15031        *
  15032        * @pa ram {strin g} type Th e kind of  context in  which thi s value is  safe for  use.  e.g.  url,
  15033        *   r esourceUrl , html, js  and css.
  15034        * @pa ram {*} va lue The va lue that t hat should  be consid ered trust ed/safe.
  15035        * @re turns {*}  A value th at can be  used to st and in for  the provi ded `value ` in place s
  15036        * whe re Angular  expects a  $sce.trus tAs() retu rn value.
  15037        */
  15038       functi on trustAs (type, tru stedValue)  {
  15039         var  Constructo r = (byTyp e.hasOwnPr operty(typ e) ? byTyp e[type] :  null);
  15040         if ( !Construct or) {
  15041           th row $sceMi nErr('icon text',
  15042                'Attempt ed to trus t a value  in invalid  context.  Context: { 0}; Value:  {1}',
  15043                type, tr ustedValue );
  15044         }
  15045         if ( trustedVal ue === nul l || trust edValue == = undefine d || trust edValue == = '') {
  15046           re turn trust edValue;
  15047         }
  15048         // A ll the cur rent conte xts in SCE _CONTEXTS  happen to  be strings .  In orde r to avoid  trusting
  15049         // m utable obj ects, we e nsure here  that the  value pass ed in is a ctually a  string.
  15050         if ( typeof tru stedValue  !== 'strin g') {
  15051           th row $sceMi nErr('ityp e',
  15052                'Attempt ed to trus t a non-st ring value  in a cont ent requir ing a stri ng: Contex t: {0}',
  15053                type);
  15054         }
  15055         retu rn new Con structor(t rustedValu e);
  15056       }
  15057  
  15058       /**
  15059        * @ng doc method
  15060        * @na me $sceDel egate#valu eOf
  15061        *
  15062        * @de scription
  15063        * If  the passed  parameter  had been  returned b y a prior  call to {@ link ng.$s ceDelegate #trustAs
  15064        * `$s ceDelegate .trustAs`} , returns  the value  that had b een passed  to {@link
  15065        * ng. $sceDelega te#trustAs  `$sceDele gate.trust As`}.
  15066        *
  15067        * If  the passed  parameter  is not a  value that  had been  returned b y {@link
  15068        * ng. $sceDelega te#trustAs  `$sceDele gate.trust As`}, retu rns it as- is.
  15069        *
  15070        * @pa ram {*} va lue The re sult of a  prior {@li nk ng.$sce Delegate#t rustAs `$s ceDelegate .trustAs`}
  15071        *       call or  anything e lse.
  15072        * @re turns {*}  The `value ` that was  originall y provided  to {@link  ng.$sceDe legate#tru stAs
  15073        *      `$sceDele gate.trust As`} if `v alue` is t he result  of such a  call.  Oth erwise, re turns
  15074        *      `value` u nchanged.
  15075        */
  15076       functi on valueOf (maybeTrus ted) {
  15077         if ( maybeTrust ed instanc eof truste dValueHold erBase) {
  15078           re turn maybe Trusted.$$ unwrapTrus tedValue() ;
  15079         } el se {
  15080           re turn maybe Trusted;
  15081         }
  15082       }
  15083  
  15084       /**
  15085        * @ng doc method
  15086        * @na me $sceDel egate#getT rusted
  15087        *
  15088        * @de scription
  15089        * Tak es the res ult of a { @link ng.$ sceDelegat e#trustAs  `$sceDeleg ate.trustA s`} call a nd
  15090        * ret urns the o riginally  supplied v alue if th e queried  context ty pe is a su pertype of  the
  15091        * cre ated type.   If this  condition  isn't sati sfied, thr ows an exc eption.
  15092        *
  15093        * @pa ram {strin g} type Th e kind of  context in  which thi s value is  to be use d.
  15094        * @pa ram {*} ma ybeTrusted  The resul t of a pri or {@link  ng.$sceDel egate#trus tAs
  15095        *      `$sceDele gate.trust As`} call.
  15096        * @re turns {*}  The value  the was or iginally p rovided to  {@link ng .$sceDeleg ate#trustA s
  15097        *      `$sceDele gate.trust As`} if va lid in thi s context.   Otherwis e, throws  an excepti on.
  15098        */
  15099       functi on getTrus ted(type,  maybeTrust ed) {
  15100         if ( maybeTrust ed === nul l || maybe Trusted == = undefine d || maybe Trusted == = '') {
  15101           re turn maybe Trusted;
  15102         }
  15103         var  constructo r = (byTyp e.hasOwnPr operty(typ e) ? byTyp e[type] :  null);
  15104         if ( constructo r && maybe Trusted in stanceof c onstructor ) {
  15105           re turn maybe Trusted.$$ unwrapTrus tedValue() ;
  15106         }
  15107         // I f we get h ere, then  we may onl y take one  of two ac tions.
  15108         // 1 . sanitize  the value  for the r equested t ype, or
  15109         // 2 . throw an  exception .
  15110         if ( type === S CE_CONTEXT S.RESOURCE _URL) {
  15111           if  (isResour ceUrlAllow edByPolicy (maybeTrus ted)) {
  15112              return may beTrusted;
  15113           }  else {
  15114              throw $sce MinErr('in securl',
  15115                  'Block ed loading  resource  from url n ot allowed  by $sceDe legate pol icy.  URL:  {0}',
  15116                  maybeT rusted.toS tring());
  15117           }
  15118         } el se if (typ e === SCE_ CONTEXTS.H TML) {
  15119           re turn htmlS anitizer(m aybeTruste d);
  15120         }
  15121         thro w $sceMinE rr('unsafe ', 'Attemp ting to us e an unsaf e value in  a safe co ntext.');
  15122       }
  15123  
  15124       return  { trustAs : trustAs,
  15125                 getTrus ted: getTr usted,
  15126                 valueOf : valueOf  };
  15127     }];
  15128   }
  15129  
  15130  
  15131   /**
  15132    * @ngdoc  provider
  15133    * @name $ sceProvide r
  15134    * @descri ption
  15135    *
  15136    * The $sc eProvider  provider a llows deve lopers to  configure  the {@link  ng.$sce $ sce} servi ce.
  15137    * -   ena ble/disabl e Strict C ontextual  Escaping ( SCE) in a  module
  15138    * -   ove rride the  default im plementati on with a  custom del egate
  15139    *
  15140    * Read mo re about { @link ng.$ sce Strict  Contextua l Escaping  (SCE)}.
  15141    */
  15142  
  15143   /* jshint  maxlen: fa lse*/
  15144  
  15145   /**
  15146    * @ngdoc  service
  15147    * @name $ sce
  15148    * @kind f unction
  15149    *
  15150    * @descri ption
  15151    *
  15152    * `$sce`  is a servi ce that pr ovides Str ict Contex tual Escap ing servic es to Angu larJS.
  15153    *
  15154    * # Stric t Contextu al Escapin g
  15155    *
  15156    * Strict  Contextual  Escaping  (SCE) is a  mode in w hich Angul arJS requi res bindin gs in cert ain
  15157    * context s to resul t in a val ue that is  marked as  safe to u se for tha t context.   One exam ple of
  15158    * such a  context is  binding a rbitrary h tml contro lled by th e user via  `ng-bind- html`.  We  refer
  15159    * to thes e contexts  as privil eged or SC E contexts .
  15160    *
  15161    * As of v ersion 1.2 , Angular  ships with  SCE enabl ed by defa ult.
  15162    *
  15163    * Note:   When enabl ed (the de fault), IE <11 in qui rks mode i s not supp orted.  In  this mode , IE<11 al low
  15164    * one to  execute ar bitrary ja vascript b y the use  of the exp ression()  syntax.  R efer
  15165    * <http:/ /blogs.msd n.com/b/ie /archive/2 008/10/16/ ending-exp ressions.a spx> to le arn more a bout them.
  15166    * You can  ensure yo ur documen t is in st andards mo de and not  quirks mo de by addi ng `<!doct ype html>`
  15167    * to the  top of you r HTML doc ument.
  15168    *
  15169    * SCE ass ists in wr iting code  in way th at (a) is  secure by  default an d (b) make s auditing  for
  15170    * securit y vulnerab ilities su ch as XSS,  clickjack ing, etc.  a lot easi er.
  15171    *
  15172    * Here's  an example  of a bind ing in a p rivileged  context:
  15173    *
  15174    * ```
  15175    * <input  ng-model=" userHtml">
  15176    * <div ng -bind-html ="userHtml "></div>
  15177    * ```
  15178    *
  15179    * Notice  that `ng-b ind-html`  is bound t o `userHtm l` control led by the  user.  Wi th SCE
  15180    * disable d, this ap plication  allows the  user to r ender arbi trary HTML  into the  DIV.
  15181    * In a mo re realist ic example , one may  be renderi ng user co mments, bl og article s, etc. vi a
  15182    * binding s.  (HTML  is just on e example  of a conte xt where r endering u ser contro lled input  creates
  15183    * securit y vulnerab ilities.)
  15184    *
  15185    * For the  case of H TML, you m ight use a  library,  either on  the client  side, or  on the ser ver side,
  15186    * to sani tize unsaf e HTML bef ore bindin g to the v alue and r endering i t in the d ocument.
  15187    *
  15188    * How wou ld you ens ure that e very place  that used  these typ es of bind ings was b ound to a  value that
  15189    * was san itized by  your libra ry (or ret urned as s afe for re ndering by  your serv er?)  How  can you
  15190    * ensure  that you d idn't acci dentally d elete the  line that  sanitized  the value,  or rename d some
  15191    * propert ies/fields  and forgo t to updat e the bind ing to the  sanitized  value?
  15192    *
  15193    * To be s ecure by d efault, yo u want to  ensure tha t any such  bindings  are disall owed unles s you can
  15194    * determi ne that so mething ex plicitly s ays it's s afe to use  a value f or binding  in that
  15195    * context .  You can  then audi t your cod e (a simpl e grep wou ld do) to  ensure tha t this is  only done
  15196    * for tho se values  that you c an easily  tell are s afe - beca use they w ere receiv ed from yo ur server,
  15197    * sanitiz ed by your  library,  etc.  You  can organi ze your co debase to  help with  this - per haps
  15198    * allowin g only the  files in  a specific  directory  to do thi s.  Ensuri ng that th e internal  API
  15199    * exposed  by that c ode doesn' t markup a rbitrary v alues as s afe then b ecomes a m ore manage able task.
  15200    *
  15201    * In the  case of An gularJS' S CE service , one uses  {@link ng .$sce#trus tAs $sce.t rustAs}
  15202    * (and sh orthand me thods such  as {@link  ng.$sce#t rustAsHtml  $sce.trus tAsHtml},  etc.) to
  15203    * obtain  values tha t will be  accepted b y SCE / pr ivileged c ontexts.
  15204    *
  15205    *
  15206    * ## How  does it wo rk?
  15207    *
  15208    * In priv ileged con texts, dir ectives an d code wil l bind to  the result  of {@link  ng.$sce#g etTrusted
  15209    * $sce.ge tTrusted(c ontext, va lue)} rath er than to  the value  directly.   Directiv es use {@l ink
  15210    * ng.$sce #parseAs $ sce.parseA s} rather  than `$par se` to wat ch attribu te binding s, which p erforms th e
  15211    * {@link  ng.$sce#ge tTrusted $ sce.getTru sted} behi nd the sce nes on non -constant  literals.
  15212    *
  15213    * As an e xample, {@ link ng.di rective:ng BindHtml n gBindHtml}  uses {@li nk
  15214    * ng.$sce #parseAsHt ml $sce.pa rseAsHtml( binding ex pression)} .  Here's  the actual  code (sli ghtly
  15215    * simplif ied):
  15216    *
  15217    * ```
  15218    * var ngB indHtmlDir ective = [ '$sce', fu nction($sc e) {
  15219    *   retur n function (scope, el ement, att r) {
  15220    *     sco pe.$watch( $sce.parse AsHtml(att r.ngBindHt ml), funct ion(value)  {
  15221    *       e lement.htm l(value ||  '');
  15222    *     });
  15223    *   };
  15224    * }];
  15225    * ```
  15226    *
  15227    * ## Impa ct on load ing templa tes
  15228    *
  15229    * This ap plies both  to the {@ link ng.di rective:ng Include `n g-include` } directiv e as well  as
  15230    * `templa teUrl`'s s pecified b y {@link g uide/direc tive direc tives}.
  15231    *
  15232    * By defa ult, Angul ar only lo ads templa tes from t he same do main and p rotocol as  the appli cation
  15233    * documen t.  This i s done by  calling {@ link ng.$s ce#getTrus tedResourc eUrl
  15234    * $sce.ge tTrustedRe sourceUrl}  on the te mplate URL .  To load  templates  from othe r domains  and/or
  15235    * protoco ls, you ma y either e ither {@li nk ng.$sce DelegatePr ovider#res ourceUrlWh itelist wh itelist
  15236    * them} o r {@link n g.$sce#tru stAsResour ceUrl wrap  it} into  a trusted  value.
  15237    *
  15238    * *Please  note*:
  15239    * The bro wser's
  15240    * [Same O rigin Poli cy](https: //code.goo gle.com/p/ browsersec /wiki/Part 2#Same-ori gin_policy _for_XMLHt tpRequest)
  15241    * and [Cr oss-Origin  Resource  Sharing (C ORS)](http ://www.w3. org/TR/cor s/)
  15242    * policy  apply in a ddition to  this and  may furthe r restrict  whether t he templat e is succe ssfully
  15243    * loaded.   This mea ns that wi thout the  right CORS  policy, l oading tem plates fro m a differ ent domain
  15244    * won't w ork on all  browsers.   Also, lo ading temp lates from  `file://`  URL does  not work o n some
  15245    * browser s.
  15246    *
  15247    * ## This  feels lik e too much  overhead
  15248    *
  15249    * It's im portant to  remember  that SCE o nly applie s to inter polation e xpressions .
  15250    *
  15251    * If your  expressio ns are con stant lite rals, they 're automa tically tr usted and  you don't  need to
  15252    * call `$ sce.trustA s` on them  (remember  to includ e the `ngS anitize` m odule) (e. g.
  15253    * `<div n g-bind-htm l="'<b>imp licitly tr usted</b>' "></div>`)  just work s.
  15254    *
  15255    * Additio nally, `a[ href]` and  `img[src] ` automati cally sani tize their  URLs and  do not pas s them
  15256    * through  {@link ng .$sce#getT rusted $sc e.getTrust ed}.  SCE  doesn't pl ay a role  here.
  15257    *
  15258    * The inc luded {@li nk ng.$sce Delegate $ sceDelegat e} comes w ith sane d efaults to  allow you  to load
  15259    * templat es in `ng- include` f rom your a pplication 's domain  without ha ving to ev en know ab out SCE.
  15260    * It bloc ks loading  templates  from othe r domains  or loading  templates  over http  from an h ttps
  15261    * served  document.   You can c hange thes e by setti ng your ow n custom { @link
  15262    * ng.$sce DelegatePr ovider#res ourceUrlWh itelist wh itelists}  and {@link
  15263    * ng.$sce DelegatePr ovider#res ourceUrlBl acklist bl acklists}  for matchi ng such UR Ls.
  15264    *
  15265    * This si gnificantl y reduces  the overhe ad.  It is  far easie r to pay t he small o verhead an d have an
  15266    * applica tion that' s secure a nd can be  audited to  verify th at with mu ch more ea se than bo lting
  15267    * securit y onto an  applicatio n later.
  15268    *
  15269    * <a name ="contexts "></a>
  15270    * ## What  trusted c ontext typ es are sup ported?
  15271    *
  15272    * | Conte xt              | Not es           |
  15273    * |------ ---------- -----|---- ---------- --|
  15274    * | `$sce .HTML`          | For  HTML that 's safe to  source in to the app lication.   The {@lin k ng.direc tive:ngBin dHtml ngBi ndHtml} di rective us es this co ntext for  bindings.  If an unsa fe value i s encounte red and th e {@link n gSanitize  $sanitize}  module is  present t his will s anitize th e value in stead of t hrowing an  error. |
  15275    * | `$sce .CSS`           | For  CSS that' s safe to  source int o the appl ication.   Currently  unused.  F eel free t o use it i n your own  directive s. |
  15276    * | `$sce .URL`           | For  URLs that  are safe  to follow  as links.   Currently  unused (` <a href=`  and `<img  src=` sani tize their  urls and  don't cons titute an  SCE contex t. |
  15277    * | `$sce .RESOURCE_ URL` | For  URLs that  are not o nly safe t o follow a s links, b ut whose c ontents ar e also saf e to inclu de in your  applicati on.  Examp les includ e `ng-incl ude`, `src ` / `ngSrc ` bindings  for tags  other than  `IMG` (e. g. `IFRAME `, `OBJECT `, etc.)   <br><br>No te that `$ sce.RESOUR CE_URL` ma kes a stro nger state ment about  the URL t han `$sce. URL` does  and theref ore contex ts requiri ng values  trusted fo r `$sce.RE SOURCE_URL ` can be u sed anywhe re that va lues trust ed for `$s ce.URL` ar e required . |
  15278    * | `$sce .JS`            | For  JavaScrip t that is  safe to ex ecute in y our applic ation's co ntext.  Cu rrently un used.  Fee l free to  use it in  your own d irectives.  |
  15279    *
  15280    * ## Form at of item s in {@lin k ng.$sceD elegatePro vider#reso urceUrlWhi telist res ourceUrlWh itelist}/{ @link ng.$ sceDelegat eProvider# resourceUr lBlacklist  Blacklist } <a name= "resourceU rlPatternI tem"></a>
  15281    *
  15282    *  Each e lement in  these arra ys must be  one of th e followin g:
  15283    *
  15284    *  - **'s elf'**
  15285    *    - Th e special  **string** , `'self'` , can be u sed to mat ch against  all URLs  of the **s ame
  15286    *      do main** as  the applic ation docu ment using  the **sam e protocol **.
  15287    *  - **St ring** (ex cept the s pecial val ue `'self' `)
  15288    *    - Th e string i s matched  against th e full *no rmalized /  absolute  URL* of th e resource
  15289    *      be ing tested  (substrin g matches  are not go od enough. )
  15290    *    - Th ere are ex actly **tw o wildcard  sequences ** - `*` a nd `**`.   All other  characters
  15291    *      ma tch themse lves.
  15292    *    - `* `: matches  zero or m ore occurr ences of a ny charact er other t han one of  the follo wing 6
  15293    *      ch aracters:  '`:`', '`/ `', '`.`',  '`?`', '` &`' and '; '.  It's a  useful wi ldcard for  use
  15294    *      in  a whiteli st.
  15295    *    - `* *`: matche s zero or  more occur rences of  *any* char acter.  As  such, it' s not
  15296    *      no t appropri ate to use  in for a  scheme, do main, etc.  as it wou ld match t oo much.   (e.g.
  15297    *      ht tp://**.ex ample.com/  would mat ch http:// evil.com/? ignore=.ex ample.com/  and that  might
  15298    *      no t have bee n the inte ntion.)  I ts usage a t the very  end of th e path is  ok.  (e.g.
  15299    *      ht tp://foo.e xample.com /templates /**).
  15300    *  - **Re gExp** (*s ee caveat  below*)
  15301    *    - *C aveat*:  W hile regul ar express ions are p owerful an d offer gr eat flexib ility,  th eir syntax
  15302    *      (a nd all the  inevitabl e escaping ) makes th em *harder  to mainta in*.  It's  easy to
  15303    *      ac cidentally  introduce  a bug whe n one upda tes a comp lex expres sion (imho , all rege xes should
  15304    *      ha ve good te st coverag e.).  For  instance,  the use of  `.` in th e regex is  correct o nly in a
  15305    *      sm all number  of cases.   A `.` ch aracter in  the regex  used when  matching  the scheme  or a
  15306    *      su bdomain co uld be mat ched again st a `:` o r literal  `.` that w as likely  not intend ed.   It
  15307    *      is  highly re commended  to use the  string pa tterns and  only fall  back to r egular exp ressions
  15308    *      if  they as a  last reso rt.
  15309    *    - Th e regular  expression  must be a n instance  of RegExp  (i.e. not  a string. )  It is
  15310    *      ma tched agai nst the ** entire** * normalized  / absolut e URL* of  the resour ce being t ested
  15311    *      (e ven when t he RegExp  did not ha ve the `^`  and `$` c odes.)  In  addition,  any flags
  15312    *      pr esent on t he RegExp  (such as m ultiline,  global, ig noreCase)  are ignore d.
  15313    *    - If  you are g enerating  your JavaS cript from  some othe r templati ng engine  (not
  15314    *      re commended,  e.g. in i ssue [#400 6](https:/ /github.co m/angular/ angular.js /issues/40 06)),
  15315    *      re member to  escape you r regular  expression  (and be a ware that  you might  need more  than
  15316    *      on e level of  escaping  depending  on your te mplating e ngine and  the way yo u interpol ated
  15317    *      th e value.)   Do make u se of your  platform' s escaping  mechanism  as it mig ht be good
  15318    *      en ough befor e coding y our own.   e.g. Ruby  has
  15319    *      [R egexp.esca pe(str)](h ttp://www. ruby-doc.o rg/core-2. 0.0/Regexp .html#meth od-c-escap e)
  15320    *      an d Python h as [re.esc ape](http: //docs.pyt hon.org/li brary/re.h tml#re.esc ape).
  15321    *      Ja vascript l acks a sim ilar built  in functi on for esc aping.  Ta ke a look  at Google
  15322    *      Cl osure libr ary's [goo g.string.r egExpEscap e(s)](
  15323    *      ht tp://docs. closure-li brary.goog lecode.com /git/closu re_goog_st ring_strin g.js.sourc e.html#lin e962).
  15324    *
  15325    * Refer { @link ng.$ sceDelegat eProvider  $sceDelega teProvider } for an e xample.
  15326    *
  15327    * ## Show  me an exa mple using  SCE.
  15328    *
  15329    * <exampl e module=" mySceApp"  deps="angu lar-saniti ze.js">
  15330    * <file n ame="index .html">
  15331    *   <div  ng-control ler="AppCo ntroller a s myCtrl">
  15332    *     <i  ng-bind-ht ml="myCtrl .explicitl yTrustedHt ml" id="ex plicitlyTr ustedHtml" ></i><br>< br>
  15333    *     <b> User comme nts</b><br >
  15334    *     By  default, H TML that i sn't expli citly trus ted (e.g.  Alice's co mment) is  sanitized  when
  15335    *     $sa nitize is  available.   If $sani tize isn't  available , this res ults in an  error ins tead of an
  15336    *     exp loit.
  15337    *     <di v class="w ell">
  15338    *       < div ng-rep eat="userC omment in  myCtrl.use rComments" >
  15339    *          <b>{{user Comment.na me}}</b>:
  15340    *          <span ng- bind-html= "userComme nt.htmlCom ment" clas s="htmlCom ment"></sp an>
  15341    *          <br>
  15342    *       < /div>
  15343    *     </d iv>
  15344    *   </div >
  15345    * </file>
  15346    *
  15347    * <file n ame="scrip t.js">
  15348    *   angul ar.module( 'mySceApp' , ['ngSani tize'])
  15349    *     .co ntroller(' AppControl ler', ['$h ttp', '$te mplateCach e', '$sce' ,
  15350    *       f unction($h ttp, $temp lateCache,  $sce) {
  15351    *          var self  = this;
  15352    *          $http.get ("test_dat a.json", { cache: $te mplateCach e}).succes s(function (userComme nts) {
  15353    *            self.us erComments  = userCom ments;
  15354    *          });
  15355    *          self.expl icitlyTrus tedHtml =  $sce.trust AsHtml(
  15356    *              '<spa n onmouseo ver="this. textConten t=&quot;Ex plicitly t rusted HTM L bypasses  ' +
  15357    *              'sani tization.& quot;">Hov er over th is text.</ span>');
  15358    *       } ]);
  15359    * </file>
  15360    *
  15361    * <file n ame="test_ data.json" >
  15362    * [
  15363    *   { "na me": "Alic e",
  15364    *     "ht mlComment" :
  15365    *          "<span on mouseover= 'this.text Content=\" PWN3D!\"'> Is <i>anyo ne</i> rea ding this? </span>"
  15366    *   },
  15367    *   { "na me": "Bob" ,
  15368    *     "ht mlComment" : "<i>Yes! </i>  Am I  the only  other one? "
  15369    *   }
  15370    * ]
  15371    * </file>
  15372    *
  15373    * <file n ame="protr actor.js"  type="prot ractor">
  15374    *   descr ibe('SCE d oc demo',  function()  {
  15375    *     it( 'should sa nitize unt rusted val ues', func tion() {
  15376    *       e xpect(elem ent.all(by .css('.htm lComment') ).first(). getInnerHt ml())
  15377    *            .toBe(' <span>Is < i>anyone</ i> reading  this?</sp an>');
  15378    *     });
  15379    *
  15380    *     it( 'should NO T sanitize  explicitl y trusted  values', f unction()  {
  15381    *       e xpect(elem ent(by.id( 'explicitl yTrustedHt ml')).getI nnerHtml() ).toBe(
  15382    *            '<span  onmouseove r="this.te xtContent= &quot;Expl icitly tru sted HTML  bypasses '  +
  15383    *            'saniti zation.&qu ot;">Hover  over this  text.</sp an>');
  15384    *     });
  15385    *   });
  15386    * </file>
  15387    * </examp le>
  15388    *
  15389    *
  15390    *
  15391    * ## Can  I disable  SCE comple tely?
  15392    *
  15393    * Yes, yo u can.  Ho wever, thi s is stron gly discou raged.  SC E gives yo u a lot of  security  benefits
  15394    * for lit tle coding  overhead.   It will  be much ha rder to ta ke an SCE  disabled a pplication  and
  15395    * either  secure it  on your ow n or enabl e SCE at a  later sta ge.  It mi ght make s ense to di sable SCE
  15396    * for cas es where y ou have a  lot of exi sting code  that was  written be fore SCE w as introdu ced and
  15397    * you're  migrating  them a mod ule at a t ime.
  15398    *
  15399    * That sa id, here's  how you c an complet ely disabl e SCE:
  15400    *
  15401    * ```
  15402    * angular .module('m yAppWithSc eDisabledm yApp', []) .config(fu nction($sc eProvider)  {
  15403    *   // Co mpletely d isable SCE .  For dem onstration  purposes  only!
  15404    *   // Do  not use i n new proj ects.
  15405    *   $sceP rovider.en abled(fals e);
  15406    * });
  15407    * ```
  15408    *
  15409    */
  15410   /* jshint  maxlen: 10 0 */
  15411  
  15412   function $ SceProvide r() {
  15413     var enab led = true ;
  15414  
  15415     /**
  15416      * @ngdo c method
  15417      * @name  $sceProvi der#enable d
  15418      * @kind  function
  15419      *
  15420      * @para m {boolean =} value I f provided , then ena bles/disab les SCE.
  15421      * @retu rn {boolea n} true if  SCE is en abled, fal se otherwi se.
  15422      *
  15423      * @desc ription
  15424      * Enabl es/disable s SCE and  returns th e current  value.
  15425      */
  15426     this.ena bled = fun ction(valu e) {
  15427       if (ar guments.le ngth) {
  15428         enab led = !!va lue;
  15429       }
  15430       return  enabled;
  15431     };
  15432  
  15433  
  15434     /* Desig n notes on  the defau lt impleme ntation fo r SCE.
  15435      *
  15436      * The A PI contrac t for the  SCE delega te
  15437      * ----- ---------- ---------- ---------- --
  15438      * The S CE delegat e object m ust provid e the foll owing 3 me thods:
  15439      *
  15440      * - tru stAs(conte xtEnum, va lue)
  15441      *     T his method  is used t o tell the  SCE servi ce that th e provided  value is  OK to use  in the
  15442      *     c ontexts sp ecified by  contextEn um.  It mu st return  an object  that will  be accepte d by
  15443      *     g etTrusted( ) for a co mpatible c ontextEnum  and retur n this val ue.
  15444      *
  15445      * - val ueOf(value )
  15446      *     F or values  that were  not produc ed by trus tAs(), ret urn them a s is.  For  values th at were
  15447      *     p roduced by  trustAs() , return t he corresp onding inp ut value t o trustAs.   Basicall y, if
  15448      *     t rustAs is  wrapping t he given v alues into  some type , this ope ration unw raps it wh en given
  15449      *     s uch a valu e.
  15450      *
  15451      * - get Trusted(co ntextEnum,  value)
  15452      *     T his functi on should  return the  a value t hat is saf e to use i n the cont ext specif ied by
  15453      *     c ontextEnum  or throw  and except ion otherw ise.
  15454      *
  15455      * NOTE:  This cont ract delib erately do es NOT sta te that va lues retur ned by tru stAs() mus t be
  15456      * opaqu e or wrapp ed in some  holder ob ject.  Tha t happens  to be an i mplementat ion detail .  For
  15457      * insta nce, an im plementati on could m aintain a  registry o f all trus ted object s by conte xt.  In
  15458      * such  a case, tr ustAs() wo uld return  the same  object tha t was pass ed in.  ge tTrusted()  would
  15459      * retur n the same  object pa ssed in if  it was fo und in the  registry  under a co mpatible c ontext or
  15460      * throw  an except ion otherw ise.  An i mplementat ion might  only wrap  values som e of the t ime based
  15461      * on so me criteri a.  getTru sted() mig ht return  a value an d not thro w an excep tion for s pecial
  15462      * const ants or ob jects even  if not wr apped.  Al l such imp lementatio ns fulfill  this cont ract.
  15463      *
  15464      *
  15465      * A not e on the i nheritance  model for  SCE conte xts
  15466      * ----- ---------- ---------- ---------- ---------- ---
  15467      * I've  used inher itance and  made RESO URCE_URL w rapped typ es a subty pe of URL  wrapped ty pes.  This
  15468      * is pu rely an im plementati on details .
  15469      *
  15470      * The c ontract is  simply th is:
  15471      *
  15472      *     g etTrusted( $sce.RESOU RCE_URL, v alue) succ eeding imp lies that  getTrusted ($sce.URL,  value)
  15473      *     w ill also s ucceed.
  15474      *
  15475      * Inher itance hap pens to ca pture this  in a natu ral way.   In some fu ture, we
  15476      * may n ot use inh eritance a nymore.  T hat is OK  because no  code outs ide of
  15477      * sce.j s and sceS pecs.js wo uld need t o be aware  of this d etail.
  15478      */
  15479  
  15480     this.$ge t = ['$par se', '$sce Delegate',  function(
  15481                    $par se,   $sce Delegate)  {
  15482       // Pre req: Ensur e that we' re not run ning in IE <11 quirks  mode.  In  that mode , IE < 11  allow
  15483       // the  "expressi on(javascr ipt expres sion)" syn tax which  is insecur e.
  15484       if (en abled && m sie < 8) {
  15485         thro w $sceMinE rr('iequir ks',
  15486           'S trict Cont extual Esc aping does  not suppo rt Interne t Explorer  version <  11 in qui rks ' +
  15487           'm ode.  You  can fix th is by addi ng the tex t <!doctyp e html> to  the top o f your HTM L ' +
  15488           'd ocument.   See http:/ /docs.angu larjs.org/ api/ng.$sc e for more  informati on.');
  15489       }
  15490  
  15491       var sc e = shallo wCopy(SCE_ CONTEXTS);
  15492  
  15493       /**
  15494        * @ng doc method
  15495        * @na me $sce#is Enabled
  15496        * @ki nd functio n
  15497        *
  15498        * @re turn {Bool ean} true  if SCE is  enabled, f alse other wise.  If  you want t o set the  value, you
  15499        * hav e to do it  at module  config ti me on {@li nk ng.$sce Provider $ sceProvide r}.
  15500        *
  15501        * @de scription
  15502        * Ret urns a boo lean indic ating if S CE is enab led.
  15503        */
  15504       sce.is Enabled =  function()  {
  15505         retu rn enabled ;
  15506       };
  15507       sce.tr ustAs = $s ceDelegate .trustAs;
  15508       sce.ge tTrusted =  $sceDeleg ate.getTru sted;
  15509       sce.va lueOf = $s ceDelegate .valueOf;
  15510  
  15511       if (!e nabled) {
  15512         sce. trustAs =  sce.getTru sted = fun ction(type , value) {  return va lue; };
  15513         sce. valueOf =  identity;
  15514       }
  15515  
  15516       /**
  15517        * @ng doc method
  15518        * @na me $sce#pa rseAs
  15519        *
  15520        * @de scription
  15521        * Con verts Angu lar {@link  guide/exp ression ex pression}  into a fun ction.  Th is is like  {@link
  15522        * ng. $parse $pa rse} and i s identica l when the  expressio n is a lit eral const ant.  Othe rwise, it
  15523        * wra ps the exp ression in  a call to  {@link ng .$sce#getT rusted $sc e.getTrust ed(*type*,
  15524        * *re sult*)}
  15525        *
  15526        * @pa ram {strin g} type Th e kind of  SCE contex t in which  this resu lt will be  used.
  15527        * @pa ram {strin g} express ion String  expressio n to compi le.
  15528        * @re turns {fun ction(cont ext, local s)} a func tion which  represent s the comp iled expre ssion:
  15529        *
  15530        *     * `context ` â€“ `{ob ject}` â€“  an object  against w hich any e xpressions  embedded  in the str ings
  15531        *       are eval uated agai nst (typic ally a sco pe object) .
  15532        *     * `locals`  â€“ `{obj ect=}` â€“  local var iables con text objec t, useful  for overri ding value s in
  15533        *       `context `.
  15534        */
  15535       sce.pa rseAs = fu nction sce ParseAs(ty pe, expr)  {
  15536         var  parsed = $ parse(expr );
  15537         if ( parsed.lit eral && pa rsed.const ant) {
  15538           re turn parse d;
  15539         } el se {
  15540           re turn $pars e(expr, fu nction(val ue) {
  15541              return sce .getTruste d(type, va lue);
  15542           }) ;
  15543         }
  15544       };
  15545  
  15546       /**
  15547        * @ng doc method
  15548        * @na me $sce#tr ustAs
  15549        *
  15550        * @de scription
  15551        * Del egates to  {@link ng. $sceDelega te#trustAs  `$sceDele gate.trust As`}.  As  such,
  15552        * ret urns an ob ject that  is trusted  by angula r for use  in specifi ed strict  contextual
  15553        * esc aping cont exts (such  as ng-bin d-html, ng -include,  any src at tribute
  15554        * int erpolation , any dom  event bind ing attrib ute interp olation su ch as for  onclick,   etc.)
  15555        * tha t uses the  provided  value.  Se e * {@link  ng.$sce $ sce} for e nabling st rict conte xtual
  15556        * esc aping.
  15557        *
  15558        * @pa ram {strin g} type Th e kind of  context in  which thi s value is  safe for  use.  e.g.  url,
  15559        *   r esource_ur l, html, j s and css.
  15560        * @pa ram {*} va lue The va lue that t hat should  be consid ered trust ed/safe.
  15561        * @re turns {*}  A value th at can be  used to st and in for  the provi ded `value ` in place s
  15562        * whe re Angular  expects a  $sce.trus tAs() retu rn value.
  15563        */
  15564  
  15565       /**
  15566        * @ng doc method
  15567        * @na me $sce#tr ustAsHtml
  15568        *
  15569        * @de scription
  15570        * Sho rthand met hod.  `$sc e.trustAsH tml(value) ` â†’
  15571        *      {@link ng .$sceDeleg ate#trustA s `$sceDel egate.trus tAs($sce.H TML, value )`}
  15572        *
  15573        * @pa ram {*} va lue The va lue to tru stAs.
  15574        * @re turns {*}  An object  that can b e passed t o {@link n g.$sce#get TrustedHtm l
  15575        *      $sce.getT rustedHtml (value)} t o obtain t he origina l value.   (privilege d directiv es
  15576        *      only acce pt express ions that  are either  literal c onstants o r are the
  15577        *      return va lue of {@l ink ng.$sc e#trustAs  $sce.trust As}.)
  15578        */
  15579  
  15580       /**
  15581        * @ng doc method
  15582        * @na me $sce#tr ustAsUrl
  15583        *
  15584        * @de scription
  15585        * Sho rthand met hod.  `$sc e.trustAsU rl(value)`  â†’
  15586        *      {@link ng .$sceDeleg ate#trustA s `$sceDel egate.trus tAs($sce.U RL, value) `}
  15587        *
  15588        * @pa ram {*} va lue The va lue to tru stAs.
  15589        * @re turns {*}  An object  that can b e passed t o {@link n g.$sce#get TrustedUrl
  15590        *      $sce.getT rustedUrl( value)} to  obtain th e original  value.  ( privileged  directive s
  15591        *      only acce pt express ions that  are either  literal c onstants o r are the
  15592        *      return va lue of {@l ink ng.$sc e#trustAs  $sce.trust As}.)
  15593        */
  15594  
  15595       /**
  15596        * @ng doc method
  15597        * @na me $sce#tr ustAsResou rceUrl
  15598        *
  15599        * @de scription
  15600        * Sho rthand met hod.  `$sc e.trustAsR esourceUrl (value)` â †’
  15601        *      {@link ng .$sceDeleg ate#trustA s `$sceDel egate.trus tAs($sce.R ESOURCE_UR L, value)` }
  15602        *
  15603        * @pa ram {*} va lue The va lue to tru stAs.
  15604        * @re turns {*}  An object  that can b e passed t o {@link n g.$sce#get TrustedRes ourceUrl
  15605        *      $sce.getT rustedReso urceUrl(va lue)} to o btain the  original v alue.  (pr ivileged d irectives
  15606        *      only acce pt express ions that  are either  literal c onstants o r are the  return
  15607        *      value of  {@link ng. $sce#trust As $sce.tr ustAs}.)
  15608        */
  15609  
  15610       /**
  15611        * @ng doc method
  15612        * @na me $sce#tr ustAsJs
  15613        *
  15614        * @de scription
  15615        * Sho rthand met hod.  `$sc e.trustAsJ s(value)`  →
  15616        *      {@link ng .$sceDeleg ate#trustA s `$sceDel egate.trus tAs($sce.J S, value)` }
  15617        *
  15618        * @pa ram {*} va lue The va lue to tru stAs.
  15619        * @re turns {*}  An object  that can b e passed t o {@link n g.$sce#get TrustedJs
  15620        *      $sce.getT rustedJs(v alue)} to  obtain the  original  value.  (p rivileged  directives
  15621        *      only acce pt express ions that  are either  literal c onstants o r are the
  15622        *      return va lue of {@l ink ng.$sc e#trustAs  $sce.trust As}.)
  15623        */
  15624  
  15625       /**
  15626        * @ng doc method
  15627        * @na me $sce#ge tTrusted
  15628        *
  15629        * @de scription
  15630        * Del egates to  {@link ng. $sceDelega te#getTrus ted `$sceD elegate.ge tTrusted`} .  As such ,
  15631        * tak es the res ult of a { @link ng.$ sce#trustA s `$sce.tr ustAs`}()  call and r eturns the
  15632        * ori ginally su pplied val ue if the  queried co ntext type  is a supe rtype of t he created  type.
  15633        * If  this condi tion isn't  satisfied , throws a n exceptio n.
  15634        *
  15635        * @pa ram {strin g} type Th e kind of  context in  which thi s value is  to be use d.
  15636        * @pa ram {*} ma ybeTrusted  The resul t of a pri or {@link  ng.$sce#tr ustAs `$sc e.trustAs` }
  15637        *                            call.
  15638        * @re turns {*}  The value  the was or iginally p rovided to
  15639        *                {@link ng. $sce#trust As `$sce.t rustAs`} i f valid in  this cont ext.
  15640        *                Otherwise,  throws an  exception .
  15641        */
  15642  
  15643       /**
  15644        * @ng doc method
  15645        * @na me $sce#ge tTrustedHt ml
  15646        *
  15647        * @de scription
  15648        * Sho rthand met hod.  `$sc e.getTrust edHtml(val ue)` â†’
  15649        *      {@link ng .$sceDeleg ate#getTru sted `$sce Delegate.g etTrusted( $sce.HTML,  value)`}
  15650        *
  15651        * @pa ram {*} va lue The va lue to pas s to `$sce .getTruste d`.
  15652        * @re turns {*}  The return  value of  `$sce.getT rusted($sc e.HTML, va lue)`
  15653        */
  15654  
  15655       /**
  15656        * @ng doc method
  15657        * @na me $sce#ge tTrustedCs s
  15658        *
  15659        * @de scription
  15660        * Sho rthand met hod.  `$sc e.getTrust edCss(valu e)` â†’
  15661        *      {@link ng .$sceDeleg ate#getTru sted `$sce Delegate.g etTrusted( $sce.CSS,  value)`}
  15662        *
  15663        * @pa ram {*} va lue The va lue to pas s to `$sce .getTruste d`.
  15664        * @re turns {*}  The return  value of  `$sce.getT rusted($sc e.CSS, val ue)`
  15665        */
  15666  
  15667       /**
  15668        * @ng doc method
  15669        * @na me $sce#ge tTrustedUr l
  15670        *
  15671        * @de scription
  15672        * Sho rthand met hod.  `$sc e.getTrust edUrl(valu e)` â†’
  15673        *      {@link ng .$sceDeleg ate#getTru sted `$sce Delegate.g etTrusted( $sce.URL,  value)`}
  15674        *
  15675        * @pa ram {*} va lue The va lue to pas s to `$sce .getTruste d`.
  15676        * @re turns {*}  The return  value of  `$sce.getT rusted($sc e.URL, val ue)`
  15677        */
  15678  
  15679       /**
  15680        * @ng doc method
  15681        * @na me $sce#ge tTrustedRe sourceUrl
  15682        *
  15683        * @de scription
  15684        * Sho rthand met hod.  `$sc e.getTrust edResource Url(value) ` â†’
  15685        *      {@link ng .$sceDeleg ate#getTru sted `$sce Delegate.g etTrusted( $sce.RESOU RCE_URL, v alue)`}
  15686        *
  15687        * @pa ram {*} va lue The va lue to pas s to `$sce Delegate.g etTrusted` .
  15688        * @re turns {*}  The return  value of  `$sce.getT rusted($sc e.RESOURCE _URL, valu e)`
  15689        */
  15690  
  15691       /**
  15692        * @ng doc method
  15693        * @na me $sce#ge tTrustedJs
  15694        *
  15695        * @de scription
  15696        * Sho rthand met hod.  `$sc e.getTrust edJs(value )` â†’
  15697        *      {@link ng .$sceDeleg ate#getTru sted `$sce Delegate.g etTrusted( $sce.JS, v alue)`}
  15698        *
  15699        * @pa ram {*} va lue The va lue to pas s to `$sce .getTruste d`.
  15700        * @re turns {*}  The return  value of  `$sce.getT rusted($sc e.JS, valu e)`
  15701        */
  15702  
  15703       /**
  15704        * @ng doc method
  15705        * @na me $sce#pa rseAsHtml
  15706        *
  15707        * @de scription
  15708        * Sho rthand met hod.  `$sc e.parseAsH tml(expres sion strin g)` â†’
  15709        *      {@link ng .$sce#pars eAs `$sce. parseAs($s ce.HTML, v alue)`}
  15710        *
  15711        * @pa ram {strin g} express ion String  expressio n to compi le.
  15712        * @re turns {fun ction(cont ext, local s)} a func tion which  represent s the comp iled expre ssion:
  15713        *
  15714        *     * `context ` â€“ `{ob ject}` â€“  an object  against w hich any e xpressions  embedded  in the str ings
  15715        *       are eval uated agai nst (typic ally a sco pe object) .
  15716        *     * `locals`  â€“ `{obj ect=}` â€“  local var iables con text objec t, useful  for overri ding value s in
  15717        *       `context `.
  15718        */
  15719  
  15720       /**
  15721        * @ng doc method
  15722        * @na me $sce#pa rseAsCss
  15723        *
  15724        * @de scription
  15725        * Sho rthand met hod.  `$sc e.parseAsC ss(value)`  â†’
  15726        *      {@link ng .$sce#pars eAs `$sce. parseAs($s ce.CSS, va lue)`}
  15727        *
  15728        * @pa ram {strin g} express ion String  expressio n to compi le.
  15729        * @re turns {fun ction(cont ext, local s)} a func tion which  represent s the comp iled expre ssion:
  15730        *
  15731        *     * `context ` â€“ `{ob ject}` â€“  an object  against w hich any e xpressions  embedded  in the str ings
  15732        *       are eval uated agai nst (typic ally a sco pe object) .
  15733        *     * `locals`  â€“ `{obj ect=}` â€“  local var iables con text objec t, useful  for overri ding value s in
  15734        *       `context `.
  15735        */
  15736  
  15737       /**
  15738        * @ng doc method
  15739        * @na me $sce#pa rseAsUrl
  15740        *
  15741        * @de scription
  15742        * Sho rthand met hod.  `$sc e.parseAsU rl(value)`  â†’
  15743        *      {@link ng .$sce#pars eAs `$sce. parseAs($s ce.URL, va lue)`}
  15744        *
  15745        * @pa ram {strin g} express ion String  expressio n to compi le.
  15746        * @re turns {fun ction(cont ext, local s)} a func tion which  represent s the comp iled expre ssion:
  15747        *
  15748        *     * `context ` â€“ `{ob ject}` â€“  an object  against w hich any e xpressions  embedded  in the str ings
  15749        *       are eval uated agai nst (typic ally a sco pe object) .
  15750        *     * `locals`  â€“ `{obj ect=}` â€“  local var iables con text objec t, useful  for overri ding value s in
  15751        *       `context `.
  15752        */
  15753  
  15754       /**
  15755        * @ng doc method
  15756        * @na me $sce#pa rseAsResou rceUrl
  15757        *
  15758        * @de scription
  15759        * Sho rthand met hod.  `$sc e.parseAsR esourceUrl (value)` â †’
  15760        *      {@link ng .$sce#pars eAs `$sce. parseAs($s ce.RESOURC E_URL, val ue)`}
  15761        *
  15762        * @pa ram {strin g} express ion String  expressio n to compi le.
  15763        * @re turns {fun ction(cont ext, local s)} a func tion which  represent s the comp iled expre ssion:
  15764        *
  15765        *     * `context ` â€“ `{ob ject}` â€“  an object  against w hich any e xpressions  embedded  in the str ings
  15766        *       are eval uated agai nst (typic ally a sco pe object) .
  15767        *     * `locals`  â€“ `{obj ect=}` â€“  local var iables con text objec t, useful  for overri ding value s in
  15768        *       `context `.
  15769        */
  15770  
  15771       /**
  15772        * @ng doc method
  15773        * @na me $sce#pa rseAsJs
  15774        *
  15775        * @de scription
  15776        * Sho rthand met hod.  `$sc e.parseAsJ s(value)`  →
  15777        *      {@link ng .$sce#pars eAs `$sce. parseAs($s ce.JS, val ue)`}
  15778        *
  15779        * @pa ram {strin g} express ion String  expressio n to compi le.
  15780        * @re turns {fun ction(cont ext, local s)} a func tion which  represent s the comp iled expre ssion:
  15781        *
  15782        *     * `context ` â€“ `{ob ject}` â€“  an object  against w hich any e xpressions  embedded  in the str ings
  15783        *       are eval uated agai nst (typic ally a sco pe object) .
  15784        *     * `locals`  â€“ `{obj ect=}` â€“  local var iables con text objec t, useful  for overri ding value s in
  15785        *       `context `.
  15786        */
  15787  
  15788       // Sho rthand del egations.
  15789       var pa rse = sce. parseAs,
  15790           ge tTrusted =  sce.getTr usted,
  15791           tr ustAs = sc e.trustAs;
  15792  
  15793       forEac h(SCE_CONT EXTS, func tion(enumV alue, name ) {
  15794         var  lName = lo wercase(na me);
  15795         sce[ camelCase( "parse_as_ " + lName) ] = functi on(expr) {
  15796           re turn parse (enumValue , expr);
  15797         };
  15798         sce[ camelCase( "get_trust ed_" + lNa me)] = fun ction(valu e) {
  15799           re turn getTr usted(enum Value, val ue);
  15800         };
  15801         sce[ camelCase( "trust_as_ " + lName) ] = functi on(value)  {
  15802           re turn trust As(enumVal ue, value) ;
  15803         };
  15804       });
  15805  
  15806       return  sce;
  15807     }];
  15808   }
  15809  
  15810   /**
  15811    * !!! Thi s is an un documented  "private"  service ! !!
  15812    *
  15813    * @name $ sniffer
  15814    * @requir es $window
  15815    * @requir es $docume nt
  15816    *
  15817    * @proper ty {boolea n} history  Does the  browser su pport html 5 history  api ?
  15818    * @proper ty {boolea n} transit ions Does  the browse r support  CSS transi tion event s ?
  15819    * @proper ty {boolea n} animati ons Does t he browser  support C SS animati on events  ?
  15820    *
  15821    * @descri ption
  15822    * This is  very simp le impleme ntation of  testing b rowser's f eatures.
  15823    */
  15824   function $ SnifferPro vider() {
  15825     this.$ge t = ['$win dow', '$do cument', f unction($w indow, $do cument) {
  15826       var ev entSupport  = {},
  15827           an droid =
  15828              int((/andr oid (\d+)/ .exec(lowe rcase(($wi ndow.navig ator || {} ).userAgen t)) || []) [1]),
  15829           bo xee = /Box ee/i.test( ($window.n avigator | | {}).user Agent),
  15830           do cument = $ document[0 ] || {},
  15831           ve ndorPrefix ,
  15832           ve ndorRegex  = /^(Moz|w ebkit|ms)( ?=[A-Z])/,
  15833           bo dyStyle =  document.b ody && doc ument.body .style,
  15834           tr ansitions  = false,
  15835           an imations =  false,
  15836           ma tch;
  15837  
  15838       if (bo dyStyle) {
  15839         for  (var prop  in bodySty le) {
  15840           if  (match =  vendorRege x.exec(pro p)) {
  15841              vendorPref ix = match [0];
  15842              vendorPref ix = vendo rPrefix.su bstr(0, 1) .toUpperCa se() + ven dorPrefix. substr(1);
  15843              break;
  15844           }
  15845         }
  15846  
  15847         if ( !vendorPre fix) {
  15848           ve ndorPrefix  = ('Webki tOpacity'  in bodySty le) && 'we bkit';
  15849         }
  15850  
  15851         tran sitions =  !!(('trans ition' in  bodyStyle)  || (vendo rPrefix +  'Transitio n' in body Style));
  15852         anim ations  =  !!(('anima tion' in b odyStyle)  || (vendor Prefix + ' Animation'  in bodySt yle));
  15853  
  15854         if ( android &&  (!transit ions ||  ! animations )) {
  15855           tr ansitions  = isString (document. body.style .webkitTra nsition);
  15856           an imations =  isString( document.b ody.style. webkitAnim ation);
  15857         }
  15858       }
  15859  
  15860  
  15861       return  {
  15862         // A ndroid has  history.p ushState,  but it doe s not upda te locatio n correctl y
  15863         // s o let's no t use the  history AP I at all.
  15864         // h ttp://code .google.co m/p/androi d/issues/d etail?id=1 7471
  15865         // h ttps://git hub.com/an gular/angu lar.js/iss ues/904
  15866  
  15867         // o lder webki t browser  (533.9) on  Boxee box  has exact ly the sam e problem  as Android  has
  15868         // s o let's no t use the  history AP I also
  15869         // W e are purp osefully u sing `!(an droid < 4) ` to cover  the case  when `andr oid` is un defined
  15870         // j shint -W01 8
  15871         hist ory: !!($w indow.hist ory && $wi ndow.histo ry.pushSta te && !(an droid < 4)  && !boxee ),
  15872         // j shint +W01 8
  15873         hasE vent: func tion(event ) {
  15874           //  IE9 imple ments 'inp ut' event  it's so fu bared that  we rather  pretend t hat it doe sn't have
  15875           //  it. In pa rticular t he event i s not fire d when bac kspace or  delete key  are press ed or
  15876           //  when cut  operation  is perform ed.
  15877           if  (event ==  'input' & & msie ==  9) return  false;
  15878  
  15879           if  (isUndefi ned(eventS upport[eve nt])) {
  15880              var divElm  = documen t.createEl ement('div ');
  15881              eventSuppo rt[event]  = 'on' + e vent in di vElm;
  15882           }
  15883  
  15884           re turn event Support[ev ent];
  15885         },
  15886         csp:  csp(),
  15887         vend orPrefix:  vendorPref ix,
  15888         tran sitions: t ransitions ,
  15889         anim ations: an imations,
  15890         andr oid: andro id
  15891       };
  15892     }];
  15893   }
  15894  
  15895   var $compi leMinErr =  minErr('$ compile');
  15896  
  15897   /**
  15898    * @ngdoc  service
  15899    * @name $ templateRe quest
  15900    *
  15901    * @descri ption
  15902    * The `$t emplateReq uest` serv ice downlo ads the pr ovided tem plate usin g `$http`  and, upon  success,
  15903    * stores  the conten ts inside  of `$templ ateCache`.  If the HT TP request  fails or  the respon se data
  15904    * of the  HTTP reque st is empt y then a ` $compile`  error will  be thrown  (the exce ption can  be thwarte d
  15905    * by sett ing the 2n d paramete r of the f unction to  true).
  15906    *
  15907    * @param  {string} t pl The HTT P request  template U RL
  15908    * @param  {boolean=}  ignoreReq uestError  Whether or  not to ig nore the e xception w hen the re quest fail s or the t emplate is  empty
  15909    *
  15910    * @return  {Promise}  the HTTP  Promise fo r the give n.
  15911    *
  15912    * @proper ty {number } totalPen dingReques ts total a mount of p ending tem plate requ ests being  downloade d.
  15913    */
  15914   function $ TemplateRe questProvi der() {
  15915     this.$ge t = ['$tem plateCache ', '$http' , '$q', fu nction($te mplateCach e, $http,  $q) {
  15916       functi on handleR equestFn(t pl, ignore RequestErr or) {
  15917         var  self = han dleRequest Fn;
  15918         self .totalPend ingRequest s++;
  15919  
  15920         var  transformR esponse =  $http.defa ults && $h ttp.defaul ts.transfo rmResponse ;
  15921  
  15922         if ( isArray(tr ansformRes ponse)) {
  15923           tr ansformRes ponse = tr ansformRes ponse.filt er(functio n(transfor mer) {
  15924              return tra nsformer ! == default HttpRespon seTransfor m;
  15925           }) ;
  15926         } el se if (tra nsformResp onse === d efaultHttp ResponseTr ansform) {
  15927           tr ansformRes ponse = nu ll;
  15928         }
  15929  
  15930         var  httpOption s = {
  15931           ca che: $temp lateCache,
  15932           tr ansformRes ponse: tra nsformResp onse
  15933         };
  15934  
  15935         retu rn $http.g et(tpl, ht tpOptions)
  15936           .t hen(functi on(respons e) {
  15937              var html =  response. data;
  15938              self.total PendingReq uests--;
  15939              $templateC ache.put(t pl, html);
  15940              return htm l;
  15941           },  handleErr or);
  15942  
  15943         func tion handl eError(res p) {
  15944           se lf.totalPe ndingReque sts--;
  15945           if  (!ignoreR equestErro r) {
  15946              throw $com pileMinErr ('tpload',  'Failed t o load tem plate: {0} ', tpl);
  15947           }
  15948           re turn $q.re ject(resp) ;
  15949         }
  15950       }
  15951  
  15952       handle RequestFn. totalPendi ngRequests  = 0;
  15953  
  15954       return  handleReq uestFn;
  15955     }];
  15956   }
  15957  
  15958   function $ $Testabili tyProvider () {
  15959     this.$ge t = ['$roo tScope', ' $browser',  '$locatio n',
  15960          fun ction($roo tScope,    $browser,    $locatio n) {
  15961  
  15962       /**
  15963        * @na me $testab ility
  15964        *
  15965        * @de scription
  15966        * The  private $ $testabili ty service  provides  a collecti on of meth ods for us e when deb ugging
  15967        * or  by automat ed test an d debuggin g tools.
  15968        */
  15969       var te stability  = {};
  15970  
  15971       /**
  15972        * @na me $$testa bility#fin dBindings
  15973        *
  15974        * @de scription
  15975        * Ret urns an ar ray of ele ments that  are bound  (via ng-b ind or {{} })
  15976        * to  expression s matching  the input .
  15977        *
  15978        * @pa ram {Eleme nt} elemen t The elem ent root t o search f rom.
  15979        * @pa ram {strin g} express ion The bi nding expr ession to  match.
  15980        * @pa ram {boole an} opt_ex actMatch I f true, on ly returns  exact mat ches
  15981        *      for the e xpression.  Filters a nd whitesp ace are ig nored.
  15982        */
  15983       testab ility.find Bindings =  function( element, e xpression,  opt_exact Match) {
  15984         var  bindings =  element.g etElements ByClassNam e('ng-bind ing');
  15985         var  matches =  [];
  15986         forE ach(bindin gs, functi on(binding ) {
  15987           va r dataBind ing = angu lar.elemen t(binding) .data('$bi nding');
  15988           if  (dataBind ing) {
  15989              forEach(da taBinding,  function( bindingNam e) {
  15990                if (opt_ exactMatch ) {
  15991                  var ma tcher = ne w RegExp(' (^|\\s)' +  escapeFor Regexp(exp ression) +  '(\\s|\\| |$)');
  15992                  if (ma tcher.test (bindingNa me)) {
  15993                    matc hes.push(b inding);
  15994                  }
  15995                } else {
  15996                  if (bi ndingName. indexOf(ex pression)  != -1) {
  15997                    matc hes.push(b inding);
  15998                  }
  15999                }
  16000              });
  16001           }
  16002         });
  16003         retu rn matches ;
  16004       };
  16005  
  16006       /**
  16007        * @na me $$testa bility#fin dModels
  16008        *
  16009        * @de scription
  16010        * Ret urns an ar ray of ele ments that  are two-w ay found v ia ng-mode l to
  16011        * exp ressions m atching th e input.
  16012        *
  16013        * @pa ram {Eleme nt} elemen t The elem ent root t o search f rom.
  16014        * @pa ram {strin g} express ion The mo del expres sion to ma tch.
  16015        * @pa ram {boole an} opt_ex actMatch I f true, on ly returns  exact mat ches
  16016        *      for the e xpression.
  16017        */
  16018       testab ility.find Models = f unction(el ement, exp ression, o pt_exactMa tch) {
  16019         var  prefixes =  ['ng-', ' data-ng-',  'ng\\:'];
  16020         for  (var p = 0 ; p < pref ixes.lengt h; ++p) {
  16021           va r attribut eEquals =  opt_exactM atch ? '='  : '*=';
  16022           va r selector  = '[' + p refixes[p]  + 'model'  + attribu teEquals +  '"' + exp ression +  '"]';
  16023           va r elements  = element .querySele ctorAll(se lector);
  16024           if  (elements .length) {
  16025              return ele ments;
  16026           }
  16027         }
  16028       };
  16029  
  16030       /**
  16031        * @na me $$testa bility#get Location
  16032        *
  16033        * @de scription
  16034        * Sho rtcut for  getting th e location  in a brow ser agnost ic way. Re turns
  16035        *      the path,  search, a nd hash. ( e.g. /path ?a=b#hash)
  16036        */
  16037       testab ility.getL ocation =  function()  {
  16038         retu rn $locati on.url();
  16039       };
  16040  
  16041       /**
  16042        * @na me $$testa bility#set Location
  16043        *
  16044        * @de scription
  16045        * Sho rtcut for  navigating  to a loca tion witho ut doing a  full page  reload.
  16046        *
  16047        * @pa ram {strin g} url The  location  url (path,  search an d hash,
  16048        *      e.g. /pat h?a=b#hash ) to go to .
  16049        */
  16050       testab ility.setL ocation =  function(u rl) {
  16051         if ( url !== $l ocation.ur l()) {
  16052           $l ocation.ur l(url);
  16053           $r ootScope.$ digest();
  16054         }
  16055       };
  16056  
  16057       /**
  16058        * @na me $$testa bility#whe nStable
  16059        *
  16060        * @de scription
  16061        * Cal ls the cal lback when  $timeout  and $http  requests a re complet ed.
  16062        *
  16063        * @pa ram {funct ion} callb ack
  16064        */
  16065       testab ility.when Stable = f unction(ca llback) {
  16066         $bro wser.notif yWhenNoOut standingRe quests(cal lback);
  16067       };
  16068  
  16069       return  testabili ty;
  16070     }];
  16071   }
  16072  
  16073   function $ TimeoutPro vider() {
  16074     this.$ge t = ['$roo tScope', ' $browser',  '$q', '$$ q', '$exce ptionHandl er',
  16075          fun ction($roo tScope,    $browser,    $q,   $$ q,   $exce ptionHandl er) {
  16076       var de ferreds =  {};
  16077  
  16078  
  16079        /**
  16080         * @n gdoc servi ce
  16081         * @n ame $timeo ut
  16082         *
  16083         * @d escription
  16084         * An gular's wr apper for  `window.se tTimeout`.  The `fn`  function i s wrapped  into a try /catch
  16085         * bl ock and de legates an y exceptio ns to
  16086         * {@ link ng.$e xceptionHa ndler $exc eptionHand ler} servi ce.
  16087         *
  16088         * Th e return v alue of re gistering  a timeout  function i s a promis e, which w ill be res olved when
  16089         * th e timeout  is reached  and the t imeout fun ction is e xecuted.
  16090         *
  16091         * To  cancel a  timeout re quest, cal l `$timeou t.cancel(p romise)`.
  16092         *
  16093         * In  tests you  can use { @link ngMo ck.$timeou t `$timeou t.flush()` } to
  16094         * sy nchronousl y flush th e queue of  deferred  functions.
  16095         *
  16096         * @p aram {func tion()} fn  A functio n, whose e xecution s hould be d elayed.
  16097         * @p aram {numb er=} [dela y=0] Delay  in millis econds.
  16098         * @p aram {bool ean=} [inv okeApply=t rue] If se t to `fals e` skips m odel dirty  checking,  otherwise
  16099         *    will invok e `fn` wit hin the {@ link ng.$r ootScope.S cope#$appl y $apply}  block.
  16100         * @r eturns {Pr omise} Pro mise that  will be re solved whe n the time out is rea ched. The  value this
  16101         *    promise wi ll be reso lved with  is the ret urn value  of the `fn ` function .
  16102         *
  16103         */
  16104       functi on timeout (fn, delay , invokeAp ply) {
  16105         var  skipApply  = (isDefin ed(invokeA pply) && ! invokeAppl y),
  16106              deferred =  (skipAppl y ? $$q :  $q).defer( ),
  16107              promise =  deferred.p romise,
  16108              timeoutId;
  16109  
  16110         time outId = $b rowser.def er(functio n() {
  16111           tr y {
  16112              deferred.r esolve(fn( ));
  16113           }  catch (e)  {
  16114              deferred.r eject(e);
  16115              $exception Handler(e) ;
  16116           }
  16117           fi nally {
  16118              delete def erreds[pro mise.$$tim eoutId];
  16119           }
  16120  
  16121           if  (!skipApp ly) $rootS cope.$appl y();
  16122         }, d elay);
  16123  
  16124         prom ise.$$time outId = ti meoutId;
  16125         defe rreds[time outId] = d eferred;
  16126  
  16127         retu rn promise ;
  16128       }
  16129  
  16130  
  16131        /**
  16132         * @n gdoc metho d
  16133         * @n ame $timeo ut#cancel
  16134         *
  16135         * @d escription
  16136         * Ca ncels a ta sk associa ted with t he `promis e`. As a r esult of t his, the p romise wil l be
  16137         * re solved wit h a reject ion.
  16138         *
  16139         * @p aram {Prom ise=} prom ise Promis e returned  by the `$ timeout` f unction.
  16140         * @r eturns {bo olean} Ret urns `true ` if the t ask hasn't  executed  yet and wa s successf ully
  16141         *    canceled.
  16142         */
  16143       timeou t.cancel =  function( promise) {
  16144         if ( promise &&  promise.$ $timeoutId  in deferr eds) {
  16145           de ferreds[pr omise.$$ti meoutId].r eject('can celed');
  16146           de lete defer reds[promi se.$$timeo utId];
  16147           re turn $brow ser.defer. cancel(pro mise.$$tim eoutId);
  16148         }
  16149         retu rn false;
  16150       };
  16151  
  16152       return  timeout;
  16153     }];
  16154   }
  16155  
  16156   // NOTE:   The usage  of window  and docume nt instead  of $windo w and $doc ument here  is
  16157   // deliber ate.  This  service d epends on  the specif ic behavio r of ancho r nodes cr eated by t he
  16158   // browser  (resolvin g and pars ing URLs)  that is un likely to  be provide d by mock  objects an d
  16159   // cause u s to break  tests.  I n addition , when the  browser r esolves a  URL for XH R, it
  16160   // doesn't  know abou t mocked l ocations a nd resolve s URLs to  the real d ocument -  which is
  16161   // exactly  the behav ior needed  here.  Th ere is lit tle value  is mocking  these out  for this
  16162   // service .
  16163   var urlPar singNode =  document. createElem ent("a");
  16164   var origin Url = urlR esolve(win dow.locati on.href);
  16165  
  16166  
  16167   /**
  16168    *
  16169    * Impleme ntation No tes for no n-IE brows ers
  16170    * ------- ---------- ---------- ---------- ---
  16171    * Assigni ng a URL t o the href  property  of an anch or DOM nod e, even on e attached  to the DO M,
  16172    * results  both in t he normali zing and p arsing of  the URL.   Normalizin g means th at a relat ive
  16173    * URL wil l be resol ved into a n absolute  URL in th e context  of the app lication d ocument.
  16174    * Parsing  means tha t the anch or node's  host, host name, prot ocol, port , pathname  and relat ed
  16175    * propert ies are al l populate d to refle ct the nor malized UR L.  This a pproach ha s wide
  16176    * compati bility - S afari 1+,  Mozilla 1+ , Opera 7+ ,e etc.  S ee
  16177    * http:// www.aptana .com/refer ence/html/ api/HTMLAn chorElemen t.html
  16178    *
  16179    * Impleme ntation No tes for IE
  16180    * ------- ---------- ----------
  16181    * IE >= 8  and <= 10  normalize s the URL  when assig ned to the  anchor no de similar  to the ot her
  16182    * browser s.  Howeve r, the par sed compon ents will  not be set  if the UR L assigned  did not s pecify
  16183    * them.   (e.g. if y ou assign  a.href = " foo", then  a.protoco l, a.host,  etc. will  be empty. )  We
  16184    * work ar ound that  by perform ing the pa rsing in a  2nd step  by taking  a previous ly normali zed
  16185    * URL (e. g. by assi gning to a .href) and  assigning  it a.href  again.  T his correc tly popula tes the
  16186    * propert ies such a s protocol , hostname , port, et c.
  16187    *
  16188    * IE7 doe s not norm alize the  URL when a ssigned to  an anchor  node.  (A pparently,  it does,  if one
  16189    * uses th e inner HT ML approac h to assig n the URL  as part of  an HTML s nippet -
  16190    * http:// stackoverf low.com/a/ 472729)  H owever, se tting img[ src] does  normalize  the URL.
  16191    * Unfortu nately, se tting img[ src] to so mething li ke "javasc ript:foo"  on IE thro ws an exce ption.
  16192    * Since t he primary  usage for  normalizi ng URLs is  to saniti ze such UR Ls, we can 't use tha t
  16193    * method  and IE < 8  is unsupp orted.
  16194    *
  16195    * Referen ces:
  16196    *   http: //develope r.mozilla. org/en-US/ docs/Web/A PI/HTMLAnc horElement
  16197    *   http: //www.apta na.com/ref erence/htm l/api/HTML AnchorElem ent.html
  16198    *   http: //url.spec .whatwg.or g/#urlutil s
  16199    *   https ://github. com/angula r/angular. js/pull/29 02
  16200    *   http: //james.pa dolsey.com /javascrip t/parsing- urls-with- the-dom/
  16201    *
  16202    * @kind f unction
  16203    * @param  {string} u rl The URL  to be par sed.
  16204    * @descri ption Norm alizes and  parses a  URL.
  16205    * @return s {object}  Returns t he normali zed URL as  a diction ary.
  16206    *
  16207    *   | mem ber name    | Descrip tion    |
  16208    *   |---- ---------- -|-------- --------|
  16209    *   | hre f           | A norma lized vers ion of the  provided  URL if it  was not an  absolute  URL |
  16210    *   | pro tocol       | The pro tocol incl uding the  trailing c olon                                 |
  16211    *   | hos t           | The hos t and port  (if the p ort is non -default)  of the nor malizedUrl     |
  16212    *   | sea rch         | The sea rch params , minus th e question  mark                                |
  16213    *   | has h           | The has h string,  minus the  hash symbo l
  16214    *   | hos tname       | The hos tname
  16215    *   | por t           | The por t, without  ":"
  16216    *   | pat hname       | The pat hname, beg inning wit h "/"
  16217    *
  16218    */
  16219   function u rlResolve( url) {
  16220     var href  = url;
  16221  
  16222     if (msie ) {
  16223       // Nor malize bef ore parse.   Refer Im plementati on Notes o n why this  is
  16224       // don e in two s teps on IE .
  16225       urlPar singNode.s etAttribut e("href",  href);
  16226       href =  urlParsin gNode.href ;
  16227     }
  16228  
  16229     urlParsi ngNode.set Attribute( 'href', hr ef);
  16230  
  16231     // urlPa rsingNode  provides t he UrlUtil s interfac e - http:/ /url.spec. whatwg.org /#urlutils
  16232     return {
  16233       href:  urlParsing Node.href,
  16234       protoc ol: urlPar singNode.p rotocol ?  urlParsing Node.proto col.replac e(/:$/, '' ) : '',
  16235       host:  urlParsing Node.host,
  16236       search : urlParsi ngNode.sea rch ? urlP arsingNode .search.re place(/^\? /, '') : ' ',
  16237       hash:  urlParsing Node.hash  ? urlParsi ngNode.has h.replace( /^#/, '')  : '',
  16238       hostna me: urlPar singNode.h ostname,
  16239       port:  urlParsing Node.port,
  16240       pathna me: (urlPa rsingNode. pathname.c harAt(0) = == '/')
  16241         ? ur lParsingNo de.pathnam e
  16242         : '/ ' + urlPar singNode.p athname
  16243     };
  16244   }
  16245  
  16246   /**
  16247    * Parse a  request U RL and det ermine whe ther this  is a same- origin req uest as th e applicat ion docume nt.
  16248    *
  16249    * @param  {string|ob ject} requ estUrl The  url of th e request  as a strin g that wil l be resol ved
  16250    * or a pa rsed URL o bject.
  16251    * @return s {boolean } Whether  the reques t is for t he same or igin as th e applicat ion docume nt.
  16252    */
  16253   function u rlIsSameOr igin(reque stUrl) {
  16254     var pars ed = (isSt ring(reque stUrl)) ?  urlResolve (requestUr l) : reque stUrl;
  16255     return ( parsed.pro tocol ===  originUrl. protocol & &
  16256              parsed.hos t === orig inUrl.host );
  16257   }
  16258  
  16259   /**
  16260    * @ngdoc  service
  16261    * @name $ window
  16262    *
  16263    * @descri ption
  16264    * A refer ence to th e browser' s `window`  object. W hile `wind ow`
  16265    * is glob ally avail able in Ja vaScript,  it causes  testabilit y problems , because
  16266    * it is a  global va riable. In  angular w e always r efer to it  through t he
  16267    * `$windo w` service , so it ma y be overr idden, rem oved or mo cked for t esting.
  16268    *
  16269    * Express ions, like  the one d efined for  the `ngCl ick` direc tive in th e example
  16270    * below,  are evalua ted with r espect to  the curren t scope.   Therefore,  there is
  16271    * no risk  of inadve rtently co ding in a  dependency  on a glob al value i n such an
  16272    * express ion.
  16273    *
  16274    * @exampl e
  16275      <exampl e module=" windowExam ple">
  16276        <file  name="ind ex.html">
  16277          <sc ript>
  16278            a ngular.mod ule('windo wExample',  [])
  16279               .controll er('Exampl eControlle r', ['$sco pe', '$win dow', func tion($scop e, $window ) {
  16280                 $scope. greeting =  'Hello, W orld!';
  16281                 $scope. doGreeting  = functio n(greeting ) {
  16282                   $wind ow.alert(g reeting);
  16283                 };
  16284               }]);
  16285          </s cript>
  16286          <di v ng-contr oller="Exa mpleContro ller">
  16287            < input type ="text" ng -model="gr eeting" />
  16288            < button ng- click="doG reeting(gr eeting)">A LERT</butt on>
  16289          </d iv>
  16290        </fil e>
  16291        <file  name="pro tractor.js " type="pr otractor">
  16292         it(' should dis play the g reeting in  the input  box', fun ction() {
  16293          ele ment(by.mo del('greet ing')).sen dKeys('Hel lo, E2E Te sts');
  16294          //  If we clic k the butt on it will  block the  test runn er
  16295          //  element(': button').c lick();
  16296         });
  16297        </fil e>
  16298      </examp le>
  16299    */
  16300   function $ WindowProv ider() {
  16301     this.$ge t = valueF n(window);
  16302   }
  16303  
  16304   /* global  currencyFi lter: true ,
  16305    dateFilte r: true,
  16306    filterFil ter: true,
  16307    jsonFilte r: true,
  16308    limitToFi lter: true ,
  16309    lowercase Filter: tr ue,
  16310    numberFil ter: true,
  16311    orderByFi lter: true ,
  16312    uppercase Filter: tr ue,
  16313    */
  16314  
  16315   /**
  16316    * @ngdoc  provider
  16317    * @name $ filterProv ider
  16318    * @descri ption
  16319    *
  16320    * Filters  are just  functions  which tran sform inpu t to an ou tput. Howe ver filter s need to  be
  16321    * Depende ncy Inject ed. To ach ieve this  a filter d efinition  consists o f a factor y function  which is
  16322    * annotat ed with de pendencies  and is re sponsible  for creati ng a filte r function .
  16323    *
  16324    * ```js
  16325    *   // Fi lter regis tration
  16326    *   funct ion MyModu le($provid e, $filter Provider)  {
  16327    *     //  create a s ervice to  demonstrat e injectio n (not alw ays needed )
  16328    *     $pr ovide.valu e('greet',  function( name){
  16329    *       r eturn 'Hel lo ' + nam e + '!';
  16330    *     });
  16331    *
  16332    *     //  register a  filter fa ctory whic h uses the
  16333    *     //  greet serv ice to dem onstrate D I.
  16334    *     $fi lterProvid er.registe r('greet',  function( greet){
  16335    *       / / return t he filter  function w hich uses  the greet  service
  16336    *       / / to gener ate saluta tion
  16337    *       r eturn func tion(text)  {
  16338    *          // filter s need to  be forgivi ng so chec k input va lidity
  16339    *          return te xt && gree t(text) ||  text;
  16340    *       } ;
  16341    *     });
  16342    *   }
  16343    * ```
  16344    *
  16345    * The fil ter functi on is regi stered wit h the `$in jector` un der the fi lter name  suffix wit h
  16346    * `Filter `.
  16347    *
  16348    * ```js
  16349    *   it('s hould be t he same in stance', i nject(
  16350    *     fun ction($fil terProvide r) {
  16351    *       $ filterProv ider.regis ter('rever se', funct ion(){
  16352    *          return .. .;
  16353    *       } );
  16354    *     },
  16355    *     fun ction($fil ter, rever seFilter)  {
  16356    *       e xpect($fil ter('rever se')).toBe (reverseFi lter);
  16357    *     });
  16358    * ```
  16359    *
  16360    *
  16361    * For mor e informat ion about  how angula r filters  work, and  how to cre ate your o wn filters , see
  16362    * {@link  guide/filt er Filters } in the A ngular Dev eloper Gui de.
  16363    */
  16364  
  16365   /**
  16366    * @ngdoc  service
  16367    * @name $ filter
  16368    * @kind f unction
  16369    * @descri ption
  16370    * Filters  are used  for format ting data  displayed  to the use r.
  16371    *
  16372    * The gen eral synta x in templ ates is as  follows:
  16373    *
  16374    *          {{ expres sion [| fi lter_name[ :parameter _value] .. . ] }}
  16375    *
  16376    * @param  {String} n ame Name o f the filt er functio n to retri eve
  16377    * @return  {Function } the filt er functio n
  16378    * @exampl e
  16379      <exampl e name="$f ilter" mod ule="filte rExample">
  16380        <file  name="ind ex.html">
  16381          <di v ng-contr oller="Mai nCtrl">
  16382           <h 3>{{ origi nalText }} </h3>
  16383           <h 3>{{ filte redText }} </h3>
  16384          </d iv>
  16385        </fil e>
  16386  
  16387        <file  name="scr ipt.js">
  16388         angu lar.module ('filterEx ample', [] )
  16389         .con troller('M ainCtrl',  function($ scope, $fi lter) {
  16390           $s cope.origi nalText =  'hello';
  16391           $s cope.filte redText =  $filter('u ppercase') ($scope.or iginalText );
  16392         });
  16393        </fil e>
  16394      </examp le>
  16395     */
  16396   $FilterPro vider.$inj ect = ['$p rovide'];
  16397   function $ FilterProv ider($prov ide) {
  16398     var suff ix = 'Filt er';
  16399  
  16400     /**
  16401      * @ngdo c method
  16402      * @name  $filterPr ovider#reg ister
  16403      * @para m {string| Object} na me Name of  the filte r function , or an ob ject map o f filters  where
  16404      *    th e keys are  the filte r names an d the valu es are the  filter fa ctories.
  16405      * @retu rns {Objec t} Registe red filter  instance,  or if a m ap of filt ers was pr ovided the n a map
  16406      *    of  the regis tered filt er instanc es.
  16407      */
  16408     function  register( name, fact ory) {
  16409       if (is Object(nam e)) {
  16410         var  filters =  {};
  16411         forE ach(name,  function(f ilter, key ) {
  16412           fi lters[key]  = registe r(key, fil ter);
  16413         });
  16414         retu rn filters ;
  16415       } else  {
  16416         retu rn $provid e.factory( name + suf fix, facto ry);
  16417       }
  16418     }
  16419     this.reg ister = re gister;
  16420  
  16421     this.$ge t = ['$inj ector', fu nction($in jector) {
  16422       return  function( name) {
  16423         retu rn $inject or.get(nam e + suffix );
  16424       };
  16425     }];
  16426  
  16427     //////// ////////// ////////// ////////// //
  16428  
  16429     /* globa l
  16430       curren cyFilter:  false,
  16431       dateFi lter: fals e,
  16432       filter Filter: fa lse,
  16433       jsonFi lter: fals e,
  16434       limitT oFilter: f alse,
  16435       lowerc aseFilter:  false,
  16436       number Filter: fa lse,
  16437       orderB yFilter: f alse,
  16438       upperc aseFilter:  false,
  16439     */
  16440  
  16441     register ('currency ', currenc yFilter);
  16442     register ('date', d ateFilter) ;
  16443     register ('filter',  filterFil ter);
  16444     register ('json', j sonFilter) ;
  16445     register ('limitTo' , limitToF ilter);
  16446     register ('lowercas e', lowerc aseFilter) ;
  16447     register ('number',  numberFil ter);
  16448     register ('orderBy' , orderByF ilter);
  16449     register ('uppercas e', upperc aseFilter) ;
  16450   }
  16451  
  16452   /**
  16453    * @ngdoc  filter
  16454    * @name f ilter
  16455    * @kind f unction
  16456    *
  16457    * @descri ption
  16458    * Selects  a subset  of items f rom `array ` and retu rns it as  a new arra y.
  16459    *
  16460    * @param  {Array} ar ray The so urce array .
  16461    * @param  {string|Ob ject|funct ion()} exp ression Th e predicat e to be us ed for sel ecting ite ms from
  16462    *   `arra y`.
  16463    *
  16464    *   Can b e one of:
  16465    *
  16466    *   - `st ring`: The  string is  evaluated  as an exp ression an d the resu lting valu e is used  for substr ing match  against
  16467    *     the  contents  of the `ar ray`. All  strings or  objects w ith string  propertie s in `arra y` that co ntain this  string
  16468    *     wil l be retur ned. The p redicate c an be nega ted by pre fixing the  string wi th `!`.
  16469    *
  16470    *   - `Ob ject`: A p attern obj ect can be  used to f ilter spec ific prope rties on o bjects con tained
  16471    *     by  `array`. F or example  `{name:"M ", phone:" 1"}` predi cate will  return an  array of i tems
  16472    *     whi ch have pr operty `na me` contai ning "M" a nd propert y `phone`  containing  "1". A sp ecial
  16473    *     pro perty name  `$` can b e used (as  in `{$:"t ext"}`) to  accept a  match agai nst any
  16474    *     pro perty of t he object.  That's eq uivalent t o the simp le substri ng match w ith a `str ing`
  16475    *     as  described  above. The  predicate  can be ne gated by p refixing t he string  with `!`.
  16476    *     For  Example ` {name: "!M "}` predic ate will r eturn an a rray of it ems which  have prope rty `name`
  16477    *     not  containin g "M".
  16478    *
  16479    *   - `fu nction(val ue, index) `: A predi cate funct ion can be  used to w rite arbit rary filte rs. The
  16480    *     fun ction is c alled for  each eleme nt of `arr ay`. The f inal resul t is an ar ray of tho se
  16481    *     ele ments that  the predi cate retur ned true f or.
  16482    *
  16483    * @param  {function( actual, ex pected)|tr ue|undefin ed} compar ator Compa rator whic h is used  in
  16484    *     det ermining i f the expe cted value  (from the  filter ex pression)  and actual  value (fr om
  16485    *     the  object in  the array ) should b e consider ed a match .
  16486    *
  16487    *   Can b e one of:
  16488    *
  16489    *   - `fu nction(act ual, expec ted)`:
  16490    *     The  function  will be gi ven the ob ject value  and the p redicate v alue to co mpare and
  16491    *     sho uld return  true if t he item sh ould be in cluded in  filtered r esult.
  16492    *
  16493    *   - `tr ue`: A sho rthand for  `function (actual, e xpected) {  return an gular.equa ls(expecte d, actual) }`.
  16494    *     thi s is essen tially str ict compar ison of ex pected and  actual.
  16495    *
  16496    *   - `fa lse|undefi ned`: A sh ort hand f or a funct ion which  will look  for a subs tring matc h in case
  16497    *     ins ensitive w ay.
  16498    *
  16499    * @exampl e
  16500      <exampl e>
  16501        <file  name="ind ex.html">
  16502          <di v ng-init= "friends =  [{name:'J ohn', phon e:'555-127 6'},
  16503                                      {name:'M ary', phon e:'800-BIG -MARY'},
  16504                                      {name:'M ike', phon e:'555-432 1'},
  16505                                      {name:'A dam', phon e:'555-567 8'},
  16506                                      {name:'J ulie', pho ne:'555-87 65'},
  16507                                      {name:'J uliette',  phone:'555 -5678'}]"> </div>
  16508  
  16509          Sea rch: <inpu t ng-model ="searchTe xt">
  16510          <ta ble id="se archTextRe sults">
  16511            < tr><th>Nam e</th><th> Phone</th> </tr>
  16512            < tr ng-repe at="friend  in friend s | filter :searchTex t">
  16513               <td>{{fri end.name}} </td>
  16514               <td>{{fri end.phone} }</td>
  16515            < /tr>
  16516          </t able>
  16517          <hr >
  16518          Any : <input n g-model="s earch.$">  <br>
  16519          Nam e only <in put ng-mod el="search .name"><br >
  16520          Pho ne only <i nput ng-mo del="searc h.phone">< br>
  16521          Equ ality <inp ut type="c heckbox" n g-model="s trict"><br >
  16522          <ta ble id="se archObjRes ults">
  16523            < tr><th>Nam e</th><th> Phone</th> </tr>
  16524            < tr ng-repe at="friend Obj in fri ends | fil ter:search :strict">
  16525               <td>{{fri endObj.nam e}}</td>
  16526               <td>{{fri endObj.pho ne}}</td>
  16527            < /tr>
  16528          </t able>
  16529        </fil e>
  16530        <file  name="pro tractor.js " type="pr otractor">
  16531          var  expectFri endNames =  function( expectedNa mes, key)  {
  16532            e lement.all (by.repeat er(key + '  in friend s').column (key + '.n ame')).the n(function (arr) {
  16533               arr.forEa ch(functio n(wd, i) {
  16534                 expect( wd.getText ()).toMatc h(expected Names[i]);
  16535               });
  16536            } );
  16537          };
  16538  
  16539          it( 'should se arch acros s all fiel ds when fi ltering wi th a strin g', functi on() {
  16540            v ar searchT ext = elem ent(by.mod el('search Text'));
  16541            s earchText. clear();
  16542            s earchText. sendKeys(' m');
  16543            e xpectFrien dNames(['M ary', 'Mik e', 'Adam' ], 'friend ');
  16544  
  16545            s earchText. clear();
  16546            s earchText. sendKeys(' 76');
  16547            e xpectFrien dNames(['J ohn', 'Jul ie'], 'fri end');
  16548          });
  16549  
  16550          it( 'should se arch in sp ecific fie lds when f iltering w ith a pred icate obje ct', funct ion() {
  16551            v ar searchA ny = eleme nt(by.mode l('search. $'));
  16552            s earchAny.c lear();
  16553            s earchAny.s endKeys('i ');
  16554            e xpectFrien dNames(['M ary', 'Mik e', 'Julie ', 'Juliet te'], 'fri endObj');
  16555          });
  16556          it( 'should us e a equal  comparison  when comp arator is  true', fun ction() {
  16557            v ar searchN ame = elem ent(by.mod el('search .name'));
  16558            v ar strict  = element( by.model(' strict'));
  16559            s earchName. clear();
  16560            s earchName. sendKeys(' Julie');
  16561            s trict.clic k();
  16562            e xpectFrien dNames(['J ulie'], 'f riendObj') ;
  16563          });
  16564        </fil e>
  16565      </examp le>
  16566    */
  16567   function f ilterFilte r() {
  16568     return f unction(ar ray, expre ssion, com parator) {
  16569       if (!i sArray(arr ay)) retur n array;
  16570  
  16571       var co mparatorTy pe = typeo f(comparat or),
  16572           pr edicates =  [];
  16573  
  16574       predic ates.check  = functio n(value, i ndex) {
  16575         for  (var j = 0 ; j < pred icates.len gth; j++)  {
  16576           if  (!predica tes[j](val ue, index) ) {
  16577              return fal se;
  16578           }
  16579         }
  16580         retu rn true;
  16581       };
  16582  
  16583       if (co mparatorTy pe !== 'fu nction') {
  16584         if ( comparator Type === ' boolean' & & comparat or) {
  16585           co mparator =  function( obj, text)  {
  16586              return ang ular.equal s(obj, tex t);
  16587           };
  16588         } el se {
  16589           co mparator =  function( obj, text)  {
  16590              if (obj &&  text && t ypeof obj  === 'objec t' && type of text == = 'object' ) {
  16591                for (var  objKey in  obj) {
  16592                  if (ob jKey.charA t(0) !== ' $' && hasO wnProperty .call(obj,  objKey) & &
  16593                      co mparator(o bj[objKey] , text[obj Key])) {
  16594                    retu rn true;
  16595                  }
  16596                }
  16597                return f alse;
  16598              }
  16599              text = (''  + text).t oLowerCase ();
  16600              return (''  + obj).to LowerCase( ).indexOf( text) > -1 ;
  16601           };
  16602         }
  16603       }
  16604  
  16605       var se arch = fun ction(obj,  text) {
  16606         if ( typeof tex t === 'str ing' && te xt.charAt( 0) === '!' ) {
  16607           re turn !sear ch(obj, te xt.substr( 1));
  16608         }
  16609         swit ch (typeof  obj) {
  16610           ca se 'boolea n':
  16611           ca se 'number ':
  16612           ca se 'string ':
  16613              return com parator(ob j, text);
  16614           ca se 'object ':
  16615              switch (ty peof text)  {
  16616                case 'ob ject':
  16617                  return  comparato r(obj, tex t);
  16618                default:
  16619                  for (v ar objKey  in obj) {
  16620                    if ( objKey.cha rAt(0) !==  '$' && se arch(obj[o bjKey], te xt)) {
  16621                      re turn true;
  16622                    }
  16623                  }
  16624                  break;
  16625              }
  16626              return fal se;
  16627           ca se 'array' :
  16628              for (var i  = 0; i <  obj.length ; i++) {
  16629                if (sear ch(obj[i],  text)) {
  16630                  return  true;
  16631                }
  16632              }
  16633              return fal se;
  16634           de fault:
  16635              return fal se;
  16636         }
  16637       };
  16638       switch  (typeof e xpression)  {
  16639         case  'boolean' :
  16640         case  'number':
  16641         case  'string':
  16642           //  Set up ex pression o bject and  fall throu gh
  16643           ex pression =  {$:expres sion};
  16644           //  jshint -W 086
  16645         case  'object':
  16646           //  jshint +W 086
  16647           fo r (var key  in expres sion) {
  16648              (function( path) {
  16649                if (type of express ion[path]  === 'undef ined') ret urn;
  16650                predicat es.push(fu nction(val ue) {
  16651                  return  search(pa th == '$'  ? value :  (value &&  value[path ]), expres sion[path] );
  16652                });
  16653              })(key);
  16654           }
  16655           br eak;
  16656         case  'function ':
  16657           pr edicates.p ush(expres sion);
  16658           br eak;
  16659         defa ult:
  16660           re turn array ;
  16661       }
  16662       var fi ltered = [ ];
  16663       for (v ar j = 0;  j < array. length; j+ +) {
  16664         var  value = ar ray[j];
  16665         if ( predicates .check(val ue, j)) {
  16666           fi ltered.pus h(value);
  16667         }
  16668       }
  16669       return  filtered;
  16670     };
  16671   }
  16672  
  16673   /**
  16674    * @ngdoc  filter
  16675    * @name c urrency
  16676    * @kind f unction
  16677    *
  16678    * @descri ption
  16679    * Formats  a number  as a curre ncy (ie $1 ,234.56).  When no cu rrency sym bol is pro vided, def ault
  16680    * symbol  for curren t locale i s used.
  16681    *
  16682    * @param  {number} a mount Inpu t to filte r.
  16683    * @param  {string=}  symbol Cur rency symb ol or iden tifier to  be display ed.
  16684    * @param  {number=}  fractionSi ze Number  of decimal  places to  round the  amount to , defaults  to defaul t max frac tion size  for curren t locale
  16685    * @return s {string}  Formatted  number.
  16686    *
  16687    *
  16688    * @exampl e
  16689      <exampl e module=" currencyEx ample">
  16690        <file  name="ind ex.html">
  16691          <sc ript>
  16692            a ngular.mod ule('curre ncyExample ', [])
  16693               .controll er('Exampl eControlle r', ['$sco pe', funct ion($scope ) {
  16694                 $scope. amount = 1 234.56;
  16695               }]);
  16696          </s cript>
  16697          <di v ng-contr oller="Exa mpleContro ller">
  16698            < input type ="number"  ng-model=" amount"> < br>
  16699            d efault cur rency symb ol ($): <s pan id="cu rrency-def ault">{{am ount | cur rency}}</s pan><br>
  16700            c ustom curr ency ident ifier (USD $): <span  id="curren cy-custom" >{{amount  | currency :"USD$"}}< /span>
  16701            n o fraction s (0): <sp an id="cur rency-no-f ractions"> {{amount |  currency: "USD$":0}} </span>
  16702          </d iv>
  16703        </fil e>
  16704        <file  name="pro tractor.js " type="pr otractor">
  16705          it( 'should in it with 12 34.56', fu nction() {
  16706            e xpect(elem ent(by.id( 'currency- default')) .getText() ).toBe('$1 ,234.56');
  16707            e xpect(elem ent(by.id( 'currency- custom')). getText()) .toBe('USD $1,234.56' );
  16708            e xpect(elem ent(by.id( 'currency- no-fractio ns')).getT ext()).toB e('USD$1,2 35');
  16709          });
  16710          it( 'should up date', fun ction() {
  16711            i f (browser .params.br owser == ' safari') {
  16712               // Safari  does not  understand  the minus  key. See
  16713               // https: //github.c om/angular /protracto r/issues/4 81
  16714               return;
  16715            }
  16716            e lement(by. model('amo unt')).cle ar();
  16717            e lement(by. model('amo unt')).sen dKeys('-12 34');
  16718            e xpect(elem ent(by.id( 'currency- default')) .getText() ).toBe('($ 1,234.00)' );
  16719            e xpect(elem ent(by.id( 'currency- custom')). getText()) .toBe('(US D$1,234.00 )');
  16720            e xpect(elem ent(by.id( 'currency- no-fractio ns')).getT ext()).toB e('(USD$1, 234)');
  16721          });
  16722        </fil e>
  16723      </examp le>
  16724    */
  16725   currencyFi lter.$inje ct = ['$lo cale'];
  16726   function c urrencyFil ter($local e) {
  16727     var form ats = $loc ale.NUMBER _FORMATS;
  16728     return f unction(am ount, curr encySymbol , fraction Size) {
  16729       if (is Undefined( currencySy mbol)) {
  16730         curr encySymbol  = formats .CURRENCY_ SYM;
  16731       }
  16732  
  16733       if (is Undefined( fractionSi ze)) {
  16734         frac tionSize =  formats.P ATTERNS[1] .maxFrac;
  16735       }
  16736  
  16737       // if  null or un defined pa ss it thro ugh
  16738       return  (amount = = null)
  16739           ?  amount
  16740           :  formatNumb er(amount,  formats.P ATTERNS[1] , formats. GROUP_SEP,  formats.D ECIMAL_SEP , fraction Size).
  16741                replace( /\u00A4/g,  currencyS ymbol);
  16742     };
  16743   }
  16744  
  16745   /**
  16746    * @ngdoc  filter
  16747    * @name n umber
  16748    * @kind f unction
  16749    *
  16750    * @descri ption
  16751    * Formats  a number  as text.
  16752    *
  16753    * If the  input is n ot a numbe r an empty  string is  returned.
  16754    *
  16755    * @param  {number|st ring} numb er Number  to format.
  16756    * @param  {(number|s tring)=} f ractionSiz e Number o f decimal  places to  round the  number to.
  16757    * If this  is not pr ovided the n the frac tion size  is compute d from the  current l ocale's nu mber
  16758    * formatt ing patter n. In the  case of th e default  locale, it  will be 3 .
  16759    * @return s {string}  Number ro unded to d ecimalPlac es and pla ces a â€œ, ” after  each third  digit.
  16760    *
  16761    * @exampl e
  16762      <exampl e module=" numberFilt erExample" >
  16763        <file  name="ind ex.html">
  16764          <sc ript>
  16765            a ngular.mod ule('numbe rFilterExa mple', [])
  16766               .controll er('Exampl eControlle r', ['$sco pe', funct ion($scope ) {
  16767                 $scope. val = 1234 .56789;
  16768               }]);
  16769          </s cript>
  16770          <di v ng-contr oller="Exa mpleContro ller">
  16771            E nter numbe r: <input  ng-model=' val'><br>
  16772            D efault for matting: < span id='n umber-defa ult'>{{val  | number} }</span><b r>
  16773            N o fraction s: <span>{ {val | num ber:0}}</s pan><br>
  16774            N egative nu mber: <spa n>{{-val |  number:4} }</span>
  16775          </d iv>
  16776        </fil e>
  16777        <file  name="pro tractor.js " type="pr otractor">
  16778          it( 'should fo rmat numbe rs', funct ion() {
  16779            e xpect(elem ent(by.id( 'number-de fault')).g etText()). toBe('1,23 4.568');
  16780            e xpect(elem ent(by.bin ding('val  | number:0 ')).getTex t()).toBe( '1,235');
  16781            e xpect(elem ent(by.bin ding('-val  | number: 4')).getTe xt()).toBe ('-1,234.5 679');
  16782          });
  16783  
  16784          it( 'should up date', fun ction() {
  16785            e lement(by. model('val ')).clear( );
  16786            e lement(by. model('val ')).sendKe ys('3374.3 33');
  16787            e xpect(elem ent(by.id( 'number-de fault')).g etText()). toBe('3,37 4.333');
  16788            e xpect(elem ent(by.bin ding('val  | number:0 ')).getTex t()).toBe( '3,374');
  16789            e xpect(elem ent(by.bin ding('-val  | number: 4')).getTe xt()).toBe ('-3,374.3 330');
  16790         });
  16791        </fil e>
  16792      </examp le>
  16793    */
  16794  
  16795  
  16796   numberFilt er.$inject  = ['$loca le'];
  16797   function n umberFilte r($locale)  {
  16798     var form ats = $loc ale.NUMBER _FORMATS;
  16799     return f unction(nu mber, frac tionSize)  {
  16800  
  16801       // if  null or un defined pa ss it thro ugh
  16802       return  (number = = null)
  16803           ?  number
  16804           :  formatNumb er(number,  formats.P ATTERNS[0] , formats. GROUP_SEP,  formats.D ECIMAL_SEP ,
  16805                            fractio nSize);
  16806     };
  16807   }
  16808  
  16809   var DECIMA L_SEP = '. ';
  16810   function f ormatNumbe r(number,  pattern, g roupSep, d ecimalSep,  fractionS ize) {
  16811     if (!isF inite(numb er) || isO bject(numb er)) retur n '';
  16812  
  16813     var isNe gative = n umber < 0;
  16814     number =  Math.abs( number);
  16815     var numS tr = numbe r + '',
  16816         form atedText =  '',
  16817         part s = [];
  16818  
  16819     var hasE xponent =  false;
  16820     if (numS tr.indexOf ('e') !==  -1) {
  16821       var ma tch = numS tr.match(/ ([\d\.]+)e (-?)(\d+)/ );
  16822       if (ma tch && mat ch[2] == ' -' && matc h[3] > fra ctionSize  + 1) {
  16823         numS tr = '0';
  16824         numb er = 0;
  16825       } else  {
  16826         form atedText =  numStr;
  16827         hasE xponent =  true;
  16828       }
  16829     }
  16830  
  16831     if (!has Exponent)  {
  16832       var fr actionLen  = (numStr. split(DECI MAL_SEP)[1 ] || '').l ength;
  16833  
  16834       // det ermine fra ctionSize  if it is n ot specifi ed
  16835       if (is Undefined( fractionSi ze)) {
  16836         frac tionSize =  Math.min( Math.max(p attern.min Frac, frac tionLen),  pattern.ma xFrac);
  16837       }
  16838  
  16839       // saf ely round  numbers in  JS withou t hitting  imprecisio ns of floa ting-point  arithmeti cs
  16840       // ins pired by:
  16841       // htt ps://devel oper.mozil la.org/en- US/docs/We b/JavaScri pt/Referen ce/Global_ Objects/Ma th/round
  16842       number  = +(Math. round(+(nu mber.toStr ing() + 'e ' + fracti onSize)).t oString()  + 'e' + -f ractionSiz e);
  16843  
  16844       if (nu mber === 0 ) {
  16845         isNe gative = f alse;
  16846       }
  16847  
  16848       var fr action = ( '' + numbe r).split(D ECIMAL_SEP );
  16849       var wh ole = frac tion[0];
  16850       fracti on = fract ion[1] ||  '';
  16851  
  16852       var i,  pos = 0,
  16853           lg roup = pat tern.lgSiz e,
  16854           gr oup = patt ern.gSize;
  16855  
  16856       if (wh ole.length  >= (lgrou p + group) ) {
  16857         pos  = whole.le ngth - lgr oup;
  16858         for  (i = 0; i  < pos; i++ ) {
  16859           if  ((pos - i ) % group  === 0 && i  !== 0) {
  16860              formatedTe xt += grou pSep;
  16861           }
  16862           fo rmatedText  += whole. charAt(i);
  16863         }
  16864       }
  16865  
  16866       for (i  = pos; i  < whole.le ngth; i++)  {
  16867         if ( (whole.len gth - i) %  lgroup == = 0 && i ! == 0) {
  16868           fo rmatedText  += groupS ep;
  16869         }
  16870         form atedText + = whole.ch arAt(i);
  16871       }
  16872  
  16873       // for mat fracti on part.
  16874       while  (fraction. length < f ractionSiz e) {
  16875         frac tion += '0 ';
  16876       }
  16877  
  16878       if (fr actionSize  && fracti onSize !==  "0") form atedText + = decimalS ep + fract ion.substr (0, fracti onSize);
  16879     } else {
  16880  
  16881       if (fr actionSize  > 0 && nu mber > -1  && number  < 1) {
  16882         form atedText =  number.to Fixed(frac tionSize);
  16883       }
  16884     }
  16885  
  16886     parts.pu sh(isNegat ive ? patt ern.negPre  : pattern .posPre,
  16887                 formate dText,
  16888                 isNegat ive ? patt ern.negSuf  : pattern .posSuf);
  16889     return p arts.join( '');
  16890   }
  16891  
  16892   function p adNumber(n um, digits , trim) {
  16893     var neg  = '';
  16894     if (num  < 0) {
  16895       neg =   '-';
  16896       num =  -num;
  16897     }
  16898     num = ''  + num;
  16899     while (n um.length  < digits)  num = '0'  + num;
  16900     if (trim )
  16901       num =  num.substr (num.lengt h - digits );
  16902     return n eg + num;
  16903   }
  16904  
  16905  
  16906   function d ateGetter( name, size , offset,  trim) {
  16907     offset =  offset ||  0;
  16908     return f unction(da te) {
  16909       var va lue = date ['get' + n ame]();
  16910       if (of fset > 0 | | value >  -offset)
  16911         valu e += offse t;
  16912       if (va lue === 0  && offset  == -12) va lue = 12;
  16913       return  padNumber (value, si ze, trim);
  16914     };
  16915   }
  16916  
  16917   function d ateStrGett er(name, s hortForm)  {
  16918     return f unction(da te, format s) {
  16919       var va lue = date ['get' + n ame]();
  16920       var ge t = upperc ase(shortF orm ? ('SH ORT' + nam e) : name) ;
  16921  
  16922       return  formats[g et][value] ;
  16923     };
  16924   }
  16925  
  16926   function t imeZoneGet ter(date)  {
  16927     var zone  = -1 * da te.getTime zoneOffset ();
  16928     var padd edZone = ( zone >= 0)  ? "+" : " ";
  16929  
  16930     paddedZo ne += padN umber(Math [zone > 0  ? 'floor'  : 'ceil']( zone / 60) , 2) +
  16931                    padN umber(Math .abs(zone  % 60), 2);
  16932  
  16933     return p addedZone;
  16934   }
  16935  
  16936   function g etFirstThu rsdayOfYea r(year) {
  16937       // 0 =  index of  January
  16938       var da yOfWeekOnF irst = (ne w Date(yea r, 0, 1)). getDay();
  16939       // 4 =  index of  Thursday ( +1 to acco unt for 1s t = 5)
  16940       // 11  = index of  *next* Th ursday (+1  account f or 1st = 1 2)
  16941       return  new Date( year, 0, ( (dayOfWeek OnFirst <=  4) ? 5 :  12) - dayO fWeekOnFir st);
  16942   }
  16943  
  16944   function g etThursday ThisWeek(d atetime) {
  16945       return  new Date( datetime.g etFullYear (), dateti me.getMont h(),
  16946         // 4  = index o f Thursday
  16947         date time.getDa te() + (4  - datetime .getDay()) );
  16948   }
  16949  
  16950   function w eekGetter( size) {
  16951      return  function(d ate) {
  16952         var  firstThurs  = getFirs tThursdayO fYear(date .getFullYe ar()),
  16953            t hisThurs =  getThursd ayThisWeek (date);
  16954  
  16955         var  diff = +th isThurs -  +firstThur s,
  16956            r esult = 1  + Math.rou nd(diff /  6.048e8);  // 6.048e8  ms per we ek
  16957  
  16958         retu rn padNumb er(result,  size);
  16959      };
  16960   }
  16961  
  16962   function a mpmGetter( date, form ats) {
  16963     return d ate.getHou rs() < 12  ? formats. AMPMS[0] :  formats.A MPMS[1];
  16964   }
  16965  
  16966   var DATE_F ORMATS = {
  16967     yyyy: da teGetter(' FullYear',  4),
  16968       yy: da teGetter(' FullYear',  2, 0, tru e),
  16969        y: da teGetter(' FullYear',  1),
  16970     MMMM: da teStrGette r('Month') ,
  16971      MMM: da teStrGette r('Month',  true),
  16972       MM: da teGetter(' Month', 2,  1),
  16973        M: da teGetter(' Month', 1,  1),
  16974       dd: da teGetter(' Date', 2),
  16975        d: da teGetter(' Date', 1),
  16976       HH: da teGetter(' Hours', 2) ,
  16977        H: da teGetter(' Hours', 1) ,
  16978       hh: da teGetter(' Hours', 2,  -12),
  16979        h: da teGetter(' Hours', 1,  -12),
  16980       mm: da teGetter(' Minutes',  2),
  16981        m: da teGetter(' Minutes',  1),
  16982       ss: da teGetter(' Seconds',  2),
  16983        s: da teGetter(' Seconds',  1),
  16984        // wh ile ISO 86 01 require s fraction s to be pr efixed wit h `.` or ` ,`
  16985        // we  can be ju st safely  rely on us ing `sss`  since we c urrently d on't suppo rt single  or two dig it fractio ns
  16986      sss: da teGetter(' Millisecon ds', 3),
  16987     EEEE: da teStrGette r('Day'),
  16988      EEE: da teStrGette r('Day', t rue),
  16989        a: am pmGetter,
  16990        Z: ti meZoneGett er,
  16991       ww: we ekGetter(2 ),
  16992        w: we ekGetter(1 )
  16993   };
  16994  
  16995   var DATE_F ORMATS_SPL IT = /((?: [^yMdHhmsa ZEw']+)|(? :'(?:[^']| '')*')|(?: E+|y+|M+|d +|H+|h+|m+ |s+|a|Z|w+ ))(.*)/,
  16996       NUMBER _STRING =  /^\-?\d+$/ ;
  16997  
  16998   /**
  16999    * @ngdoc  filter
  17000    * @name d ate
  17001    * @kind f unction
  17002    *
  17003    * @descri ption
  17004    *   Forma ts `date`  to a strin g based on  the reque sted `form at`.
  17005    *
  17006    *   `form at` string  can be co mposed of  the follow ing elemen ts:
  17007    *
  17008    *   * `'y yyy'`: 4 d igit repre sentation  of year (e .g. AD 1 = > 0001, AD  2010 => 2 010)
  17009    *   * `'y y'`: 2 dig it represe ntation of  year, pad ded (00-99 ). (e.g. A D 2001 =>  01, AD 201 0 => 10)
  17010    *   * `'y '`: 1 digi t represen tation of  year, e.g.  (AD 1 =>  1, AD 199  => 199)
  17011    *   * `'M MMM'`: Mon th in year  (January- December)
  17012    *   * `'M MM'`: Mont h in year  (Jan-Dec)
  17013    *   * `'M M'`: Month  in year,  padded (01 -12)
  17014    *   * `'M '`: Month  in year (1 -12)
  17015    *   * `'d d'`: Day i n month, p added (01- 31)
  17016    *   * `'d '`: Day in  month (1- 31)
  17017    *   * `'E EEE'`: Day  in Week,( Sunday-Sat urday)
  17018    *   * `'E EE'`: Day  in Week, ( Sun-Sat)
  17019    *   * `'H H'`: Hour  in day, pa dded (00-2 3)
  17020    *   * `'H '`: Hour i n day (0-2 3)
  17021    *   * `'h h'`: Hour  in AM/PM,  padded (01 -12)
  17022    *   * `'h '`: Hour i n AM/PM, ( 1-12)
  17023    *   * `'m m'`: Minut e in hour,  padded (0 0-59)
  17024    *   * `'m '`: Minute  in hour ( 0-59)
  17025    *   * `'s s'`: Secon d in minut e, padded  (00-59)
  17026    *   * `'s '`: Second  in minute  (0-59)
  17027    *   * `'. sss' or ', sss'`: Mil lisecond i n second,  padded (00 0-999)
  17028    *   * `'a '`: AM/PM  marker
  17029    *   * `'Z '`: 4 digi t (+sign)  representa tion of th e timezone  offset (- 1200-+1200 )
  17030    *   * `'w w'`: ISO-8 601 week o f year (00 -53)
  17031    *   * `'w '`: ISO-86 01 week of  year (0-5 3)
  17032    *
  17033    *   `form at` string  can also  be one of  the follow ing predef ined
  17034    *   {@lin k guide/i1 8n localiz able forma ts}:
  17035    *
  17036    *   * `'m edium'`: e quivalent  to `'MMM d , y h:mm:s s a'` for  en_US loca le
  17037    *     (e. g. Sep 3,  2010 12:05 :08 PM)
  17038    *   * `'s hort'`: eq uivalent t o `'M/d/yy  h:mm a'`  for en_US   locale (e .g. 9/3/10  12:05 PM)
  17039    *   * `'f ullDate'`:  equivalen t to `'EEE E, MMMM d,  y'` for e n_US  loca le
  17040    *     (e. g. Friday,  September  3, 2010)
  17041    *   * `'l ongDate'`:  equivalen t to `'MMM M d, y'` f or en_US   locale (e. g. Septemb er 3, 2010 )
  17042    *   * `'m ediumDate' `: equival ent to `'M MM d, y'`  for en_US   locale (e .g. Sep 3,  2010)
  17043    *   * `'s hortDate'` : equivale nt to `'M/ d/yy'` for  en_US loc ale (e.g.  9/3/10)
  17044    *   * `'m ediumTime' `: equival ent to `'h :mm:ss a'`  for en_US  locale (e .g. 12:05: 08 PM)
  17045    *   * `'s hortTime'` : equivale nt to `'h: mm a'` for  en_US loc ale (e.g.  12:05 PM)
  17046    *
  17047    *   `form at` string  can conta in literal  values. T hese need  to be esca ped by sur rounding w ith single  quotes (e .g.
  17048    *   `"h ' in the mor ning'"`).  In order t o output a  single qu ote, escap e it - i.e ., two sin gle quotes  in a sequ ence
  17049    *   (e.g.  `"h 'o''c lock'"`).
  17050    *
  17051    * @param  {(Date|num ber|string )} date Da te to form at either  as Date ob ject, mill iseconds ( string or
  17052    *    numb er) or var ious ISO 8 601 dateti me string  formats (e .g. yyyy-M M-ddTHH:mm :ss.sssZ a nd its
  17053    *    shor ter versio ns like yy yy-MM-ddTH H:mmZ, yyy y-MM-dd or  yyyyMMddT HHmmssZ).  If no time zone is
  17054    *    spec ified in t he string  input, the  time is c onsidered  to be in t he local t imezone.
  17055    * @param  {string=}  format For matting ru les (see D escription ). If not  specified,
  17056    *    `med iumDate` i s used.
  17057    * @param  {string=}  timezone T imezone to  be used f or formatt ing. Right  now, only  `'UTC'` i s supporte d.
  17058    *    If n ot specifi ed, the ti mezone of  the browse r will be  used.
  17059    * @return s {string}  Formatted  string or  the input  if input  is not rec ognized as  date/mill is.
  17060    *
  17061    * @exampl e
  17062      <exampl e>
  17063        <file  name="ind ex.html">
  17064          <sp an ng-non- bindable>{ {128832362 3006 | dat e:'medium' }}</span>:
  17065               <span>{{1 2883236230 06 | date: 'medium'}} </span><br >
  17066          <sp an ng-non- bindable>{ {128832362 3006 | dat e:'yyyy-MM -dd HH:mm: ss Z'}}</s pan>:
  17067              <span>{{12 8832362300 6 | date:' yyyy-MM-dd  HH:mm:ss  Z'}}</span ><br>
  17068          <sp an ng-non- bindable>{ {128832362 3006 | dat e:'MM/dd/y yyy @ h:mm a'}}</span >:
  17069              <span>{{'1 2883236230 06' | date :'MM/dd/yy yy @ h:mma '}}</span> <br>
  17070          <sp an ng-non- bindable>{ {128832362 3006 | dat e:"MM/dd/y yyy 'at' h :mma"}}</s pan>:
  17071              <span>{{'1 2883236230 06' | date :"MM/dd/yy yy 'at' h: mma"}}</sp an><br>
  17072        </fil e>
  17073        <file  name="pro tractor.js " type="pr otractor">
  17074          it( 'should fo rmat date' , function () {
  17075            e xpect(elem ent(by.bin ding("1288 323623006  | date:'me dium'")).g etText()).
  17076                toMatch( /Oct 2\d,  2010 \d{1, 2}:\d{2}:\ d{2} (AM|P M)/);
  17077            e xpect(elem ent(by.bin ding("1288 323623006  | date:'yy yy-MM-dd H H:mm:ss Z' ")).getTex t()).
  17078                toMatch( /2010\-10\ -2\d \d{2} :\d{2}:\d{ 2} (\-|\+) ?\d{4}/);
  17079            e xpect(elem ent(by.bin ding("'128 8323623006 ' | date:' MM/dd/yyyy  @ h:mma'" )).getText ()).
  17080                toMatch( /10\/2\d\/ 2010 @ \d{ 1,2}:\d{2} (AM|PM)/);
  17081            e xpect(elem ent(by.bin ding("'128 8323623006 ' | date:\ "MM/dd/yyy y 'at' h:m ma\"")).ge tText()).
  17082                toMatch( /10\/2\d\/ 2010 at \d {1,2}:\d{2 }(AM|PM)/) ;
  17083          });
  17084        </fil e>
  17085      </examp le>
  17086    */
  17087   dateFilter .$inject =  ['$locale '];
  17088   function d ateFilter( $locale) {
  17089  
  17090  
  17091     var R_IS O8601_STR  = /^(\d{4} )-?(\d\d)- ?(\d\d)(?: T(\d\d)(?: :?(\d\d)(? ::?(\d\d)( ?:\.(\d+)) ?)?)?(Z|([ +-])(\d\d) :?(\d\d))? )?$/;
  17092                          // 1         2        3          4           5           6           7           8  9      10       11
  17093     function  jsonStrin gToDate(st ring) {
  17094       var ma tch;
  17095       if (ma tch = stri ng.match(R _ISO8601_S TR)) {
  17096         var  date = new  Date(0),
  17097              tzHour = 0 ,
  17098              tzMin  = 0 ,
  17099              dateSetter  = match[8 ] ? date.s etUTCFullY ear : date .setFullYe ar,
  17100              timeSetter  = match[8 ] ? date.s etUTCHours  : date.se tHours;
  17101  
  17102         if ( match[9])  {
  17103           tz Hour = int (match[9]  + match[10 ]);
  17104           tz Min = int( match[9] +  match[11] );
  17105         }
  17106         date Setter.cal l(date, in t(match[1] ), int(mat ch[2]) - 1 , int(matc h[3]));
  17107         var  h = int(ma tch[4] ||  0) - tzHou r;
  17108         var  m = int(ma tch[5] ||  0) - tzMin ;
  17109         var  s = int(ma tch[6] ||  0);
  17110         var  ms = Math. round(pars eFloat('0. ' + (match [7] || 0))  * 1000);
  17111         time Setter.cal l(date, h,  m, s, ms) ;
  17112         retu rn date;
  17113       }
  17114       return  string;
  17115     }
  17116  
  17117  
  17118     return f unction(da te, format , timezone ) {
  17119       var te xt = '',
  17120           pa rts = [],
  17121           fn , match;
  17122  
  17123       format  = format  || 'medium Date';
  17124       format  = $locale .DATETIME_ FORMATS[fo rmat] || f ormat;
  17125       if (is String(dat e)) {
  17126         date  = NUMBER_ STRING.tes t(date) ?  int(date)  : jsonStri ngToDate(d ate);
  17127       }
  17128  
  17129       if (is Number(dat e)) {
  17130         date  = new Dat e(date);
  17131       }
  17132  
  17133       if (!i sDate(date )) {
  17134         retu rn date;
  17135       }
  17136  
  17137       while  (format) {
  17138         matc h = DATE_F ORMATS_SPL IT.exec(fo rmat);
  17139         if ( match) {
  17140           pa rts = conc at(parts,  match, 1);
  17141           fo rmat = par ts.pop();
  17142         } el se {
  17143           pa rts.push(f ormat);
  17144           fo rmat = nul l;
  17145         }
  17146       }
  17147  
  17148       if (ti mezone &&  timezone = == 'UTC')  {
  17149         date  = new Dat e(date.get Time());
  17150         date .setMinute s(date.get Minutes()  + date.get TimezoneOf fset());
  17151       }
  17152       forEac h(parts, f unction(va lue) {
  17153         fn =  DATE_FORM ATS[value] ;
  17154         text  += fn ? f n(date, $l ocale.DATE TIME_FORMA TS)
  17155                     : v alue.repla ce(/(^'|'$ )/g, '').r eplace(/'' /g, "'");
  17156       });
  17157  
  17158       return  text;
  17159     };
  17160   }
  17161  
  17162  
  17163   /**
  17164    * @ngdoc  filter
  17165    * @name j son
  17166    * @kind f unction
  17167    *
  17168    * @descri ption
  17169    *   Allow s you to c onvert a J avaScript  object int o JSON str ing.
  17170    *
  17171    *   This  filter is  mostly use ful for de bugging. W hen using  the double  curly {{v alue}} not ation
  17172    *   the b inding is  automatica lly conver ted to JSO N.
  17173    *
  17174    * @param  {*} object  Any JavaS cript obje ct (includ ing arrays  and primi tive types ) to filte r.
  17175    * @return s {string}  JSON stri ng.
  17176    *
  17177    *
  17178    * @exampl e
  17179      <exampl e>
  17180        <file  name="ind ex.html">
  17181          <pr e>{{ {'nam e':'value' } | json } }</pre>
  17182        </fil e>
  17183        <file  name="pro tractor.js " type="pr otractor">
  17184          it( 'should js onify filt ered objec ts', funct ion() {
  17185            e xpect(elem ent(by.bin ding("{'na me':'value '}")).getT ext()).toM atch(/\{\n   "name":  ?"value"\n }/);
  17186          });
  17187        </fil e>
  17188      </examp le>
  17189    *
  17190    */
  17191   function j sonFilter( ) {
  17192     return f unction(ob ject) {
  17193       return  toJson(ob ject, true );
  17194     };
  17195   }
  17196  
  17197  
  17198   /**
  17199    * @ngdoc  filter
  17200    * @name l owercase
  17201    * @kind f unction
  17202    * @descri ption
  17203    * Convert s string t o lowercas e.
  17204    * @see an gular.lowe rcase
  17205    */
  17206   var lowerc aseFilter  = valueFn( lowercase) ;
  17207  
  17208  
  17209   /**
  17210    * @ngdoc  filter
  17211    * @name u ppercase
  17212    * @kind f unction
  17213    * @descri ption
  17214    * Convert s string t o uppercas e.
  17215    * @see an gular.uppe rcase
  17216    */
  17217   var upperc aseFilter  = valueFn( uppercase) ;
  17218  
  17219   /**
  17220    * @ngdoc  filter
  17221    * @name l imitTo
  17222    * @kind f unction
  17223    *
  17224    * @descri ption
  17225    * Creates  a new arr ay or stri ng contain ing only a  specified  number of  elements.  The eleme nts
  17226    * are tak en from ei ther the b eginning o r the end  of the sou rce array,  string or  number, a s specifie d by
  17227    * the val ue and sig n (positiv e or negat ive) of `l imit`. If  a number i s used as  input, it  is
  17228    * convert ed to a st ring.
  17229    *
  17230    * @param  {Array|str ing|number } input So urce array , string o r number t o be limit ed.
  17231    * @param  {string|nu mber} limi t The leng th of the  returned a rray or st ring. If t he `limit`  number
  17232    *     is  positive,  `limit` nu mber of it ems from t he beginni ng of the  source arr ay/string  are copied .
  17233    *     If  the number  is negati ve, `limit ` number   of items f rom the en d of the s ource arra y/string
  17234    *     are  copied. T he `limit`  will be t rimmed if  it exceeds  `array.le ngth`
  17235    * @return s {Array|s tring} A n ew sub-arr ay or subs tring of l ength `lim it` or les s if input  array
  17236    *     had  less than  `limit` e lements.
  17237    *
  17238    * @exampl e
  17239      <exampl e module=" limitToExa mple">
  17240        <file  name="ind ex.html">
  17241          <sc ript>
  17242            a ngular.mod ule('limit ToExample' , [])
  17243               .controll er('Exampl eControlle r', ['$sco pe', funct ion($scope ) {
  17244                 $scope. numbers =  [1,2,3,4,5 ,6,7,8,9];
  17245                 $scope. letters =  "abcdefghi ";
  17246                 $scope. longNumber  = 2345432 342;
  17247                 $scope. numLimit =  3;
  17248                 $scope. letterLimi t = 3;
  17249                 $scope. longNumber Limit = 3;
  17250               }]);
  17251          </s cript>
  17252          <di v ng-contr oller="Exa mpleContro ller">
  17253            L imit {{num bers}} to:  <input ty pe="number " step="1"  ng-model= "numLimit" >
  17254            < p>Output n umbers: {{  numbers |  limitTo:n umLimit }} </p>
  17255            L imit {{let ters}} to:  <input ty pe="number " step="1"  ng-model= "letterLim it">
  17256            < p>Output l etters: {{  letters |  limitTo:l etterLimit  }}</p>
  17257            L imit {{lon gNumber}}  to: <input  type="num ber" step= "1" ng-mod el="longNu mberLimit" >
  17258            < p>Output l ong number : {{ longN umber | li mitTo:long NumberLimi t }}</p>
  17259          </d iv>
  17260        </fil e>
  17261        <file  name="pro tractor.js " type="pr otractor">
  17262          var  numLimitI nput = ele ment(by.mo del('numLi mit'));
  17263          var  letterLim itInput =  element(by .model('le tterLimit' ));
  17264          var  longNumbe rLimitInpu t = elemen t(by.model ('longNumb erLimit')) ;
  17265          var  limitedNu mbers = el ement(by.b inding('nu mbers | li mitTo:numL imit'));
  17266          var  limitedLe tters = el ement(by.b inding('le tters | li mitTo:lett erLimit')) ;
  17267          var  limitedLo ngNumber =  element(b y.binding( 'longNumbe r | limitT o:longNumb erLimit')) ;
  17268  
  17269          it( 'should li mit the nu mber array  to first  three item s', functi on() {
  17270            e xpect(numL imitInput. getAttribu te('value' )).toBe('3 ');
  17271            e xpect(lett erLimitInp ut.getAttr ibute('val ue')).toBe ('3');
  17272            e xpect(long NumberLimi tInput.get Attribute( 'value')). toBe('3');
  17273            e xpect(limi tedNumbers .getText() ).toEqual( 'Output nu mbers: [1, 2,3]');
  17274            e xpect(limi tedLetters .getText() ).toEqual( 'Output le tters: abc ');
  17275            e xpect(limi tedLongNum ber.getTex t()).toEqu al('Output  long numb er: 234');
  17276          });
  17277  
  17278          //  There is a  bug in sa fari and p rotractor  that doesn 't like th e minus ke y
  17279          //  it('should  update th e output w hen -3 is  entered',  function()  {
  17280          //    numLimit Input.clea r();
  17281          //    numLimit Input.send Keys('-3') ;
  17282          //    letterLi mitInput.c lear();
  17283          //    letterLi mitInput.s endKeys('- 3');
  17284          //    longNumb erLimitInp ut.clear() ;
  17285          //    longNumb erLimitInp ut.sendKey s('-3');
  17286          //    expect(l imitedNumb ers.getTex t()).toEqu al('Output  numbers:  [7,8,9]');
  17287          //    expect(l imitedLett ers.getTex t()).toEqu al('Output  letters:  ghi');
  17288          //    expect(l imitedLong Number.get Text()).to Equal('Out put long n umber: 342 ');
  17289          //  });
  17290  
  17291          it( 'should no t exceed t he maximum  size of i nput array ', functio n() {
  17292            n umLimitInp ut.clear() ;
  17293            n umLimitInp ut.sendKey s('100');
  17294            l etterLimit Input.clea r();
  17295            l etterLimit Input.send Keys('100' );
  17296            l ongNumberL imitInput. clear();
  17297            l ongNumberL imitInput. sendKeys(' 100');
  17298            e xpect(limi tedNumbers .getText() ).toEqual( 'Output nu mbers: [1, 2,3,4,5,6, 7,8,9]');
  17299            e xpect(limi tedLetters .getText() ).toEqual( 'Output le tters: abc defghi');
  17300            e xpect(limi tedLongNum ber.getTex t()).toEqu al('Output  long numb er: 234543 2342');
  17301          });
  17302        </fil e>
  17303      </examp le>
  17304   */
  17305   function l imitToFilt er() {
  17306     return f unction(in put, limit ) {
  17307       if (is Number(inp ut)) input  = input.t oString();
  17308       if (!i sArray(inp ut) && !is String(inp ut)) retur n input;
  17309  
  17310       if (Ma th.abs(Num ber(limit) ) === Infi nity) {
  17311         limi t = Number (limit);
  17312       } else  {
  17313         limi t = int(li mit);
  17314       }
  17315  
  17316       if (is String(inp ut)) {
  17317         //Na N check on  limit
  17318         if ( limit) {
  17319           re turn limit  >= 0 ? in put.slice( 0, limit)  : input.sl ice(limit,  input.len gth);
  17320         } el se {
  17321           re turn "";
  17322         }
  17323       }
  17324  
  17325       var ou t = [],
  17326         i, n ;
  17327  
  17328       // if  abs(limit)  exceeds m aximum len gth, trim  it
  17329       if (li mit > inpu t.length)
  17330         limi t = input. length;
  17331       else i f (limit <  -input.le ngth)
  17332         limi t = -input .length;
  17333  
  17334       if (li mit > 0) {
  17335         i =  0;
  17336         n =  limit;
  17337       } else  {
  17338         i =  input.leng th + limit ;
  17339         n =  input.leng th;
  17340       }
  17341  
  17342       for (;  i < n; i+ +) {
  17343         out. push(input [i]);
  17344       }
  17345  
  17346       return  out;
  17347     };
  17348   }
  17349  
  17350   /**
  17351    * @ngdoc  filter
  17352    * @name o rderBy
  17353    * @kind f unction
  17354    *
  17355    * @descri ption
  17356    * Orders  a specifie d `array`  by the `ex pression`  predicate.  It is ord ered alpha betically
  17357    * for str ings and n umerically  for numbe rs. Note:  if you not ice number s are not  being sort ed
  17358    * correct ly, make s ure they a re actuall y being sa ved as num bers and n ot strings .
  17359    *
  17360    * @param  {Array} ar ray The ar ray to sor t.
  17361    * @param  {function( *)|string| Array.<(fu nction(*)| string)>=}  expressio n A predic ate to be
  17362    *    used  by the co mparator t o determin e the orde r of eleme nts.
  17363    *
  17364    *    Can  be one of:
  17365    *
  17366    *    - `f unction`:  Getter fun ction. The  result of  this func tion will  be sorted  using the
  17367    *      `< `, `=`, `> ` operator .
  17368    *    - `s tring`: An  Angular e xpression.  The resul t of this  expression  is used t o compare  elements
  17369    *      (f or example  `name` to  sort by a  property  called `na me` or `na me.substr( 0, 3)` to  sort by
  17370    *      3  first char acters of  a property  called `n ame`). The  result of  a constan t expressi on
  17371    *      is  interpret ed as a pr operty nam e to be us ed in comp arisons (f or example  `"special  name"`
  17372    *      to  sort obje ct by the  value of t heir `spec ial name`  property).  An expres sion can b e
  17373    *      op tionally p refixed wi th `+` or  `-` to con trol ascen ding or de scending s ort order
  17374    *      (f or example , `+name`  or `-name` ). If no p roperty is  provided,  (e.g. `'+ '`) then t he array
  17375    *      el ement itse lf is used  to compar e where so rting.
  17376    *    - `A rray`: An  array of f unction or  string pr edicates.  The first  predicate  in the arr ay
  17377    *      is  used for  sorting, b ut when tw o items ar e equivale nt, the ne xt predica te is used .
  17378    *
  17379    *    If t he predica te is miss ing or emp ty then it  defaults  to `'+'`.
  17380    *
  17381    * @param  {boolean=}  reverse R everse the  order of  the array.
  17382    * @return s {Array}  Sorted cop y of the s ource arra y.
  17383    *
  17384    * @exampl e
  17385      <exampl e module=" orderByExa mple">
  17386        <file  name="ind ex.html">
  17387          <sc ript>
  17388            a ngular.mod ule('order ByExample' , [])
  17389               .controll er('Exampl eControlle r', ['$sco pe', funct ion($scope ) {
  17390                 $scope. friends =
  17391                     [{n ame:'John' , phone:'5 55-1212',  age:10},
  17392                      {n ame:'Mary' , phone:'5 55-9876',  age:19},
  17393                      {n ame:'Mike' , phone:'5 55-4321',  age:21},
  17394                      {n ame:'Adam' , phone:'5 55-5678',  age:35},
  17395                      {n ame:'Julie ', phone:' 555-8765',  age:29}];
  17396                 $scope. predicate  = '-age';
  17397               }]);
  17398          </s cript>
  17399          <di v ng-contr oller="Exa mpleContro ller">
  17400            < pre>Sortin g predicat e = {{pred icate}}; r everse = { {reverse}} </pre>
  17401            < hr/>
  17402            [  <a href=" " ng-click ="predicat e=''">unso rted</a> ]
  17403            < table clas s="friend" >
  17404               <tr>
  17405                 <th><a  href="" ng -click="pr edicate =  'name'; re verse=fals e">Name</a >
  17406                     (<a  href="" n g-click="p redicate =  '-name';  reverse=fa lse">^</a> )</th>
  17407                 <th><a  href="" ng -click="pr edicate =  'phone'; r everse=!re verse">Pho ne Number< /a></th>
  17408                 <th><a  href="" ng -click="pr edicate =  'age'; rev erse=!reve rse">Age</ a></th>
  17409               </tr>
  17410               <tr ng-re peat="frie nd in frie nds | orde rBy:predic ate:revers e">
  17411                 <td>{{f riend.name }}</td>
  17412                 <td>{{f riend.phon e}}</td>
  17413                 <td>{{f riend.age} }</td>
  17414               </tr>
  17415            < /table>
  17416          </d iv>
  17417        </fil e>
  17418      </examp le>
  17419    *
  17420    * It's al so possibl e to call  the orderB y filter m anually, b y injectin g `$filter `, retriev ing the
  17421    * filter  routine wi th `$filte r('orderBy ')`, and c alling the  returned  filter rou tine with  the
  17422    * desired  parameter s.
  17423    *
  17424    * Example :
  17425    *
  17426    * @exampl e
  17427     <example  module="o rderByExam ple">
  17428       <file  name="inde x.html">
  17429         <div  ng-contro ller="Exam pleControl ler">
  17430           <t able class ="friend">
  17431              <tr>
  17432                <th><a h ref="" ng- click="rev erse=false ;order('na me', false )">Name</a >
  17433                  (<a hr ef="" ng-c lick="orde r('-name', false)">^< /a>)</th>
  17434                <th><a h ref="" ng- click="rev erse=!reve rse;order( 'phone', r everse)">P hone Numbe r</a></th>
  17435                <th><a h ref="" ng- click="rev erse=!reve rse;order( 'age',reve rse)">Age< /a></th>
  17436              </tr>
  17437              <tr ng-rep eat="frien d in frien ds">
  17438                <td>{{fr iend.name} }</td>
  17439                <td>{{fr iend.phone }}</td>
  17440                <td>{{fr iend.age}} </td>
  17441              </tr>
  17442           </ table>
  17443         </di v>
  17444       </file >
  17445  
  17446       <file  name="scri pt.js">
  17447         angu lar.module ('orderByE xample', [ ])
  17448           .c ontroller( 'ExampleCo ntroller',  ['$scope' , '$filter ', functio n($scope,  $filter) {
  17449              var orderB y = $filte r('orderBy ');
  17450              $scope.fri ends = [
  17451                { name:  'John',     phone: '5 55-1212',     age: 10  },
  17452                { name:  'Mary',     phone: '5 55-9876',     age: 19  },
  17453                { name:  'Mike',     phone: '5 55-4321',     age: 21  },
  17454                { name:  'Adam',     phone: '5 55-5678',     age: 35  },
  17455                { name:  'Julie',    phone: '5 55-8765',     age: 29  }
  17456              ];
  17457              $scope.ord er = funct ion(predic ate, rever se) {
  17458                $scope.f riends = o rderBy($sc ope.friend s, predica te, revers e);
  17459              };
  17460              $scope.ord er('-age', false);
  17461           }] );
  17462       </file >
  17463   </example>
  17464    */
  17465   orderByFil ter.$injec t = ['$par se'];
  17466   function o rderByFilt er($parse)  {
  17467     return f unction(ar ray, sortP redicate,  reverseOrd er) {
  17468       if (!( isArrayLik e(array)))  return ar ray;
  17469       sortPr edicate =  isArray(so rtPredicat e) ? sortP redicate :  [sortPred icate];
  17470       if (so rtPredicat e.length = == 0) { so rtPredicat e = ['+'];  }
  17471       sortPr edicate =  sortPredic ate.map(fu nction(pre dicate) {
  17472         var  descending  = false,  get = pred icate || i dentity;
  17473         if ( isString(p redicate))  {
  17474           if  ((predica te.charAt( 0) == '+'  || predica te.charAt( 0) == '-') ) {
  17475              descending  = predica te.charAt( 0) == '-';
  17476              predicate  = predicat e.substrin g(1);
  17477           }
  17478           if  (predicat e === '')  {
  17479              // Effecti vely no pr edicate wa s passed s o we compa re identit y
  17480              return rev erseCompar ator(funct ion(a, b)  {
  17481                return c ompare(a,  b);
  17482              }, descend ing);
  17483           }
  17484           ge t = $parse (predicate );
  17485           if  (get.cons tant) {
  17486              var key =  get();
  17487              return rev erseCompar ator(funct ion(a, b)  {
  17488                return c ompare(a[k ey], b[key ]);
  17489              }, descend ing);
  17490           }
  17491         }
  17492         retu rn reverse Comparator (function( a, b) {
  17493           re turn compa re(get(a), get(b));
  17494         }, d escending) ;
  17495       });
  17496       return  slice.cal l(array).s ort(revers eComparato r(comparat or, revers eOrder));
  17497  
  17498       functi on compara tor(o1, o2 ) {
  17499         for  (var i = 0 ; i < sort Predicate. length; i+ +) {
  17500           va r comp = s ortPredica te[i](o1,  o2);
  17501           if  (comp !==  0) return  comp;
  17502         }
  17503         retu rn 0;
  17504       }
  17505       functi on reverse Comparator (comp, des cending) {
  17506         retu rn descend ing
  17507              ? function (a, b) {re turn comp( b,a);}
  17508              : comp;
  17509       }
  17510       functi on compare (v1, v2) {
  17511         var  t1 = typeo f v1;
  17512         var  t2 = typeo f v2;
  17513         if ( t1 == t2)  {
  17514           if  (isDate(v 1) && isDa te(v2)) {
  17515              v1 = v1.va lueOf();
  17516              v2 = v2.va lueOf();
  17517           }
  17518           if  (t1 == "s tring") {
  17519               v1 = v1.t oLowerCase ();
  17520               v2 = v2.t oLowerCase ();
  17521           }
  17522           if  (v1 === v 2) return  0;
  17523           re turn v1 <  v2 ? -1 :  1;
  17524         } el se {
  17525           re turn t1 <  t2 ? -1 :  1;
  17526         }
  17527       }
  17528     };
  17529   }
  17530  
  17531   function n gDirective (directive ) {
  17532     if (isFu nction(dir ective)) {
  17533       direct ive = {
  17534         link : directiv e
  17535       };
  17536     }
  17537     directiv e.restrict  = directi ve.restric t || 'AC';
  17538     return v alueFn(dir ective);
  17539   }
  17540  
  17541   /**
  17542    * @ngdoc  directive
  17543    * @name a
  17544    * @restri ct E
  17545    *
  17546    * @descri ption
  17547    * Modifie s the defa ult behavi or of the  html A tag  so that t he default  action is  prevented  when
  17548    * the hre f attribut e is empty .
  17549    *
  17550    * This ch ange permi ts the eas y creation  of action  links wit h the `ngC lick` dire ctive
  17551    * without  changing  the locati on or caus ing page r eloads, e. g.:
  17552    * `<a hre f="" ng-cl ick="list. addItem()" >Add Item< /a>`
  17553    */
  17554   var htmlAn chorDirect ive = valu eFn({
  17555     restrict : 'E',
  17556     compile:  function( element, a ttr) {
  17557       if (!a ttr.href & & !attr.xl inkHref &&  !attr.nam e) {
  17558         retu rn functio n(scope, e lement) {
  17559           //  SVGAEleme nt does no t use the  href attri bute, but  rather the  'xlinkHre f' attribu te.
  17560           va r href = t oString.ca ll(element .prop('hre f')) === ' [object SV GAnimatedS tring]' ?
  17561                       ' xlink:href ' : 'href' ;
  17562           el ement.on(' click', fu nction(eve nt) {
  17563              // if we h ave no hre f url, the n don't na vigate any where.
  17564              if (!eleme nt.attr(hr ef)) {
  17565                event.pr eventDefau lt();
  17566              }
  17567           }) ;
  17568         };
  17569       }
  17570     }
  17571   });
  17572  
  17573   /**
  17574    * @ngdoc  directive
  17575    * @name n gHref
  17576    * @restri ct A
  17577    * @priori ty 99
  17578    *
  17579    * @descri ption
  17580    * Using A ngular mar kup like ` {{hash}}`  in an href  attribute  will
  17581    * make th e link go  to the wro ng URL if  the user c licks it b efore
  17582    * Angular  has a cha nce to rep lace the ` {{hash}}`  markup wit h its
  17583    * value.  Until Angu lar replac es the mar kup the li nk will be  broken
  17584    * and wil l most lik ely return  a 404 err or. The `n gHref` dir ective
  17585    * solves  this probl em.
  17586    *
  17587    * The wro ng way to  write it:
  17588    * ```html
  17589    * <a href ="http://w ww.gravata r.com/avat ar/{{hash} }">link1</ a>
  17590    * ```
  17591    *
  17592    * The cor rect way t o write it :
  17593    * ```html
  17594    * <a ng-h ref="http: //www.grav atar.com/a vatar/{{ha sh}}">link 1</a>
  17595    * ```
  17596    *
  17597    * @elemen t A
  17598    * @param  {template}  ngHref an y string w hich can c ontain `{{ }}` markup .
  17599    *
  17600    * @exampl e
  17601    * This ex ample show s various  combinatio ns of `hre f`, `ng-hr ef` and `n g-click` a ttributes
  17602    * in link s and thei r differen t behavior s:
  17603       <examp le>
  17604         <fil e name="in dex.html">
  17605           <i nput ng-mo del="value " /><br />
  17606           <a  id="link- 1" href ng -click="va lue = 1">l ink 1</a>  (link, don 't reload) <br />
  17607           <a  id="link- 2" href=""  ng-click= "value = 2 ">link 2</ a> (link,  don't relo ad)<br />
  17608           <a  id="link- 3" ng-href ="/{{'123' }}">link 3 </a> (link , reload!) <br />
  17609           <a  id="link- 4" href=""  name="xx"  ng-click= "value = 4 ">anchor</ a> (link,  don't relo ad)<br />
  17610           <a  id="link- 5" name="x xx" ng-cli ck="value  = 5">ancho r</a> (no  link)<br / >
  17611           <a  id="link- 6" ng-href ="{{value} }">link</a > (link, c hange loca tion)
  17612         </fi le>
  17613         <fil e name="pr otractor.j s" type="p rotractor" >
  17614           it ('should e xecute ng- click but  not reload  when href  without v alue', fun ction() {
  17615              element(by .id('link- 1')).click ();
  17616              expect(ele ment(by.mo del('value ')).getAtt ribute('va lue')).toE qual('1');
  17617              expect(ele ment(by.id ('link-1') ).getAttri bute('href ')).toBe(' ');
  17618           }) ;
  17619  
  17620           it ('should e xecute ng- click but  not reload  when href  empty str ing', func tion() {
  17621              element(by .id('link- 2')).click ();
  17622              expect(ele ment(by.mo del('value ')).getAtt ribute('va lue')).toE qual('2');
  17623              expect(ele ment(by.id ('link-2') ).getAttri bute('href ')).toBe(' ');
  17624           }) ;
  17625  
  17626           it ('should e xecute ng- click and  change url  when ng-h ref specif ied', func tion() {
  17627              expect(ele ment(by.id ('link-3') ).getAttri bute('href ')).toMatc h(/\/123$/ );
  17628  
  17629              element(by .id('link- 3')).click ();
  17630  
  17631              // At this  point, we  navigate  away from  an Angular  page, so  we need
  17632              // to use  browser.dr iver to ge t the base  webdriver .
  17633  
  17634              browser.wa it(functio n() {
  17635                return b rowser.dri ver.getCur rentUrl(). then(funct ion(url) {
  17636                  return  url.match (/\/123$/) ;
  17637                });
  17638              }, 5000, ' page shoul d navigate  to /123') ;
  17639           }) ;
  17640  
  17641           xi t('should  execute ng -click but  not reloa d when hre f empty st ring and n ame specif ied', func tion() {
  17642              element(by .id('link- 4')).click ();
  17643              expect(ele ment(by.mo del('value ')).getAtt ribute('va lue')).toE qual('4');
  17644              expect(ele ment(by.id ('link-4') ).getAttri bute('href ')).toBe(' ');
  17645           }) ;
  17646  
  17647           it ('should e xecute ng- click but  not reload  when no h ref but na me specifi ed', funct ion() {
  17648              element(by .id('link- 5')).click ();
  17649              expect(ele ment(by.mo del('value ')).getAtt ribute('va lue')).toE qual('5');
  17650              expect(ele ment(by.id ('link-5') ).getAttri bute('href ')).toBe(n ull);
  17651           }) ;
  17652  
  17653           it ('should o nly change  url when  only ng-hr ef', funct ion() {
  17654              element(by .model('va lue')).cle ar();
  17655              element(by .model('va lue')).sen dKeys('6') ;
  17656              expect(ele ment(by.id ('link-6') ).getAttri bute('href ')).toMatc h(/\/6$/);
  17657  
  17658              element(by .id('link- 6')).click ();
  17659  
  17660              // At this  point, we  navigate  away from  an Angular  page, so  we need
  17661              // to use  browser.dr iver to ge t the base  webdriver .
  17662              browser.wa it(functio n() {
  17663                return b rowser.dri ver.getCur rentUrl(). then(funct ion(url) {
  17664                  return  url.match (/\/6$/);
  17665                });
  17666              }, 5000, ' page shoul d navigate  to /6');
  17667           }) ;
  17668         </fi le>
  17669       </exam ple>
  17670    */
  17671  
  17672   /**
  17673    * @ngdoc  directive
  17674    * @name n gSrc
  17675    * @restri ct A
  17676    * @priori ty 99
  17677    *
  17678    * @descri ption
  17679    * Using A ngular mar kup like ` {{hash}}`  in a `src`  attribute  doesn't
  17680    * work ri ght: The b rowser wil l fetch fr om the URL  with the  literal
  17681    * text `{ {hash}}` u ntil Angul ar replace s the expr ession ins ide
  17682    * `{{hash }}`. The ` ngSrc` dir ective sol ves this p roblem.
  17683    *
  17684    * The bug gy way to  write it:
  17685    * ```html
  17686    * <img sr c="http:// www.gravat ar.com/ava tar/{{hash }}"/>
  17687    * ```
  17688    *
  17689    * The cor rect way t o write it :
  17690    * ```html
  17691    * <img ng -src="http ://www.gra vatar.com/ avatar/{{h ash}}"/>
  17692    * ```
  17693    *
  17694    * @elemen t IMG
  17695    * @param  {template}  ngSrc any  string wh ich can co ntain `{{} }` markup.
  17696    */
  17697  
  17698   /**
  17699    * @ngdoc  directive
  17700    * @name n gSrcset
  17701    * @restri ct A
  17702    * @priori ty 99
  17703    *
  17704    * @descri ption
  17705    * Using A ngular mar kup like ` {{hash}}`  in a `srcs et` attrib ute doesn' t
  17706    * work ri ght: The b rowser wil l fetch fr om the URL  with the  literal
  17707    * text `{ {hash}}` u ntil Angul ar replace s the expr ession ins ide
  17708    * `{{hash }}`. The ` ngSrcset`  directive  solves thi s problem.
  17709    *
  17710    * The bug gy way to  write it:
  17711    * ```html
  17712    * <img sr cset="http ://www.gra vatar.com/ avatar/{{h ash}} 2x"/ >
  17713    * ```
  17714    *
  17715    * The cor rect way t o write it :
  17716    * ```html
  17717    * <img ng -srcset="h ttp://www. gravatar.c om/avatar/ {{hash}} 2 x"/>
  17718    * ```
  17719    *
  17720    * @elemen t IMG
  17721    * @param  {template}  ngSrcset  any string  which can  contain ` {{}}` mark up.
  17722    */
  17723  
  17724   /**
  17725    * @ngdoc  directive
  17726    * @name n gDisabled
  17727    * @restri ct A
  17728    * @priori ty 100
  17729    *
  17730    * @descri ption
  17731    *
  17732    * We shou ldn't do t his, becau se it will  make the  button ena bled on Ch rome/Firef ox but not  on IE8 an d older IE s:
  17733    * ```html
  17734    * <div ng -init="sco pe = { isD isabled: f alse }">
  17735    *  <butto n disabled ="{{scope. isDisabled }}">Disabl ed</button >
  17736    * </div>
  17737    * ```
  17738    *
  17739    * The HTM L specific ation does  not requi re browser s to prese rve the va lues of bo olean attr ibutes
  17740    * such as  disabled.  (Their pr esence mea ns true an d their ab sence mean s false.)
  17741    * If we p ut an Angu lar interp olation ex pression i nto such a n attribut e then the
  17742    * binding  informati on would b e lost whe n the brow ser remove s the attr ibute.
  17743    * The `ng Disabled`  directive  solves thi s problem  for the `d isabled` a ttribute.
  17744    * This co mplementar y directiv e is not r emoved by  the browse r and so p rovides
  17745    * a perma nent relia ble place  to store t he binding  informati on.
  17746    *
  17747    * @exampl e
  17748       <examp le>
  17749         <fil e name="in dex.html">
  17750           Cl ick me to  toggle: <i nput type= "checkbox"  ng-model= "checked"> <br/>
  17751           <b utton ng-m odel="butt on" ng-dis abled="che cked">Butt on</button >
  17752         </fi le>
  17753         <fil e name="pr otractor.j s" type="p rotractor" >
  17754           it ('should t oggle butt on', funct ion() {
  17755              expect(ele ment(by.cs s('button' )).getAttr ibute('dis abled')).t oBeFalsy() ;
  17756              element(by .model('ch ecked')).c lick();
  17757              expect(ele ment(by.cs s('button' )).getAttr ibute('dis abled')).t oBeTruthy( );
  17758           }) ;
  17759         </fi le>
  17760       </exam ple>
  17761    *
  17762    * @elemen t INPUT
  17763    * @param  {expressio n} ngDisab led If the  {@link gu ide/expres sion expre ssion} is  truthy,
  17764    *     the n special  attribute  "disabled"  will be s et on the  element
  17765    */
  17766  
  17767  
  17768   /**
  17769    * @ngdoc  directive
  17770    * @name n gChecked
  17771    * @restri ct A
  17772    * @priori ty 100
  17773    *
  17774    * @descri ption
  17775    * The HTM L specific ation does  not requi re browser s to prese rve the va lues of bo olean attr ibutes
  17776    * such as  checked.  (Their pre sence mean s true and  their abs ence means  false.)
  17777    * If we p ut an Angu lar interp olation ex pression i nto such a n attribut e then the
  17778    * binding  informati on would b e lost whe n the brow ser remove s the attr ibute.
  17779    * The `ng Checked` d irective s olves this  problem f or the `ch ecked` att ribute.
  17780    * This co mplementar y directiv e is not r emoved by  the browse r and so p rovides
  17781    * a perma nent relia ble place  to store t he binding  informati on.
  17782    * @exampl e
  17783       <examp le>
  17784         <fil e name="in dex.html">
  17785           Ch eck me to  check both : <input t ype="check box" ng-mo del="maste r"><br/>
  17786           <i nput id="c heckSlave"  type="che ckbox" ng- checked="m aster">
  17787         </fi le>
  17788         <fil e name="pr otractor.j s" type="p rotractor" >
  17789           it ('should c heck both  checkBoxes ', functio n() {
  17790              expect(ele ment(by.id ('checkSla ve')).getA ttribute(' checked')) .toBeFalsy ();
  17791              element(by .model('ma ster')).cl ick();
  17792              expect(ele ment(by.id ('checkSla ve')).getA ttribute(' checked')) .toBeTruth y();
  17793           }) ;
  17794         </fi le>
  17795       </exam ple>
  17796    *
  17797    * @elemen t INPUT
  17798    * @param  {expressio n} ngCheck ed If the  {@link gui de/express ion expres sion} is t ruthy,
  17799    *     the n special  attribute  "checked"  will be se t on the e lement
  17800    */
  17801  
  17802  
  17803   /**
  17804    * @ngdoc  directive
  17805    * @name n gReadonly
  17806    * @restri ct A
  17807    * @priori ty 100
  17808    *
  17809    * @descri ption
  17810    * The HTM L specific ation does  not requi re browser s to prese rve the va lues of bo olean attr ibutes
  17811    * such as  readonly.  (Their pr esence mea ns true an d their ab sence mean s false.)
  17812    * If we p ut an Angu lar interp olation ex pression i nto such a n attribut e then the
  17813    * binding  informati on would b e lost whe n the brow ser remove s the attr ibute.
  17814    * The `ng Readonly`  directive  solves thi s problem  for the `r eadonly` a ttribute.
  17815    * This co mplementar y directiv e is not r emoved by  the browse r and so p rovides
  17816    * a perma nent relia ble place  to store t he binding  informati on.
  17817    * @exampl e
  17818       <examp le>
  17819         <fil e name="in dex.html">
  17820           Ch eck me to  make text  readonly:  <input typ e="checkbo x" ng-mode l="checked "><br/>
  17821           <i nput type= "text" ng- readonly=" checked" v alue="I'm  Angular"/>
  17822         </fi le>
  17823         <fil e name="pr otractor.j s" type="p rotractor" >
  17824           it ('should t oggle read only attr' , function () {
  17825              expect(ele ment(by.cs s('[type=" text"]')). getAttribu te('readon ly')).toBe Falsy();
  17826              element(by .model('ch ecked')).c lick();
  17827              expect(ele ment(by.cs s('[type=" text"]')). getAttribu te('readon ly')).toBe Truthy();
  17828           }) ;
  17829         </fi le>
  17830       </exam ple>
  17831    *
  17832    * @elemen t INPUT
  17833    * @param  {expressio n} ngReado nly If the  {@link gu ide/expres sion expre ssion} is  truthy,
  17834    *     the n special  attribute  "readonly"  will be s et on the  element
  17835    */
  17836  
  17837  
  17838   /**
  17839    * @ngdoc  directive
  17840    * @name n gSelected
  17841    * @restri ct A
  17842    * @priori ty 100
  17843    *
  17844    * @descri ption
  17845    * The HTM L specific ation does  not requi re browser s to prese rve the va lues of bo olean attr ibutes
  17846    * such as  selected.  (Their pr esence mea ns true an d their ab sence mean s false.)
  17847    * If we p ut an Angu lar interp olation ex pression i nto such a n attribut e then the
  17848    * binding  informati on would b e lost whe n the brow ser remove s the attr ibute.
  17849    * The `ng Selected`  directive  solves thi s problem  for the `s elected` a ttribute.
  17850    * This co mplementar y directiv e is not r emoved by  the browse r and so p rovides
  17851    * a perma nent relia ble place  to store t he binding  informati on.
  17852    *
  17853    * @exampl e
  17854       <examp le>
  17855         <fil e name="in dex.html">
  17856           Ch eck me to  select: <i nput type= "checkbox"  ng-model= "selected" ><br/>
  17857           <s elect>
  17858              <option>He llo!</opti on>
  17859              <option id ="greet" n g-selected ="selected ">Greeting s!</option >
  17860           </ select>
  17861         </fi le>
  17862         <fil e name="pr otractor.j s" type="p rotractor" >
  17863           it ('should s elect Gree tings!', f unction()  {
  17864              expect(ele ment(by.id ('greet')) .getAttrib ute('selec ted')).toB eFalsy();
  17865              element(by .model('se lected')). click();
  17866              expect(ele ment(by.id ('greet')) .getAttrib ute('selec ted')).toB eTruthy();
  17867           }) ;
  17868         </fi le>
  17869       </exam ple>
  17870    *
  17871    * @elemen t OPTION
  17872    * @param  {expressio n} ngSelec ted If the  {@link gu ide/expres sion expre ssion} is  truthy,
  17873    *     the n special  attribute  "selected"  will be s et on the  element
  17874    */
  17875  
  17876   /**
  17877    * @ngdoc  directive
  17878    * @name n gOpen
  17879    * @restri ct A
  17880    * @priori ty 100
  17881    *
  17882    * @descri ption
  17883    * The HTM L specific ation does  not requi re browser s to prese rve the va lues of bo olean attr ibutes
  17884    * such as  open. (Th eir presen ce means t rue and th eir absenc e means fa lse.)
  17885    * If we p ut an Angu lar interp olation ex pression i nto such a n attribut e then the
  17886    * binding  informati on would b e lost whe n the brow ser remove s the attr ibute.
  17887    * The `ng Open` dire ctive solv es this pr oblem for  the `open`  attribute .
  17888    * This co mplementar y directiv e is not r emoved by  the browse r and so p rovides
  17889    * a perma nent relia ble place  to store t he binding  informati on.
  17890    * @exampl e
  17891        <exam ple>
  17892          <fi le name="i ndex.html" >
  17893            C heck me ch eck multip le: <input  type="che ckbox" ng- model="ope n"><br/>
  17894            < details id ="details"  ng-open=" open">
  17895                <summary >Show/Hide  me</summa ry>
  17896            < /details>
  17897          </f ile>
  17898          <fi le name="p rotractor. js" type=" protractor ">
  17899            i t('should  toggle ope n', functi on() {
  17900               expect(el ement(by.i d('details ')).getAtt ribute('op en')).toBe Falsy();
  17901               element(b y.model('o pen')).cli ck();
  17902               expect(el ement(by.i d('details ')).getAtt ribute('op en')).toBe Truthy();
  17903            } );
  17904          </f ile>
  17905        </exa mple>
  17906    *
  17907    * @elemen t DETAILS
  17908    * @param  {expressio n} ngOpen  If the {@l ink guide/ expression  expressio n} is trut hy,
  17909    *     the n special  attribute  "open" wil l be set o n the elem ent
  17910    */
  17911  
  17912   var ngAttr ibuteAlias Directives  = {};
  17913  
  17914  
  17915   // boolean  attrs are  evaluated
  17916   forEach(BO OLEAN_ATTR , function (propName,  attrName)  {
  17917     // bindi ng to mult iple is no t supporte d
  17918     if (prop Name == "m ultiple")  return;
  17919  
  17920     var norm alized = d irectiveNo rmalize('n g-' + attr Name);
  17921     ngAttrib uteAliasDi rectives[n ormalized]  = functio n() {
  17922       return  {
  17923         rest rict: 'A',
  17924         prio rity: 100,
  17925         link : function (scope, el ement, att r) {
  17926           sc ope.$watch (attr[norm alized], f unction ng BooleanAtt rWatchActi on(value)  {
  17927              attr.$set( attrName,  !!value);
  17928           }) ;
  17929         }
  17930       };
  17931     };
  17932   });
  17933  
  17934   // aliased  input att rs are eva luated
  17935   forEach(AL IASED_ATTR , function (htmlAttr,  ngAttr) {
  17936     ngAttrib uteAliasDi rectives[n gAttr] = f unction()  {
  17937       return  {
  17938         prio rity: 100,
  17939         link : function (scope, el ement, att r) {
  17940           // special ca se ngPatte rn when a  literal re gular expr ession val ue
  17941           // is used as  the expre ssion (thi s way we d on't have  to watch a nything).
  17942           if  (ngAttr = == "ngPatt ern" && at tr.ngPatte rn.charAt( 0) == "/")  {
  17943              var match  = attr.ngP attern.mat ch(REGEX_S TRING_REGE XP);
  17944              if (match)  {
  17945                attr.$se t("ngPatte rn", new R egExp(matc h[1], matc h[2]));
  17946                return;
  17947              }
  17948           }
  17949  
  17950           sc ope.$watch (attr[ngAt tr], funct ion ngAttr AliasWatch Action(val ue) {
  17951              attr.$set( ngAttr, va lue);
  17952           }) ;
  17953         }
  17954       };
  17955     };
  17956   });
  17957  
  17958   // ng-src,  ng-srcset , ng-href  are interp olated
  17959   forEach([' src', 'src set', 'hre f'], funct ion(attrNa me) {
  17960     var norm alized = d irectiveNo rmalize('n g-' + attr Name);
  17961     ngAttrib uteAliasDi rectives[n ormalized]  = functio n() {
  17962       return  {
  17963         prio rity: 99,  // it need s to run a fter the a ttributes  are interp olated
  17964         link : function (scope, el ement, att r) {
  17965           va r propName  = attrNam e,
  17966                name = a ttrName;
  17967  
  17968           if  (attrName  === 'href ' &&
  17969                toString .call(elem ent.prop(' href')) == = '[object  SVGAnimat edString]' ) {
  17970              name = 'xl inkHref';
  17971              attr.$attr [name] = ' xlink:href ';
  17972              propName =  null;
  17973           }
  17974  
  17975           at tr.$observ e(normaliz ed, functi on(value)  {
  17976              if (!value ) {
  17977                if (attr Name === ' href') {
  17978                  attr.$ set(name,  null);
  17979                }
  17980                return;
  17981              }
  17982  
  17983              attr.$set( name, valu e);
  17984  
  17985              // on IE,  if "ng:src " directiv e declarat ion is use d and "src " attribut e doesn't  exist
  17986              // then ca lling elem ent.setAtt ribute('sr c', 'foo')  doesn't d o anything , so we ne ed
  17987              // to set  the proper ty as well  to achiev e the desi red effect .
  17988              // we use  attr[attrN ame] value  since $se t can sani tize the u rl.
  17989              if (msie & & propName ) element. prop(propN ame, attr[ name]);
  17990           }) ;
  17991         }
  17992       };
  17993     };
  17994   });
  17995  
  17996   /* global  -nullFormC trl, -SUBM ITTED_CLAS S, addSetV alidityMet hod: true
  17997    */
  17998   var nullFo rmCtrl = {
  17999     $addCont rol: noop,
  18000       $$renameCo ntrol: nul lF DNS     ameControl ,
  18001     $removeC ontrol: no op,
  18002     $setVali dity: noop ,
  18003     $setDirt y: noop,
  18004     $setPris tine: noop ,
  18005     $setSubm itted: noo p
  18006   },
  18007   SUBMITTED_ CLASS = 'n g-submitte d';
  18008  
  18009   function n ullF DNS     ameControl (control,  name) {
  18010     control. $name = na me;
  18011   }
  18012  
  18013   /**
  18014    * @ngdoc  type
  18015    * @name f orm.F DNS     troller
  18016    *
  18017    * @proper ty {boolea n} $pristi ne True if  user has  not intera cted with  the form y et.
  18018    * @proper ty {boolea n} $dirty  True if us er has alr eady inter acted with  the form.
  18019    * @proper ty {boolea n} $valid  True if al l of the c ontaining  forms and  controls a re valid.
  18020    * @proper ty {boolea n} $invali d True if  at least o ne contain ing contro l or form  is invalid .
  18021    * @proper ty {boolea n} $submit ted True i f user has  submitted  the form  even if it s invalid.
  18022    *
  18023    * @proper ty {Object } $error I s an objec t hash, co ntaining r eferences  to control s or
  18024    *  forms  with faili ng validat ors, where :
  18025    *
  18026    *  - keys  are valid ation toke ns (error  names),
  18027    *  - valu es are arr ays of con trols or f orms that  have a fai ling valid ator for g iven error  name.
  18028    *
  18029    *  Built- in validat ion tokens :
  18030    *
  18031    *  - `ema il`
  18032    *  - `max `
  18033    *  - `max length`
  18034    *  - `min `
  18035    *  - `min length`
  18036    *  - `num ber`
  18037    *  - `pat tern`
  18038    *  - `req uired`
  18039    *  - `url `
  18040    *  - `dat e`
  18041    *  - `dat etimelocal `
  18042    *  - `tim e`
  18043    *  - `wee k`
  18044    *  - `mon th`
  18045    *
  18046    * @descri ption
  18047    * `F DNS     troller` k eeps track  of all it s controls  and neste d forms as  well as t he state o f them,
  18048    * such as  being val id/invalid  or dirty/ pristine.
  18049    *
  18050    * Each {@ link ng.di rective:fo rm form} d irective c reates an  instance
  18051    * of `F DNS     troller`.
  18052    *
  18053    */
  18054   //asks for  $scope to  fool the  BC control ler module
  18055   F DNS     troller.$i nject = [' $element',  '$attrs',  '$scope',  '$animate ', '$inter polate'];
  18056   function F DNS     troller(el ement, att rs, $scope , $animate , $interpo late) {
  18057     var form  = this,
  18058         cont rols = [];
  18059  
  18060     var pare ntForm = f orm.$$pare ntForm = e lement.par ent().cont roller('fo rm') || nu llFormCtrl ;
  18061  
  18062     // init  state
  18063     form.$er ror = {};
  18064     form.$$s uccess = { };
  18065     form.$pe nding = un defined;
  18066     form.$na me = $inte rpolate(at trs.name | | attrs.ng Form || '' )($scope);
  18067     form.$di rty = fals e;
  18068     form.$pr istine = t rue;
  18069     form.$va lid = true ;
  18070     form.$in valid = fa lse;
  18071     form.$su bmitted =  false;
  18072  
  18073     parentFo rm.$addCon trol(form) ;
  18074  
  18075     /**
  18076      * @ngdo c method
  18077        * @name fo rm.F DNS     troller#$r ollbackVie wValue
  18078      *
  18079      * @desc ription
  18080      * Rollb ack all fo rm control s pending  updates to  the `$mod elValue`.
  18081      *
  18082      * Updat es may be  pending by  a debounc ed event o r because  the input  is waiting  for a som e future
  18083      * event  defined i n `ng-mode l-options` . This met hod is typ ically nee ded by the  reset but ton of
  18084      * a for m that use s `ng-mode l-options`  to pend u pdates.
  18085      */
  18086     form.$ro llbackView Value = fu nction() {
  18087       forEac h(controls , function (control)  {
  18088         cont rol.$rollb ackViewVal ue();
  18089       });
  18090     };
  18091  
  18092     /**
  18093      * @ngdo c method
  18094        * @name fo rm.F DNS     troller#$c ommitViewV alue
  18095      *
  18096      * @desc ription
  18097      * Commi t all form  controls  pending up dates to t he `$model Value`.
  18098      *
  18099      * Updat es may be  pending by  a debounc ed event o r because  the input  is waiting  for a som e future
  18100      * event  defined i n `ng-mode l-options` . This met hod is rar ely needed  as `NgMod elControll er`
  18101      * usual ly handles  calling t his in res ponse to i nput event s.
  18102      */
  18103     form.$co mmitViewVa lue = func tion() {
  18104       forEac h(controls , function (control)  {
  18105         cont rol.$commi tViewValue ();
  18106       });
  18107     };
  18108  
  18109     /**
  18110      * @ngdo c method
  18111        * @name fo rm.F DNS     troller#$a ddControl
  18112      *
  18113      * @desc ription
  18114      * Regis ter a cont rol with t he form.
  18115      *
  18116      * Input  elements  using ngMo delControl ler do thi s automati cally when  they are  linked.
  18117      */
  18118     form.$ad dControl =  function( control) {
  18119       // Bre aking chan ge - befor e, inputs  whose name  was "hasO wnProperty " were qui etly ignor ed
  18120       // and  not added  to the sc ope.  Now  we throw a n error.
  18121       assert NotHasOwnP roperty(co ntrol.$nam e, 'input' );
  18122       contro ls.push(co ntrol);
  18123  
  18124       if (co ntrol.$nam e) {
  18125         form [control.$ name] = co ntrol;
  18126       }
  18127     };
  18128  
  18129     // Priva te API: re name a for m control
  18130     form.$$r enameContr ol = funct ion(contro l, newName ) {
  18131       var ol dName = co ntrol.$nam e;
  18132  
  18133       if (fo rm[oldName ] === cont rol) {
  18134         dele te form[ol dName];
  18135       }
  18136       form[n ewName] =  control;
  18137       contro l.$name =  newName;
  18138     };
  18139  
  18140     /**
  18141      * @ngdo c method
  18142        * @name fo rm.F DNS     troller#$r emoveContr ol
  18143      *
  18144      * @desc ription
  18145      * Dereg ister a co ntrol from  the form.
  18146      *
  18147      * Input  elements  using ngMo delControl ler do thi s automati cally when  they are  destroyed.
  18148      */
  18149     form.$re moveContro l = functi on(control ) {
  18150       if (co ntrol.$nam e && form[ control.$n ame] === c ontrol) {
  18151         dele te form[co ntrol.$nam e];
  18152       }
  18153       forEac h(form.$pe nding, fun ction(valu e, name) {
  18154         form .$setValid ity(name,  null, cont rol);
  18155       });
  18156       forEac h(form.$er ror, funct ion(value,  name) {
  18157         form .$setValid ity(name,  null, cont rol);
  18158       });
  18159  
  18160       arrayR emove(cont rols, cont rol);
  18161     };
  18162  
  18163  
  18164     /**
  18165      * @ngdo c method
  18166        * @name fo rm.F DNS     troller#$s etValidity
  18167      *
  18168      * @desc ription
  18169      * Sets  the validi ty of a fo rm control .
  18170      *
  18171      * This  method wil l also pro pagate to  parent for ms.
  18172      */
  18173     addSetVa lidityMeth od({
  18174       ctrl:  this,
  18175       $eleme nt: elemen t,
  18176       set: f unction(ob ject, prop erty, cont rol) {
  18177         var  list = obj ect[proper ty];
  18178         if ( !list) {
  18179           ob ject[prope rty] = [co ntrol];
  18180         } el se {
  18181           va r index =  list.index Of(control );
  18182           if  (index == = -1) {
  18183              list.push( control);
  18184           }
  18185         }
  18186       },
  18187       unset:  function( object, pr operty, co ntrol) {
  18188         var  list = obj ect[proper ty];
  18189         if ( !list) {
  18190           re turn;
  18191         }
  18192         arra yRemove(li st, contro l);
  18193         if ( list.lengt h === 0) {
  18194           de lete objec t[property ];
  18195         }
  18196       },
  18197       parent Form: pare ntForm,
  18198       $anima te: $anima te
  18199     });
  18200  
  18201     /**
  18202      * @ngdo c method
  18203        * @name fo rm.F DNS     troller#$s etDirty
  18204      *
  18205      * @desc ription
  18206      * Sets  the form t o a dirty  state.
  18207      *
  18208      * This  method can  be called  to add th e 'ng-dirt y' class a nd set the  form to a  dirty
  18209      * state  (ng-dirty  class). T his method  will also  propagate  to parent  forms.
  18210      */
  18211     form.$se tDirty = f unction()  {
  18212       $anima te.removeC lass(eleme nt, PRISTI NE_CLASS);
  18213       $anima te.addClas s(element,  DIRTY_CLA SS);
  18214       form.$ dirty = tr ue;
  18215       form.$ pristine =  false;
  18216       parent Form.$setD irty();
  18217     };
  18218  
  18219     /**
  18220      * @ngdo c method
  18221        * @name fo rm.F DNS     troller#$s etPristine
  18222      *
  18223      * @desc ription
  18224      * Sets  the form t o its pris tine state .
  18225      *
  18226      * This  method can  be called  to remove  the 'ng-d irty' clas s and set  the form t o its pris tine
  18227      * state  (ng-prist ine class) . This met hod will a lso propag ate to all  the contr ols contai ned
  18228      * in th is form.
  18229      *
  18230      * Setti ng a form  back to a  pristine s tate is of ten useful  when we w ant to 're use' a for m after
  18231      * savin g or reset ting it.
  18232      */
  18233     form.$se tPristine  = function () {
  18234       $anima te.setClas s(element,  PRISTINE_ CLASS, DIR TY_CLASS +  ' ' + SUB MITTED_CLA SS);
  18235       form.$ dirty = fa lse;
  18236       form.$ pristine =  true;
  18237       form.$ submitted  = false;
  18238       forEac h(controls , function (control)  {
  18239         cont rol.$setPr istine();
  18240       });
  18241     };
  18242  
  18243     /**
  18244      * @ngdo c method
  18245        * @name fo rm.F DNS     troller#$s etUntouche d
  18246      *
  18247      * @desc ription
  18248      * Sets  the form t o its unto uched stat e.
  18249      *
  18250      * This  method can  be called  to remove  the 'ng-t ouched' cl ass and se t the form  controls  to their
  18251      * untou ched state  (ng-untou ched class ).
  18252      *
  18253      * Setti ng a form  controls b ack to the ir untouch ed state i s often us eful when  setting th e form
  18254      * back  to its pri stine stat e.
  18255      */
  18256     form.$se tUntouched  = functio n() {
  18257       forEac h(controls , function (control)  {
  18258         cont rol.$setUn touched();
  18259       });
  18260     };
  18261  
  18262     /**
  18263      * @ngdo c method
  18264        * @name fo rm.F DNS     troller#$s etSubmitte d
  18265      *
  18266      * @desc ription
  18267      * Sets  the form t o its subm itted stat e.
  18268      */
  18269     form.$se tSubmitted  = functio n() {
  18270       $anima te.addClas s(element,  SUBMITTED _CLASS);
  18271       form.$ submitted  = true;
  18272       parent Form.$setS ubmitted() ;
  18273     };
  18274   }
  18275  
  18276   /**
  18277    * @ngdoc  directive
  18278    * @name n gForm
  18279    * @restri ct EAC
  18280    *
  18281    * @descri ption
  18282    * Nestabl e alias of  {@link ng .directive :form `for m`} direct ive. HTML
  18283    * does no t allow ne sting of f orm elemen ts. It is  useful to  nest forms , for exam ple if the  validity  of a
  18284    * sub-gro up of cont rols needs  to be det ermined.
  18285    *
  18286    * Note: t he purpose  of `ngFor m` is to g roup contr ols,
  18287    * but not  to be a r eplacement  for the ` <form>` ta g with all  of its ca pabilities
  18288    * (e.g. p osting to  the server , ...).
  18289    *
  18290    * @param  {string=}  ngForm|nam e Name of  the form.  If specifi ed, the fo rm control ler will b e publishe d into
  18291    *                         relat ed scope,  under this  name.
  18292    *
  18293    */
  18294  
  18295    /**
  18296    * @ngdoc  directive
  18297    * @name f orm
  18298    * @restri ct E
  18299    *
  18300    * @descri ption
  18301    * Directi ve that in stantiates
  18302    * {@link  form.F DNS     troller F DNS     troller}.
  18303    *
  18304    * If the  `name` att ribute is  specified,  the form  controller  is publis hed onto t he current  scope und er
  18305    * this na me.
  18306    *
  18307    * # Alias : {@link n g.directiv e:ngForm ` ngForm`}
  18308    *
  18309    * In Angu lar forms  can be nes ted. This  means that  the outer  form is v alid when  all of the  child
  18310    * forms a re valid a s well. Ho wever, bro wsers do n ot allow n esting of  `<form>` e lements, s o
  18311    * Angular  provides  the {@link  ng.direct ive:ngForm  `ngForm`}  directive  which beh aves ident ically to
  18312    * `<form> ` but can  be nested.   This all ows you to  have nest ed forms,  which is v ery useful  when
  18313    * using A ngular val idation di rectives i n forms th at are dyn amically g enerated u sing the
  18314    * {@link  ng.directi ve:ngRepea t `ngRepea t`} direct ive. Since  you canno t dynamica lly genera te the `na me`
  18315    * attribu te of inpu t elements  using int erpolation , you have  to wrap e ach set of  repeated  inputs in  an
  18316    * `ngForm ` directiv e and nest  these in  an outer ` form` elem ent.
  18317    *
  18318    *
  18319    * # CSS c lasses
  18320    *  - `ng- valid` is  set if the  form is v alid.
  18321    *  - `ng- invalid` i s set if t he form is  invalid.
  18322    *  - `ng- pristine`  is set if  the form i s pristine .
  18323    *  - `ng- dirty` is  set if the  form is d irty.
  18324    *  - `ng- submitted`  is set if  the form  was submit ted.
  18325    *
  18326    * Keep in  mind that  ngAnimate  can detec t each of  these clas ses when a dded and r emoved.
  18327    *
  18328    *
  18329    * # Submi tting a fo rm and pre venting th e default  action
  18330    *
  18331    * Since t he role of  forms in  client-sid e Angular  applicatio ns is diff erent than  in classi cal
  18332    * roundtr ip apps, i t is desir able for t he browser  not to tr anslate th e form sub mission in to a full
  18333    * page re load that  sends the  data to th e server.  Instead so me javascr ipt logic  should be  triggered
  18334    * to hand le the for m submissi on in an a pplication -specific  way.
  18335    *
  18336    * For thi s reason,  Angular pr events the  default a ction (for m submissi on to the  server) un less the
  18337    * `<form> ` element  has an `ac tion` attr ibute spec ified.
  18338    *
  18339    * You can  use one o f the foll owing two  ways to sp ecify what  javascrip t method s hould be c alled when
  18340    * a form  is submitt ed:
  18341    *
  18342    * - {@lin k ng.direc tive:ngSub mit ngSubm it} direct ive on the  form elem ent
  18343    * - {@lin k ng.direc tive:ngCli ck ngClick } directiv e on the f irst
  18344     *  butto n or input  field of  type submi t (input[t ype=submit ])
  18345    *
  18346    * To prev ent double  execution  of the ha ndler, use  only one  of the {@l ink ng.dir ective:ngS ubmit ngSu bmit}
  18347    * or {@li nk ng.dire ctive:ngCl ick ngClic k} directi ves.
  18348    * This is  because o f the foll owing form  submissio n rules in  the HTML  specificat ion:
  18349    *
  18350    * - If a  form has o nly one in put field  then hitti ng enter i n this fie ld trigger s form sub mit
  18351    * (`ngSub mit`)
  18352    * - if a  form has 2 + input fi elds and n o buttons  or input[t ype=submit ] then hit ting enter
  18353    * doesn't  trigger s ubmit
  18354    * - if a  form has o ne or more  input fie lds and on e or more  buttons or  input[typ e=submit]  then
  18355    * hitting  enter in  any of the  input fie lds will t rigger the  click han dler on th e *first*  button or
  18356    * input[t ype=submit ] (`ngClic k`) *and*  a submit h andler on  the enclos ing form ( `ngSubmit` )
  18357    *
  18358    * Any pen ding `ngMo delOptions ` changes  will take  place imme diately wh en an encl osing form  is
  18359    * submitt ed. Note t hat `ngCli ck` events  will occu r before t he model i s updated.  Use `ngSu bmit`
  18360    * to have  access to  the updat ed model.
  18361    *
  18362    * ## Anim ation Hook s
  18363    *
  18364    * Animati ons in ngF orm are tr iggered wh en any of  the associ ated CSS c lasses are  added and  removed.
  18365    * These c lasses are : `.ng-pri stine`, `. ng-dirty`,  `.ng-inva lid` and ` .ng-valid`  as well a s any
  18366    * other v alidations  that are  performed  within the  form. Ani mations in  ngForm ar e similar  to how
  18367    * they wo rk in ngCl ass and an imations c an be hook ed into us ing CSS tr ansitions,  keyframes  as well
  18368    * as JS a nimations.
  18369    *
  18370    * The fol lowing exa mple shows  a simple  way to uti lize CSS t ransitions  to style  a form ele ment
  18371    * that ha s been ren dered as i nvalid aft er it has  been valid ated:
  18372    *
  18373    * <pre>
  18374    * //be su re to incl ude ngAnim ate as a m odule to h ook into m ore
  18375    * //advan ced animat ions
  18376    * .my-for m {
  18377    *   trans ition:0.5s  linear al l;
  18378    *   backg round: whi te;
  18379    * }
  18380    * .my-for m.ng-inval id {
  18381    *   backg round: red ;
  18382    *   color :white;
  18383    * }
  18384    * </pre>
  18385    *
  18386    * @exampl e
  18387       <examp le deps="a ngular-ani mate.js" a nimations= "true" fix Base="true " module=" formExampl e">
  18388         <fil e name="in dex.html">
  18389          <sc ript>
  18390            a ngular.mod ule('formE xample', [ ])
  18391                .controlle r('F DNS     troller',  ['$scope',  function( $scope) {
  18392                 $scope. userType =  'guest';
  18393               }]);
  18394          </s cript>
  18395          <st yle>
  18396           .m y-form {
  18397              -webkit-tr ansition:a ll linear  0.5s;
  18398              transition :all linea r 0.5s;
  18399              background : transpar ent;
  18400           }
  18401           .m y-form.ng- invalid {
  18402              background : red;
  18403           }
  18404          </s tyle>
  18405            <form name ="myForm"  ng-control ler="F DNS     troller" c lass="my-f orm">
  18406            u serType: < input name ="input" n g-model="u serType" r equired>
  18407            < span class ="error" n g-show="my Form.input .$error.re quired">Re quired!</s pan><br>
  18408            < tt>userTyp e = {{user Type}}</tt ><br>
  18409            < tt>myForm. input.$val id = {{myF orm.input. $valid}}</ tt><br>
  18410            < tt>myForm. input.$err or = {{myF orm.input. $error}}</ tt><br>
  18411            < tt>myForm. $valid = { {myForm.$v alid}}</tt ><br>
  18412            < tt>myForm. $error.req uired = {{ !!myForm.$ error.requ ired}}</tt ><br>
  18413           </ form>
  18414         </fi le>
  18415         <fil e name="pr otractor.j s" type="p rotractor" >
  18416           it ('should i nitialize  to model',  function( ) {
  18417              var userTy pe = eleme nt(by.bind ing('userT ype'));
  18418              var valid  = element( by.binding ('myForm.i nput.$vali d'));
  18419  
  18420              expect(use rType.getT ext()).toC ontain('gu est');
  18421              expect(val id.getText ()).toCont ain('true' );
  18422           }) ;
  18423  
  18424           it ('should b e invalid  if empty',  function( ) {
  18425              var userTy pe = eleme nt(by.bind ing('userT ype'));
  18426              var valid  = element( by.binding ('myForm.i nput.$vali d'));
  18427              var userIn put = elem ent(by.mod el('userTy pe'));
  18428  
  18429              userInput. clear();
  18430              userInput. sendKeys(' ');
  18431  
  18432              expect(use rType.getT ext()).toE qual('user Type =');
  18433              expect(val id.getText ()).toCont ain('false ');
  18434           }) ;
  18435         </fi le>
  18436       </exam ple>
  18437    *
  18438    * @param  {string=}  name Name  of the for m. If spec ified, the  form cont roller wil l be publi shed into
  18439    *                         relat ed scope,  under this  name.
  18440    */
  18441   var formDi rectiveFac tory = fun ction(isNg Form) {
  18442     return [ '$timeout' , function ($timeout)  {
  18443       var fo rmDirectiv e = {
  18444         name : 'form',
  18445         rest rict: isNg Form ? 'EA C' : 'E',
  18446           controller : F DNS     troller,
  18447           compile: f unction ng F DNS    mpile(form Element) {
  18448           //  Setup ini tial state  of the co ntrol
  18449           fo rmElement. addClass(P RISTINE_CL ASS).addCl ass(VALID_ CLASS);
  18450  
  18451           re turn {
  18452               pre: funct ion ngF DNS     Link(scope , formElem ent, attr,  controlle r) {
  18453                // if `a ction` att r is not p resent on  the form,  prevent th e default  action (su bmission)
  18454                if (!('a ction' in  attr)) {
  18455                  // we  can't use  jq events  because if  a form is  destroyed  during su bmission t he default
  18456                  // act ion is not  prevented . see #123 8
  18457                  //
  18458                  // IE  9 is not a ffected be cause it d oesn't fir e a submit  event and  try to do  a full
  18459                  // pag e reload i f the form  was destr oyed by su bmission o f the form  via a cli ck handler
  18460                  // on  a button i n the form . Looks li ke an IE9  specific b ug.
  18461                  var ha ndleFormSu bmission =  function( event) {
  18462                    scop e.$apply(f unction()  {
  18463                      co ntroller.$ commitView Value();
  18464                      co ntroller.$ setSubmitt ed();
  18465                    });
  18466  
  18467                    even t.preventD efault();
  18468                  };
  18469  
  18470                  addEve ntListener Fn(formEle ment[0], ' submit', h andleFormS ubmission) ;
  18471  
  18472                  // unr egister th e preventD efault lis tener so t hat we don 't not lea k memory b ut in a
  18473                  // way  that will  achieve t he prevent ion of the  default a ction.
  18474                  formEl ement.on(' $destroy',  function( ) {
  18475                    $tim eout(funct ion() {
  18476                      re moveEventL istenerFn( formElemen t[0], 'sub mit', hand leFormSubm ission);
  18477                    }, 0 , false);
  18478                  });
  18479                }
  18480  
  18481                var pare ntFormCtrl  = control ler.$$pare ntForm,
  18482                    alia s = contro ller.$name ;
  18483  
  18484                if (alia s) {
  18485                  setter (scope, al ias, contr oller, ali as);
  18486                  attr.$ observe(at tr.name ?  'name' : ' ngForm', f unction(ne wValue) {
  18487                    if ( alias ===  newValue)  return;
  18488                    sett er(scope,  alias, und efined, al ias);
  18489                    alia s = newVal ue;
  18490                    sett er(scope,  alias, con troller, a lias);
  18491                    pare ntFormCtrl .$$renameC ontrol(con troller, a lias);
  18492                  });
  18493                }
  18494                formElem ent.on('$d estroy', f unction()  {
  18495                  parent FormCtrl.$ removeCont rol(contro ller);
  18496                  if (al ias) {
  18497                    sett er(scope,  alias, und efined, al ias);
  18498                  }
  18499                  extend (controlle r, nullFor mCtrl); // stop propa gating chi ld destruc tion handl ers upward s
  18500                });
  18501              }
  18502           };
  18503         }
  18504       };
  18505  
  18506       return  formDirec tive;
  18507     }];
  18508   };
  18509  
  18510   var formDi rective =  formDirect iveFactory ();
  18511   var ngForm Directive  = formDire ctiveFacto ry(true);
  18512  
  18513   /* global  VALID_CLAS S: true,
  18514     INVALID_ CLASS: tru e,
  18515     PRISTINE _CLASS: tr ue,
  18516     DIRTY_CL ASS: true,
  18517     UNTOUCHE D_CLASS: t rue,
  18518     TOUCHED_ CLASS: tru e,
  18519   */
  18520  
  18521   // Regex c ode is obt ained from  SO: https ://stackov erflow.com /questions /3143070/j avascript- regex-iso- datetime#a nswer-3143 231
  18522   var ISO_DA TE_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)/;
  18523   var URL_RE GEXP = /^( ftp|http|h ttps):\/\/ (\w+:{0,1} \w*@)?(\S+ )(:[0-9]+) ?(\/|\/([\ w#!:.?+=&% @!\-\/]))? $/;
  18524   var EMAIL_ REGEXP = / ^[a-z0-9!# $%&'*+\/=? ^_`{|}~.-] +@[a-z0-9] ([a-z0-9-] *[a-z0-9]) ?(\.[a-z0- 9]([a-z0-9 -]*[a-z0-9 ])?)*$/i;
  18525   var NUMBER _REGEXP =  /^\s*(\-|\ +)?(\d+|(\ d*(\.\d*)) )\s*$/;
  18526   var DATE_R EGEXP = /^ (\d{4})-(\ d{2})-(\d{ 2})$/;
  18527   var DATETI MELOCAL_RE GEXP = /^( \d{4})-(\d \d)-(\d\d) T(\d\d):(\ d\d)(?::(\ d\d)(\.\d{ 1,3})?)?$/ ;
  18528   var WEEK_R EGEXP = /^ (\d{4})-W( \d\d)$/;
  18529   var MONTH_ REGEXP = / ^(\d{4})-( \d\d)$/;
  18530   var TIME_R EGEXP = /^ (\d\d):(\d \d)(?::(\d \d)(\.\d{1 ,3})?)?$/;
  18531   var DEFAUL T_REGEXP =  /(\s+|^)d efault(\s+ |$)/;
  18532  
  18533   var $ngMod elMinErr =  new minEr r('ngModel ');
  18534  
  18535   var inputT ype = {
  18536  
  18537     /**
  18538      * @ngdo c input
  18539      * @name  input[tex t]
  18540      *
  18541      * @desc ription
  18542      * Stand ard HTML t ext input  with angul ar data bi nding, inh erited by  most of th e `input`  elements.
  18543      *
  18544      *
  18545      * @para m {string}  ngModel A ssignable  angular ex pression t o data-bin d to.
  18546      * @para m {string= } name Pro perty name  of the fo rm under w hich the c ontrol is  published.
  18547      * @para m {string= } required  Adds `req uired` val idation er ror key if  the value  is not en tered.
  18548      * @para m {string= } ngRequir ed Adds `r equired` a ttribute a nd `requir ed` valida tion const raint to
  18549      *    th e element  when the n gRequired  expression  evaluates  to true.  Use `ngReq uired` ins tead of
  18550      *    `r equired` w hen you wa nt to data -bind to t he `requir ed` attrib ute.
  18551      * @para m {number= } ngMinlen gth Sets ` minlength`  validatio n error ke y if the v alue is sh orter than
  18552      *    mi nlength.
  18553      * @para m {number= } ngMaxlen gth Sets ` maxlength`  validatio n error ke y if the v alue is lo nger than
  18554      *    ma xlength. S etting the  attribute  to a nega tive or no n-numeric  value, all ows view v alues of
  18555      *    an y length.
  18556      * @para m {string= } pattern  Similar to  `ngPatter n` except  that the a ttribute v alue is th e actual s tring
  18557      *    th at contain s the regu lar expres sion body  that will  be convert ed to a re gular expr ession
  18558      *    as  in the ng Pattern di rective.
  18559      * @para m {string= } ngPatter n Sets `pa ttern` val idation er ror key if  the ngMod el value d oes not ma tch
  18560      *    a  RegExp fou nd by eval uating the  Angular e xpression  given in t he attribu te value.
  18561      *    If  the expre ssion eval uates to a  RegExp ob ject then  this is us ed directl y.
  18562      *    If  the expre ssion is a  string th en it will  be conver ted to a R egExp afte r wrapping  it in `^`  and `$`
  18563      *    ch aracters.  For instan ce, `"abc" ` will be  converted  to `new Re gExp('^abc $')`.
  18564      * @para m {string= } ngChange  Angular e xpression  to be exec uted when  input chan ges due to  user
  18565      *    in teraction  with the i nput eleme nt.
  18566      * @para m {boolean =} [ngTrim =true] If  set to fal se Angular  will not  automatica lly trim t he input.
  18567      *    Th is paramet er is igno red for in put[type=p assword] c ontrols, w hich will  never trim  the
  18568      *    in put.
  18569      *
  18570      * @exam ple
  18571         <exa mple name= "text-inpu t-directiv e" module= "textInput Example">
  18572           <f ile name=" index.html ">
  18573            < script>
  18574               angular.m odule('tex tInputExam ple', [])
  18575                 .contro ller('Exam pleControl ler', ['$s cope', fun ction($sco pe) {
  18576                   $scop e.text = ' guest';
  18577                   $scop e.word = / ^\s*\w*\s* $/;
  18578                 }]);
  18579            < /script>
  18580            < form name= "myForm" n g-controll er="Exampl eControlle r">
  18581               Single wo rd: <input  type="tex t" name="i nput" ng-m odel="text "
  18582                                     ng-patter n="word" r equired ng -trim="fal se">
  18583               <span cla ss="error"  ng-show=" myForm.inp ut.$error. required">
  18584                 Require d!</span>
  18585               <span cla ss="error"  ng-show=" myForm.inp ut.$error. pattern">
  18586                 Single  word only! </span>
  18587  
  18588               <tt>text  = {{text}} </tt><br/>
  18589               <tt>myFor m.input.$v alid = {{m yForm.inpu t.$valid}} </tt><br/>
  18590               <tt>myFor m.input.$e rror = {{m yForm.inpu t.$error}} </tt><br/>
  18591               <tt>myFor m.$valid =  {{myForm. $valid}}</ tt><br/>
  18592               <tt>myFor m.$error.r equired =  {{!!myForm .$error.re quired}}</ tt><br/>
  18593              </form>
  18594           </ file>
  18595           <f ile name=" protractor .js" type= "protracto r">
  18596              var text =  element(b y.binding( 'text'));
  18597              var valid  = element( by.binding ('myForm.i nput.$vali d'));
  18598              var input  = element( by.model(' text'));
  18599  
  18600              it('should  initializ e to model ', functio n() {
  18601                expect(t ext.getTex t()).toCon tain('gues t');
  18602                expect(v alid.getTe xt()).toCo ntain('tru e');
  18603              });
  18604  
  18605              it('should  be invali d if empty ', functio n() {
  18606                input.cl ear();
  18607                input.se ndKeys('') ;
  18608  
  18609                expect(t ext.getTex t()).toEqu al('text = ');
  18610                expect(v alid.getTe xt()).toCo ntain('fal se');
  18611              });
  18612  
  18613              it('should  be invali d if multi  word', fu nction() {
  18614                input.cl ear();
  18615                input.se ndKeys('he llo world' );
  18616  
  18617                expect(v alid.getTe xt()).toCo ntain('fal se');
  18618              });
  18619           </ file>
  18620         </ex ample>
  18621      */
  18622     'text':  textInputT ype,
  18623  
  18624       /**
  18625        * @ng doc input
  18626        * @na me input[d ate]
  18627        *
  18628        * @de scription
  18629        * Inp ut with da te validat ion and tr ansformati on. In bro wsers that  do not ye t support
  18630        * the  HTML5 dat e input, a  text elem ent will b e used. In  that case , text mus t be enter ed in a va lid ISO-86 01
  18631        * dat e format ( yyyy-MM-dd ), for exa mple: `200 9-01-06`.  Since many
  18632        * mod ern browse rs do not  yet suppor t this inp ut type, i t is impor tant to pr ovide cues  to users  on the
  18633        * exp ected inpu t format v ia a place holder or  label.
  18634        *
  18635        * The  model mus t always b e a Date o bject, oth erwise Ang ular will  throw an e rror.
  18636        * Inv alid `Date ` objects  (dates who se `getTim e()` is `N aN`) will  be rendere d as an em pty string .
  18637        *
  18638        * The  timezone  to be used  to read/w rite the ` Date` inst ance in th e model ca n be defin ed using
  18639        * {@l ink ng.dir ective:ngM odelOption s ngModelO ptions}. B y default,  this is t he timezon e of the b rowser.
  18640        *
  18641        * @pa ram {strin g} ngModel  Assignabl e angular  expression  to data-b ind to.
  18642        * @pa ram {strin g=} name P roperty na me of the  form under  which the  control i s publishe d.
  18643        * @pa ram {strin g=} min Se ts the `mi n` validat ion error  key if the  value ent ered is le ss than `m in`. This  must be a
  18644        * val id ISO dat e string ( yyyy-MM-dd ).
  18645        * @pa ram {strin g=} max Se ts the `ma x` validat ion error  key if the  value ent ered is gr eater than  `max`. Th is must be
  18646        * a v alid ISO d ate string  (yyyy-MM- dd).
  18647        * @pa ram {strin g=} requir ed Sets `r equired` v alidation  error key  if the val ue is not  entered.
  18648        * @pa ram {strin g=} ngRequ ired Adds  `required`  attribute  and `requ ired` vali dation con straint to
  18649        *     the elemen t when the  ngRequire d expressi on evaluat es to true . Use `ngR equired` i nstead of
  18650        *     `required`  when you  want to da ta-bind to  the `requ ired` attr ibute.
  18651        * @pa ram {strin g=} ngChan ge Angular  expressio n to be ex ecuted whe n input ch anges due  to user
  18652        *     interactio n with the  input ele ment.
  18653        *
  18654        * @ex ample
  18655        <exam ple name=" date-input -directive " module=" dateInputE xample">
  18656        <file  name="ind ex.html">
  18657          <sc ript>
  18658              angular.mo dule('date InputExamp le', [])
  18659                .control ler('DateC ontroller' , ['$scope ', functio n($scope)  {
  18660                  $scope .value = n ew Date(20 13, 9, 22) ;
  18661                }]);
  18662          </s cript>
  18663          <fo rm name="m yForm" ng- controller ="DateCont roller as  dateCtrl">
  18664              Pick a dat e in 2013:
  18665              <input typ e="date" i d="example Input" nam e="input"  ng-model=" value"
  18666                  placeh older="yyy y-MM-dd" m in="2013-0 1-01" max= "2013-12-3 1" require d />
  18667              <span clas s="error"  ng-show="m yForm.inpu t.$error.r equired">
  18668                  Requir ed!</span>
  18669              <span clas s="error"  ng-show="m yForm.inpu t.$error.d ate">
  18670                  Not a  valid date !</span>
  18671               <tt>value  = {{value  | date: " yyyy-MM-dd "}}</tt><b r/>
  18672               <tt>myFor m.input.$v alid = {{m yForm.inpu t.$valid}} </tt><br/>
  18673               <tt>myFor m.input.$e rror = {{m yForm.inpu t.$error}} </tt><br/>
  18674               <tt>myFor m.$valid =  {{myForm. $valid}}</ tt><br/>
  18675               <tt>myFor m.$error.r equired =  {{!!myForm .$error.re quired}}</ tt><br/>
  18676          </f orm>
  18677        </fil e>
  18678        <file  name="pro tractor.js " type="pr otractor">
  18679           va r value =  element(by .binding(' value | da te: "yyyy- MM-dd"'));
  18680           va r valid =  element(by .binding(' myForm.inp ut.$valid' ));
  18681           va r input =  element(by .model('va lue'));
  18682  
  18683           //  currently  protracto r/webdrive r does not  support
  18684           //  sending k eys to all  known HTM L5 input c ontrols
  18685           //  for vario us browser s (see htt ps://githu b.com/angu lar/protra ctor/issue s/562).
  18686           fu nction set Input(val)  {
  18687              // set the  value of  the elemen t and forc e validati on.
  18688              var scr =  "var ipt =  document. getElement ById('exam pleInput') ; " +
  18689              "ipt.value  = '" + va l + "';" +
  18690              "angular.e lement(ipt ).scope(). $apply(fun ction(s) {  s.myForm[ ipt.name]. $setViewVa lue('" + v al + "');  });";
  18691              browser.ex ecuteScrip t(scr);
  18692           }
  18693  
  18694           it ('should i nitialize  to model',  function( ) {
  18695              expect(val ue.getText ()).toCont ain('2013- 10-22');
  18696              expect(val id.getText ()).toCont ain('myFor m.input.$v alid = tru e');
  18697           }) ;
  18698  
  18699           it ('should b e invalid  if empty',  function( ) {
  18700              setInput(' ');
  18701              expect(val ue.getText ()).toEqua l('value = ');
  18702              expect(val id.getText ()).toCont ain('myFor m.input.$v alid = fal se');
  18703           }) ;
  18704  
  18705           it ('should b e invalid  if over ma x', functi on() {
  18706              setInput(' 2015-01-01 ');
  18707              expect(val ue.getText ()).toCont ain('');
  18708              expect(val id.getText ()).toCont ain('myFor m.input.$v alid = fal se');
  18709           }) ;
  18710        </fil e>
  18711        </exa mple>
  18712        */
  18713     'date':  createDate InputType( 'date', DA TE_REGEXP,
  18714            c reateDateP arser(DATE _REGEXP, [ 'yyyy', 'M M', 'dd']) ,
  18715            ' yyyy-MM-dd '),
  18716  
  18717      /**
  18718       * @ngd oc input
  18719       * @nam e input[da tetime-loc al]
  18720       *
  18721       * @des cription
  18722       * Inpu t with dat etime vali dation and  transform ation. In  browsers t hat do not  yet suppo rt
  18723       * the  HTML5 date  input, a  text eleme nt will be  used. In  that case,  the text  must be en tered in a  valid ISO -8601
  18724       * loca l datetime  format (y yyy-MM-ddT HH:mm:ss),  for examp le: `2010- 12-28T14:5 7:00`.
  18725       *
  18726       * The  model must  always be  a Date ob ject, othe rwise Angu lar will t hrow an er ror.
  18727       * Inva lid `Date`  objects ( dates whos e `getTime ()` is `Na N`) will b e rendered  as an emp ty string.
  18728       *
  18729       * The  timezone t o be used  to read/wr ite the `D ate` insta nce in the  model can  be define d using
  18730       * {@li nk ng.dire ctive:ngMo delOptions  ngModelOp tions}. By  default,  this is th e timezone  of the br owser.
  18731       *
  18732       * @par am {string } ngModel  Assignable  angular e xpression  to data-bi nd to.
  18733       * @par am {string =} name Pr operty nam e of the f orm under  which the  control is  published .
  18734       * @par am {string =} min Set s the `min ` validati on error k ey if the  value ente red is les s than `mi n`. This m ust be a
  18735       * vali d ISO date time forma t (yyyy-MM -ddTHH:mm: ss).
  18736       * @par am {string =} max Set s the `max ` validati on error k ey if the  value ente red is gre ater than  `max`. Thi s must be
  18737       * a va lid ISO da tetime for mat (yyyy- MM-ddTHH:m m:ss).
  18738       * @par am {string =} require d Sets `re quired` va lidation e rror key i f the valu e is not e ntered.
  18739       * @par am {string =} ngRequi red Adds ` required`  attribute  and `requi red` valid ation cons traint to
  18740       *    t he element  when the  ngRequired  expressio n evaluate s to true.  Use `ngRe quired` in stead of
  18741       *    ` required`  when you w ant to dat a-bind to  the `requi red` attri bute.
  18742       * @par am {string =} ngChang e Angular  expression  to be exe cuted when  input cha nges due t o user
  18743       *    i nteraction  with the  input elem ent.
  18744       *
  18745       * @exa mple
  18746       <examp le name="d atetimeloc al-input-d irective"  module="da teExample" >
  18747       <file  name="inde x.html">
  18748         <scr ipt>
  18749           an gular.modu le('dateEx ample', [] )
  18750              .controlle r('DateCon troller',  ['$scope',  function( $scope) {
  18751                $scope.v alue = new  Date(2010 , 11, 28,  14, 57);
  18752              }]);
  18753         </sc ript>
  18754         <for m name="my Form" ng-c ontroller= "DateContr oller as d ateCtrl">
  18755           Pi ck a date  between in  2013:
  18756           <i nput type= "datetime- local" id= "exampleIn put" name= "input" ng -model="va lue"
  18757                placehol der="yyyy- MM-ddTHH:m m:ss" min= "2001-01-0 1T00:00:00 " max="201 3-12-31T00 :00:00" re quired />
  18758           <s pan class= "error" ng -show="myF orm.input. $error.req uired">
  18759                Required !</span>
  18760           <s pan class= "error" ng -show="myF orm.input. $error.dat etimelocal ">
  18761                Not a va lid date!< /span>
  18762           <t t>value =  {{value |  date: "yyy y-MM-ddTHH :mm:ss"}}< /tt><br/>
  18763           <t t>myForm.i nput.$vali d = {{myFo rm.input.$ valid}}</t t><br/>
  18764           <t t>myForm.i nput.$erro r = {{myFo rm.input.$ error}}</t t><br/>
  18765           <t t>myForm.$ valid = {{ myForm.$va lid}}</tt> <br/>
  18766           <t t>myForm.$ error.requ ired = {{! !myForm.$e rror.requi red}}</tt> <br/>
  18767         </fo rm>
  18768       </file >
  18769       <file  name="prot ractor.js"  type="pro tractor">
  18770         var  value = el ement(by.b inding('va lue | date : "yyyy-MM -ddTHH:mm: ss"'));
  18771         var  valid = el ement(by.b inding('my Form.input .$valid')) ;
  18772         var  input = el ement(by.m odel('valu e'));
  18773  
  18774         // c urrently p rotractor/ webdriver  does not s upport
  18775         // s ending key s to all k nown HTML5  input con trols
  18776         // f or various  browsers  (https://g ithub.com/ angular/pr otractor/i ssues/562) .
  18777         func tion setIn put(val) {
  18778           //  set the v alue of th e element  and force  validation .
  18779           va r scr = "v ar ipt = d ocument.ge tElementBy Id('exampl eInput');  " +
  18780           "i pt.value =  '" + val  + "';" +
  18781           "a ngular.ele ment(ipt). scope().$a pply(funct ion(s) { s .myForm[ip t.name].$s etViewValu e('" + val  + "'); }) ;";
  18782           br owser.exec uteScript( scr);
  18783         }
  18784  
  18785         it(' should ini tialize to  model', f unction()  {
  18786           ex pect(value .getText() ).toContai n('2010-12 -28T14:57: 00');
  18787           ex pect(valid .getText() ).toContai n('myForm. input.$val id = true' );
  18788         });
  18789  
  18790         it(' should be  invalid if  empty', f unction()  {
  18791           se tInput('') ;
  18792           ex pect(value .getText() ).toEqual( 'value =') ;
  18793           ex pect(valid .getText() ).toContai n('myForm. input.$val id = false ');
  18794         });
  18795  
  18796         it(' should be  invalid if  over max' , function () {
  18797           se tInput('20 15-01-01T2 3:59:00');
  18798           ex pect(value .getText() ).toContai n('');
  18799           ex pect(valid .getText() ).toContai n('myForm. input.$val id = false ');
  18800         });
  18801       </file >
  18802       </exam ple>
  18803       */
  18804     'datetim e-local':  createDate InputType( 'datetimel ocal', DAT ETIMELOCAL _REGEXP,
  18805         crea teDatePars er(DATETIM ELOCAL_REG EXP, ['yyy y', 'MM',  'dd', 'HH' , 'mm', 's s', 'sss'] ),
  18806         'yyy y-MM-ddTHH :mm:ss.sss '),
  18807  
  18808     /**
  18809      * @ngdo c input
  18810      * @name  input[tim e]
  18811      *
  18812      * @desc ription
  18813      * Input  with time  validatio n and tran sformation . In brows ers that d o not yet  support
  18814      * the H TML5 date  input, a t ext elemen t will be  used. In t hat case,  the text m ust be ent ered in a  valid ISO- 8601
  18815      * local  time form at (HH:mm: ss), for e xample: `1 4:57:00`.  Model must  be a Date  object. T his bindin g will alw ays output  a
  18816      * Date  object to  the model  of January  1, 1970,  or local d ate `new D ate(1970,  0, 1, HH,  mm, ss)`.
  18817      *
  18818      * The m odel must  always be  a Date obj ect, other wise Angul ar will th row an err or.
  18819      * Inval id `Date`  objects (d ates whose  `getTime( )` is `NaN `) will be  rendered  as an empt y string.
  18820      *
  18821      * The t imezone to  be used t o read/wri te the `Da te` instan ce in the  model can  be defined  using
  18822      * {@lin k ng.direc tive:ngMod elOptions  ngModelOpt ions}. By  default, t his is the  timezone  of the bro wser.
  18823      *
  18824      * @para m {string}  ngModel A ssignable  angular ex pression t o data-bin d to.
  18825      * @para m {string= } name Pro perty name  of the fo rm under w hich the c ontrol is  published.
  18826      * @para m {string= } min Sets  the `min`  validatio n error ke y if the v alue enter ed is less  than `min `. This mu st be a
  18827      * valid  ISO time  format (HH :mm:ss).
  18828      * @para m {string= } max Sets  the `max`  validatio n error ke y if the v alue enter ed is grea ter than ` max`. This  must be a
  18829      * valid  ISO time  format (HH :mm:ss).
  18830      * @para m {string= } required  Sets `req uired` val idation er ror key if  the value  is not en tered.
  18831      * @para m {string= } ngRequir ed Adds `r equired` a ttribute a nd `requir ed` valida tion const raint to
  18832      *    th e element  when the n gRequired  expression  evaluates  to true.  Use `ngReq uired` ins tead of
  18833      *    `r equired` w hen you wa nt to data -bind to t he `requir ed` attrib ute.
  18834      * @para m {string= } ngChange  Angular e xpression  to be exec uted when  input chan ges due to  user
  18835      *    in teraction  with the i nput eleme nt.
  18836      *
  18837      * @exam ple
  18838      <exampl e name="ti me-input-d irective"  module="ti meExample" >
  18839      <file n ame="index .html">
  18840        <scri pt>
  18841         angu lar.module ('timeExam ple', [])
  18842           .c ontroller( 'DateContr oller', [' $scope', f unction($s cope) {
  18843              $scope.val ue = new D ate(1970,  0, 1, 14,  57, 0);
  18844           }] );
  18845        </scr ipt>
  18846        <form  name="myF orm" ng-co ntroller=" DateContro ller as da teCtrl">
  18847           Pi ck a betwe en 8am and  5pm:
  18848           <i nput type= "time" id= "exampleIn put" name= "input" ng -model="va lue"
  18849                placehol der="HH:mm :ss" min=" 08:00:00"  max="17:00 :00" requi red />
  18850           <s pan class= "error" ng -show="myF orm.input. $error.req uired">
  18851                Required !</span>
  18852           <s pan class= "error" ng -show="myF orm.input. $error.tim e">
  18853                Not a va lid date!< /span>
  18854           <t t>value =  {{value |  date: "HH: mm:ss"}}</ tt><br/>
  18855           <t t>myForm.i nput.$vali d = {{myFo rm.input.$ valid}}</t t><br/>
  18856           <t t>myForm.i nput.$erro r = {{myFo rm.input.$ error}}</t t><br/>
  18857           <t t>myForm.$ valid = {{ myForm.$va lid}}</tt> <br/>
  18858           <t t>myForm.$ error.requ ired = {{! !myForm.$e rror.requi red}}</tt> <br/>
  18859        </for m>
  18860      </file>
  18861      <file n ame="protr actor.js"  type="prot ractor">
  18862         var  value = el ement(by.b inding('va lue | date : "HH:mm:s s"'));
  18863         var  valid = el ement(by.b inding('my Form.input .$valid')) ;
  18864         var  input = el ement(by.m odel('valu e'));
  18865  
  18866         // c urrently p rotractor/ webdriver  does not s upport
  18867         // s ending key s to all k nown HTML5  input con trols
  18868         // f or various  browsers  (https://g ithub.com/ angular/pr otractor/i ssues/562) .
  18869         func tion setIn put(val) {
  18870           //  set the v alue of th e element  and force  validation .
  18871           va r scr = "v ar ipt = d ocument.ge tElementBy Id('exampl eInput');  " +
  18872           "i pt.value =  '" + val  + "';" +
  18873           "a ngular.ele ment(ipt). scope().$a pply(funct ion(s) { s .myForm[ip t.name].$s etViewValu e('" + val  + "'); }) ;";
  18874           br owser.exec uteScript( scr);
  18875         }
  18876  
  18877         it(' should ini tialize to  model', f unction()  {
  18878           ex pect(value .getText() ).toContai n('14:57:0 0');
  18879           ex pect(valid .getText() ).toContai n('myForm. input.$val id = true' );
  18880         });
  18881  
  18882         it(' should be  invalid if  empty', f unction()  {
  18883           se tInput('') ;
  18884           ex pect(value .getText() ).toEqual( 'value =') ;
  18885           ex pect(valid .getText() ).toContai n('myForm. input.$val id = false ');
  18886         });
  18887  
  18888         it(' should be  invalid if  over max' , function () {
  18889           se tInput('23 :59:00');
  18890           ex pect(value .getText() ).toContai n('');
  18891           ex pect(valid .getText() ).toContai n('myForm. input.$val id = false ');
  18892         });
  18893      </file>
  18894      </examp le>
  18895      */
  18896     'time':  createDate InputType( 'time', TI ME_REGEXP,
  18897         crea teDatePars er(TIME_RE GEXP, ['HH ', 'mm', ' ss', 'sss' ]),
  18898        'HH:m m:ss.sss') ,
  18899  
  18900      /**
  18901       * @ngd oc input
  18902       * @nam e input[we ek]
  18903       *
  18904       * @des cription
  18905       * Inpu t with wee k-of-the-y ear valida tion and t ransformat ion to Dat e. In brow sers that  do not yet  support
  18906       * the  HTML5 week  input, a  text eleme nt will be  used. In  that case,  the text  must be en tered in a  valid ISO -8601
  18907       * week  format (y yyy-W##),  for exampl e: `2013-W 02`.
  18908       *
  18909       * The  model must  always be  a Date ob ject, othe rwise Angu lar will t hrow an er ror.
  18910       * Inva lid `Date`  objects ( dates whos e `getTime ()` is `Na N`) will b e rendered  as an emp ty string.
  18911       *
  18912       * The  timezone t o be used  to read/wr ite the `D ate` insta nce in the  model can  be define d using
  18913       * {@li nk ng.dire ctive:ngMo delOptions  ngModelOp tions}. By  default,  this is th e timezone  of the br owser.
  18914       *
  18915       * @par am {string } ngModel  Assignable  angular e xpression  to data-bi nd to.
  18916       * @par am {string =} name Pr operty nam e of the f orm under  which the  control is  published .
  18917       * @par am {string =} min Set s the `min ` validati on error k ey if the  value ente red is les s than `mi n`. This m ust be a
  18918       * vali d ISO week  format (y yyy-W##).
  18919       * @par am {string =} max Set s the `max ` validati on error k ey if the  value ente red is gre ater than  `max`. Thi s must be
  18920       * a va lid ISO we ek format  (yyyy-W##) .
  18921       * @par am {string =} require d Sets `re quired` va lidation e rror key i f the valu e is not e ntered.
  18922       * @par am {string =} ngRequi red Adds ` required`  attribute  and `requi red` valid ation cons traint to
  18923       *    t he element  when the  ngRequired  expressio n evaluate s to true.  Use `ngRe quired` in stead of
  18924       *    ` required`  when you w ant to dat a-bind to  the `requi red` attri bute.
  18925       * @par am {string =} ngChang e Angular  expression  to be exe cuted when  input cha nges due t o user
  18926       *    i nteraction  with the  input elem ent.
  18927       *
  18928       * @exa mple
  18929       <examp le name="w eek-input- directive"  module="w eekExample ">
  18930       <file  name="inde x.html">
  18931         <scr ipt>
  18932         angu lar.module ('weekExam ple', [])
  18933           .c ontroller( 'DateContr oller', [' $scope', f unction($s cope) {
  18934              $scope.val ue = new D ate(2013,  0, 3);
  18935           }] );
  18936         </sc ript>
  18937         <for m name="my Form" ng-c ontroller= "DateContr oller as d ateCtrl">
  18938           Pi ck a date  between in  2013:
  18939           <i nput id="e xampleInpu t" type="w eek" name= "input" ng -model="va lue"
  18940                placehol der="YYYY- W##" min=" 2012-W32"  max="2013- W52" requi red />
  18941           <s pan class= "error" ng -show="myF orm.input. $error.req uired">
  18942                Required !</span>
  18943           <s pan class= "error" ng -show="myF orm.input. $error.wee k">
  18944                Not a va lid date!< /span>
  18945           <t t>value =  {{value |  date: "yyy y-Www"}}</ tt><br/>
  18946           <t t>myForm.i nput.$vali d = {{myFo rm.input.$ valid}}</t t><br/>
  18947           <t t>myForm.i nput.$erro r = {{myFo rm.input.$ error}}</t t><br/>
  18948           <t t>myForm.$ valid = {{ myForm.$va lid}}</tt> <br/>
  18949           <t t>myForm.$ error.requ ired = {{! !myForm.$e rror.requi red}}</tt> <br/>
  18950         </fo rm>
  18951       </file >
  18952       <file  name="prot ractor.js"  type="pro tractor">
  18953         var  value = el ement(by.b inding('va lue | date : "yyyy-Ww w"'));
  18954         var  valid = el ement(by.b inding('my Form.input .$valid')) ;
  18955         var  input = el ement(by.m odel('valu e'));
  18956  
  18957         // c urrently p rotractor/ webdriver  does not s upport
  18958         // s ending key s to all k nown HTML5  input con trols
  18959         // f or various  browsers  (https://g ithub.com/ angular/pr otractor/i ssues/562) .
  18960         func tion setIn put(val) {
  18961           //  set the v alue of th e element  and force  validation .
  18962           va r scr = "v ar ipt = d ocument.ge tElementBy Id('exampl eInput');  " +
  18963           "i pt.value =  '" + val  + "';" +
  18964           "a ngular.ele ment(ipt). scope().$a pply(funct ion(s) { s .myForm[ip t.name].$s etViewValu e('" + val  + "'); }) ;";
  18965           br owser.exec uteScript( scr);
  18966         }
  18967  
  18968         it(' should ini tialize to  model', f unction()  {
  18969           ex pect(value .getText() ).toContai n('2013-W0 1');
  18970           ex pect(valid .getText() ).toContai n('myForm. input.$val id = true' );
  18971         });
  18972  
  18973         it(' should be  invalid if  empty', f unction()  {
  18974           se tInput('') ;
  18975           ex pect(value .getText() ).toEqual( 'value =') ;
  18976           ex pect(valid .getText() ).toContai n('myForm. input.$val id = false ');
  18977         });
  18978  
  18979         it(' should be  invalid if  over max' , function () {
  18980           se tInput('20 15-W01');
  18981           ex pect(value .getText() ).toContai n('');
  18982           ex pect(valid .getText() ).toContai n('myForm. input.$val id = false ');
  18983         });
  18984       </file >
  18985       </exam ple>
  18986       */
  18987     'week':  createDate InputType( 'week', WE EK_REGEXP,  weekParse r, 'yyyy-W ww'),
  18988  
  18989     /**
  18990      * @ngdo c input
  18991      * @name  input[mon th]
  18992      *
  18993      * @desc ription
  18994      * Input  with mont h validati on and tra nsformatio n. In brow sers that  do not yet  support
  18995      * the H TML5 month  input, a  text eleme nt will be  used. In  that case,  the text  must be en tered in a  valid ISO -8601
  18996      * month  format (y yyy-MM), f or example : `2009-01 `.
  18997      *
  18998      * The m odel must  always be  a Date obj ect, other wise Angul ar will th row an err or.
  18999      * Inval id `Date`  objects (d ates whose  `getTime( )` is `NaN `) will be  rendered  as an empt y string.
  19000      * If th e model is  not set t o the firs t of the m onth, the  next view  to model u pdate will  set it
  19001      * to th e first of  the month .
  19002      *
  19003      * The t imezone to  be used t o read/wri te the `Da te` instan ce in the  model can  be defined  using
  19004      * {@lin k ng.direc tive:ngMod elOptions  ngModelOpt ions}. By  default, t his is the  timezone  of the bro wser.
  19005      *
  19006      * @para m {string}  ngModel A ssignable  angular ex pression t o data-bin d to.
  19007      * @para m {string= } name Pro perty name  of the fo rm under w hich the c ontrol is  published.
  19008      * @para m {string= } min Sets  the `min`  validatio n error ke y if the v alue enter ed is less  than `min `. This mu st be
  19009      * a val id ISO mon th format  (yyyy-MM).
  19010      * @para m {string= } max Sets  the `max`  validatio n error ke y if the v alue enter ed is grea ter than ` max`. This  must
  19011      * be a  valid ISO  month form at (yyyy-M M).
  19012      * @para m {string= } required  Sets `req uired` val idation er ror key if  the value  is not en tered.
  19013      * @para m {string= } ngRequir ed Adds `r equired` a ttribute a nd `requir ed` valida tion const raint to
  19014      *    th e element  when the n gRequired  expression  evaluates  to true.  Use `ngReq uired` ins tead of
  19015      *    `r equired` w hen you wa nt to data -bind to t he `requir ed` attrib ute.
  19016      * @para m {string= } ngChange  Angular e xpression  to be exec uted when  input chan ges due to  user
  19017      *    in teraction  with the i nput eleme nt.
  19018      *
  19019      * @exam ple
  19020      <exampl e name="mo nth-input- directive"  module="m onthExampl e">
  19021      <file n ame="index .html">
  19022        <scri pt>
  19023         angu lar.module ('monthExa mple', [])
  19024           .c ontroller( 'DateContr oller', [' $scope', f unction($s cope) {
  19025              $scope.val ue = new D ate(2013,  9, 1);
  19026           }] );
  19027        </scr ipt>
  19028        <form  name="myF orm" ng-co ntroller=" DateContro ller as da teCtrl">
  19029          Pic k a month  int 2013:
  19030          <in put id="ex ampleInput " type="mo nth" name= "input" ng -model="va lue"
  19031              placeholde r="yyyy-MM " min="201 3-01" max= "2013-12"  required / >
  19032          <sp an class=" error" ng- show="myFo rm.input.$ error.requ ired">
  19033              Required!< /span>
  19034          <sp an class=" error" ng- show="myFo rm.input.$ error.mont h">
  19035              Not a vali d month!</ span>
  19036          <tt >value = { {value | d ate: "yyyy -MM"}}</tt ><br/>
  19037          <tt >myForm.in put.$valid  = {{myFor m.input.$v alid}}</tt ><br/>
  19038          <tt >myForm.in put.$error  = {{myFor m.input.$e rror}}</tt ><br/>
  19039          <tt >myForm.$v alid = {{m yForm.$val id}}</tt>< br/>
  19040          <tt >myForm.$e rror.requi red = {{!! myForm.$er ror.requir ed}}</tt>< br/>
  19041        </for m>
  19042      </file>
  19043      <file n ame="protr actor.js"  type="prot ractor">
  19044         var  value = el ement(by.b inding('va lue | date : "yyyy-MM "'));
  19045         var  valid = el ement(by.b inding('my Form.input .$valid')) ;
  19046         var  input = el ement(by.m odel('valu e'));
  19047  
  19048         // c urrently p rotractor/ webdriver  does not s upport
  19049         // s ending key s to all k nown HTML5  input con trols
  19050         // f or various  browsers  (https://g ithub.com/ angular/pr otractor/i ssues/562) .
  19051         func tion setIn put(val) {
  19052           //  set the v alue of th e element  and force  validation .
  19053           va r scr = "v ar ipt = d ocument.ge tElementBy Id('exampl eInput');  " +
  19054           "i pt.value =  '" + val  + "';" +
  19055           "a ngular.ele ment(ipt). scope().$a pply(funct ion(s) { s .myForm[ip t.name].$s etViewValu e('" + val  + "'); }) ;";
  19056           br owser.exec uteScript( scr);
  19057         }
  19058  
  19059         it(' should ini tialize to  model', f unction()  {
  19060           ex pect(value .getText() ).toContai n('2013-10 ');
  19061           ex pect(valid .getText() ).toContai n('myForm. input.$val id = true' );
  19062         });
  19063  
  19064         it(' should be  invalid if  empty', f unction()  {
  19065           se tInput('') ;
  19066           ex pect(value .getText() ).toEqual( 'value =') ;
  19067           ex pect(valid .getText() ).toContai n('myForm. input.$val id = false ');
  19068         });
  19069  
  19070         it(' should be  invalid if  over max' , function () {
  19071           se tInput('20 15-01');
  19072           ex pect(value .getText() ).toContai n('');
  19073           ex pect(valid .getText() ).toContai n('myForm. input.$val id = false ');
  19074         });
  19075      </file>
  19076      </examp le>
  19077      */
  19078     'month':  createDat eInputType ('month',  MONTH_REGE XP,
  19079        creat eDateParse r(MONTH_RE GEXP, ['yy yy', 'MM'] ),
  19080        'yyyy -MM'),
  19081  
  19082     /**
  19083      * @ngdo c input
  19084      * @name  input[num ber]
  19085      *
  19086      * @desc ription
  19087      * Text  input with  number va lidation a nd transfo rmation. S ets the `n umber` val idation
  19088      * error  if not a  valid numb er.
  19089      *
  19090      * The m odel must  always be  a number,  otherwise  Angular wi ll throw a n error.
  19091      *
  19092      * @para m {string}  ngModel A ssignable  angular ex pression t o data-bin d to.
  19093      * @para m {string= } name Pro perty name  of the fo rm under w hich the c ontrol is  published.
  19094      * @para m {string= } min Sets  the `min`  validatio n error ke y if the v alue enter ed is less  than `min `.
  19095      * @para m {string= } max Sets  the `max`  validatio n error ke y if the v alue enter ed is grea ter than ` max`.
  19096      * @para m {string= } required  Sets `req uired` val idation er ror key if  the value  is not en tered.
  19097      * @para m {string= } ngRequir ed Adds `r equired` a ttribute a nd `requir ed` valida tion const raint to
  19098      *    th e element  when the n gRequired  expression  evaluates  to true.  Use `ngReq uired` ins tead of
  19099      *    `r equired` w hen you wa nt to data -bind to t he `requir ed` attrib ute.
  19100      * @para m {number= } ngMinlen gth Sets ` minlength`  validatio n error ke y if the v alue is sh orter than
  19101      *    mi nlength.
  19102      * @para m {number= } ngMaxlen gth Sets ` maxlength`  validatio n error ke y if the v alue is lo nger than
  19103      *    ma xlength. S etting the  attribute  to a nega tive or no n-numeric  value, all ows view v alues of
  19104      *    an y length.
  19105      * @para m {string= } pattern  Similar to  `ngPatter n` except  that the a ttribute v alue is th e actual s tring
  19106      *    th at contain s the regu lar expres sion body  that will  be convert ed to a re gular expr ession
  19107      *    as  in the ng Pattern di rective.
  19108      * @para m {string= } ngPatter n Sets `pa ttern` val idation er ror key if  the ngMod el value d oes not ma tch
  19109      *    a  RegExp fou nd by eval uating the  Angular e xpression  given in t he attribu te value.
  19110      *    If  the expre ssion eval uates to a  RegExp ob ject then  this is us ed directl y.
  19111      *    If  the expre ssion is a  string th en it will  be conver ted to a R egExp afte r wrapping  it in `^`  and `$`
  19112      *    ch aracters.  For instan ce, `"abc" ` will be  converted  to `new Re gExp('^abc $')`.
  19113      * @para m {string= } ngChange  Angular e xpression  to be exec uted when  input chan ges due to  user
  19114      *    in teraction  with the i nput eleme nt.
  19115      *
  19116      * @exam ple
  19117         <exa mple name= "number-in put-direct ive" modul e="numberE xample">
  19118           <f ile name=" index.html ">
  19119            < script>
  19120               angular.m odule('num berExample ', [])
  19121                 .contro ller('Exam pleControl ler', ['$s cope', fun ction($sco pe) {
  19122                   $scop e.value =  12;
  19123                 }]);
  19124            < /script>
  19125            < form name= "myForm" n g-controll er="Exampl eControlle r">
  19126               Number: < input type ="number"  name="inpu t" ng-mode l="value"
  19127                               min= "0" max="9 9" require d>
  19128               <span cla ss="error"  ng-show=" myForm.inp ut.$error. required">
  19129                 Require d!</span>
  19130               <span cla ss="error"  ng-show=" myForm.inp ut.$error. number">
  19131                 Not val id number! </span>
  19132               <tt>value  = {{value }}</tt><br />
  19133               <tt>myFor m.input.$v alid = {{m yForm.inpu t.$valid}} </tt><br/>
  19134               <tt>myFor m.input.$e rror = {{m yForm.inpu t.$error}} </tt><br/>
  19135               <tt>myFor m.$valid =  {{myForm. $valid}}</ tt><br/>
  19136               <tt>myFor m.$error.r equired =  {{!!myForm .$error.re quired}}</ tt><br/>
  19137              </form>
  19138           </ file>
  19139           <f ile name=" protractor .js" type= "protracto r">
  19140              var value  = element( by.binding ('value')) ;
  19141              var valid  = element( by.binding ('myForm.i nput.$vali d'));
  19142              var input  = element( by.model(' value'));
  19143  
  19144              it('should  initializ e to model ', functio n() {
  19145                expect(v alue.getTe xt()).toCo ntain('12' );
  19146                expect(v alid.getTe xt()).toCo ntain('tru e');
  19147              });
  19148  
  19149              it('should  be invali d if empty ', functio n() {
  19150                input.cl ear();
  19151                input.se ndKeys('') ;
  19152                expect(v alue.getTe xt()).toEq ual('value  =');
  19153                expect(v alid.getTe xt()).toCo ntain('fal se');
  19154              });
  19155  
  19156              it('should  be invali d if over  max', func tion() {
  19157                input.cl ear();
  19158                input.se ndKeys('12 3');
  19159                expect(v alue.getTe xt()).toEq ual('value  =');
  19160                expect(v alid.getTe xt()).toCo ntain('fal se');
  19161              });
  19162           </ file>
  19163         </ex ample>
  19164      */
  19165     'number' : numberIn putType,
  19166  
  19167  
  19168     /**
  19169      * @ngdo c input
  19170      * @name  input[url ]
  19171      *
  19172      * @desc ription
  19173      * Text  input with  URL valid ation. Set s the `url ` validati on error k ey if the  content is  not a
  19174      * valid  URL.
  19175      *
  19176      * <div  class="ale rt alert-w arning">
  19177      * **Not e:** `inpu t[url]` us es a regex  to valida te urls th at is deri ved from t he regex
  19178      * used  in Chromiu m. If you  need stric ter valida tion, you  can use `n g-pattern`  or modify
  19179      * the b uilt-in va lidators ( see the {@ link guide /forms For ms guide})
  19180      * </div >
  19181      *
  19182      * @para m {string}  ngModel A ssignable  angular ex pression t o data-bin d to.
  19183      * @para m {string= } name Pro perty name  of the fo rm under w hich the c ontrol is  published.
  19184      * @para m {string= } required  Sets `req uired` val idation er ror key if  the value  is not en tered.
  19185      * @para m {string= } ngRequir ed Adds `r equired` a ttribute a nd `requir ed` valida tion const raint to
  19186      *    th e element  when the n gRequired  expression  evaluates  to true.  Use `ngReq uired` ins tead of
  19187      *    `r equired` w hen you wa nt to data -bind to t he `requir ed` attrib ute.
  19188      * @para m {number= } ngMinlen gth Sets ` minlength`  validatio n error ke y if the v alue is sh orter than
  19189      *    mi nlength.
  19190      * @para m {number= } ngMaxlen gth Sets ` maxlength`  validatio n error ke y if the v alue is lo nger than
  19191      *    ma xlength. S etting the  attribute  to a nega tive or no n-numeric  value, all ows view v alues of
  19192      *    an y length.
  19193      * @para m {string= } pattern  Similar to  `ngPatter n` except  that the a ttribute v alue is th e actual s tring
  19194      *    th at contain s the regu lar expres sion body  that will  be convert ed to a re gular expr ession
  19195      *    as  in the ng Pattern di rective.
  19196      * @para m {string= } ngPatter n Sets `pa ttern` val idation er ror key if  the ngMod el value d oes not ma tch
  19197      *    a  RegExp fou nd by eval uating the  Angular e xpression  given in t he attribu te value.
  19198      *    If  the expre ssion eval uates to a  RegExp ob ject then  this is us ed directl y.
  19199      *    If  the expre ssion is a  string th en it will  be conver ted to a R egExp afte r wrapping  it in `^`  and `$`
  19200      *    ch aracters.  For instan ce, `"abc" ` will be  converted  to `new Re gExp('^abc $')`.
  19201      * @para m {string= } ngChange  Angular e xpression  to be exec uted when  input chan ges due to  user
  19202      *    in teraction  with the i nput eleme nt.
  19203      *
  19204      * @exam ple
  19205         <exa mple name= "url-input -directive " module=" urlExample ">
  19206           <f ile name=" index.html ">
  19207            < script>
  19208               angular.m odule('url Example',  [])
  19209                 .contro ller('Exam pleControl ler', ['$s cope', fun ction($sco pe) {
  19210                   $scop e.text = ' http://goo gle.com';
  19211                 }]);
  19212            < /script>
  19213            < form name= "myForm" n g-controll er="Exampl eControlle r">
  19214               URL: <inp ut type="u rl" name=" input" ng- model="tex t" require d>
  19215               <span cla ss="error"  ng-show=" myForm.inp ut.$error. required">
  19216                 Require d!</span>
  19217               <span cla ss="error"  ng-show=" myForm.inp ut.$error. url">
  19218                 Not val id url!</s pan>
  19219               <tt>text  = {{text}} </tt><br/>
  19220               <tt>myFor m.input.$v alid = {{m yForm.inpu t.$valid}} </tt><br/>
  19221               <tt>myFor m.input.$e rror = {{m yForm.inpu t.$error}} </tt><br/>
  19222               <tt>myFor m.$valid =  {{myForm. $valid}}</ tt><br/>
  19223               <tt>myFor m.$error.r equired =  {{!!myForm .$error.re quired}}</ tt><br/>
  19224               <tt>myFor m.$error.u rl = {{!!m yForm.$err or.url}}</ tt><br/>
  19225              </form>
  19226           </ file>
  19227           <f ile name=" protractor .js" type= "protracto r">
  19228              var text =  element(b y.binding( 'text'));
  19229              var valid  = element( by.binding ('myForm.i nput.$vali d'));
  19230              var input  = element( by.model(' text'));
  19231  
  19232              it('should  initializ e to model ', functio n() {
  19233                expect(t ext.getTex t()).toCon tain('http ://google. com');
  19234                expect(v alid.getTe xt()).toCo ntain('tru e');
  19235              });
  19236  
  19237              it('should  be invali d if empty ', functio n() {
  19238                input.cl ear();
  19239                input.se ndKeys('') ;
  19240  
  19241                expect(t ext.getTex t()).toEqu al('text = ');
  19242                expect(v alid.getTe xt()).toCo ntain('fal se');
  19243              });
  19244  
  19245              it('should  be invali d if not u rl', funct ion() {
  19246                input.cl ear();
  19247                input.se ndKeys('bo x');
  19248  
  19249                expect(v alid.getTe xt()).toCo ntain('fal se');
  19250              });
  19251           </ file>
  19252         </ex ample>
  19253      */
  19254     'url': u rlInputTyp e,
  19255  
  19256  
  19257     /**
  19258      * @ngdo c input
  19259      * @name  input[ema il]
  19260      *
  19261      * @desc ription
  19262      * Text  input with  email val idation. S ets the `e mail` vali dation err or key if  not a vali d email
  19263      * addre ss.
  19264      *
  19265      * <div  class="ale rt alert-w arning">
  19266      * **Not e:** `inpu t[email]`  uses a reg ex to vali date email  addresses  that is d erived fro m the rege x
  19267      * used  in Chromiu m. If you  need stric ter valida tion (e.g.  requiring  a top-lev el domain) , you can
  19268      * use ` ng-pattern ` or modif y the buil t-in valid ators (see  the {@lin k guide/fo rms Forms  guide})
  19269      * </div >
  19270      *
  19271      * @para m {string}  ngModel A ssignable  angular ex pression t o data-bin d to.
  19272      * @para m {string= } name Pro perty name  of the fo rm under w hich the c ontrol is  published.
  19273      * @para m {string= } required  Sets `req uired` val idation er ror key if  the value  is not en tered.
  19274      * @para m {string= } ngRequir ed Adds `r equired` a ttribute a nd `requir ed` valida tion const raint to
  19275      *    th e element  when the n gRequired  expression  evaluates  to true.  Use `ngReq uired` ins tead of
  19276      *    `r equired` w hen you wa nt to data -bind to t he `requir ed` attrib ute.
  19277      * @para m {number= } ngMinlen gth Sets ` minlength`  validatio n error ke y if the v alue is sh orter than
  19278      *    mi nlength.
  19279      * @para m {number= } ngMaxlen gth Sets ` maxlength`  validatio n error ke y if the v alue is lo nger than
  19280      *    ma xlength. S etting the  attribute  to a nega tive or no n-numeric  value, all ows view v alues of
  19281      *    an y length.
  19282      * @para m {string= } pattern  Similar to  `ngPatter n` except  that the a ttribute v alue is th e actual s tring
  19283      *    th at contain s the regu lar expres sion body  that will  be convert ed to a re gular expr ession
  19284      *    as  in the ng Pattern di rective.
  19285      * @para m {string= } ngPatter n Sets `pa ttern` val idation er ror key if  the ngMod el value d oes not ma tch
  19286      *    a  RegExp fou nd by eval uating the  Angular e xpression  given in t he attribu te value.
  19287      *    If  the expre ssion eval uates to a  RegExp ob ject then  this is us ed directl y.
  19288      *    If  the expre ssion is a  string th en it will  be conver ted to a R egExp afte r wrapping  it in `^`  and `$`
  19289      *    ch aracters.  For instan ce, `"abc" ` will be  converted  to `new Re gExp('^abc $')`.
  19290      * @para m {string= } ngChange  Angular e xpression  to be exec uted when  input chan ges due to  user
  19291      *    in teraction  with the i nput eleme nt.
  19292      *
  19293      * @exam ple
  19294         <exa mple name= "email-inp ut-directi ve" module ="emailExa mple">
  19295           <f ile name=" index.html ">
  19296            < script>
  19297               angular.m odule('ema ilExample' , [])
  19298                 .contro ller('Exam pleControl ler', ['$s cope', fun ction($sco pe) {
  19299                   $scop e.text = ' me@example .com';
  19300                 }]);
  19301            < /script>
  19302               <form nam e="myForm"  ng-contro ller="Exam pleControl ler">
  19303                 Email:  <input typ e="email"  name="inpu t" ng-mode l="text" r equired>
  19304                 <span c lass="erro r" ng-show ="myForm.i nput.$erro r.required ">
  19305                   Requi red!</span >
  19306                 <span c lass="erro r" ng-show ="myForm.i nput.$erro r.email">
  19307                   Not v alid email !</span>
  19308                 <tt>tex t = {{text }}</tt><br />
  19309                 <tt>myF orm.input. $valid = { {myForm.in put.$valid }}</tt><br />
  19310                 <tt>myF orm.input. $error = { {myForm.in put.$error }}</tt><br />
  19311                 <tt>myF orm.$valid  = {{myFor m.$valid}} </tt><br/>
  19312                 <tt>myF orm.$error .required  = {{!!myFo rm.$error. required}} </tt><br/>
  19313                 <tt>myF orm.$error .email = { {!!myForm. $error.ema il}}</tt>< br/>
  19314               </form>
  19315            < /file>
  19316           <f ile name=" protractor .js" type= "protracto r">
  19317              var text =  element(b y.binding( 'text'));
  19318              var valid  = element( by.binding ('myForm.i nput.$vali d'));
  19319              var input  = element( by.model(' text'));
  19320  
  19321              it('should  initializ e to model ', functio n() {
  19322                expect(t ext.getTex t()).toCon tain('me@e xample.com ');
  19323                expect(v alid.getTe xt()).toCo ntain('tru e');
  19324              });
  19325  
  19326              it('should  be invali d if empty ', functio n() {
  19327                input.cl ear();
  19328                input.se ndKeys('') ;
  19329                expect(t ext.getTex t()).toEqu al('text = ');
  19330                expect(v alid.getTe xt()).toCo ntain('fal se');
  19331              });
  19332  
  19333              it('should  be invali d if not e mail', fun ction() {
  19334                input.cl ear();
  19335                input.se ndKeys('xx x');
  19336  
  19337                expect(v alid.getTe xt()).toCo ntain('fal se');
  19338              });
  19339           </ file>
  19340         </ex ample>
  19341      */
  19342     'email':  emailInpu tType,
  19343  
  19344  
  19345     /**
  19346      * @ngdo c input
  19347      * @name  input[rad io]
  19348      *
  19349      * @desc ription
  19350      * HTML  radio butt on.
  19351      *
  19352      * @para m {string}  ngModel A ssignable  angular ex pression t o data-bin d to.
  19353      * @para m {string}  value The  value to  which the  expression  should be  set when  selected.
  19354      * @para m {string= } name Pro perty name  of the fo rm under w hich the c ontrol is  published.
  19355      * @para m {string= } ngChange  Angular e xpression  to be exec uted when  input chan ges due to  user
  19356      *    in teraction  with the i nput eleme nt.
  19357      * @para m {string}  ngValue A ngular exp ression wh ich sets t he value t o which th e expressi on should
  19358      *    be  set when  selected.
  19359      *
  19360      * @exam ple
  19361         <exa mple name= "radio-inp ut-directi ve" module ="radioExa mple">
  19362           <f ile name=" index.html ">
  19363            < script>
  19364               angular.m odule('rad ioExample' , [])
  19365                 .contro ller('Exam pleControl ler', ['$s cope', fun ction($sco pe) {
  19366                   $scop e.color =  'blue';
  19367                   $scop e.specialV alue = {
  19368                     "id ": "12345" ,
  19369                     "va lue": "gre en"
  19370                   };
  19371                 }]);
  19372            < /script>
  19373            < form name= "myForm" n g-controll er="Exampl eControlle r">
  19374               <input ty pe="radio"  ng-model= "color" va lue="red">   Red <br/ >
  19375               <input ty pe="radio"  ng-model= "color" ng -value="sp ecialValue "> Green < br/>
  19376               <input ty pe="radio"  ng-model= "color" va lue="blue" > Blue <br />
  19377               <tt>color  = {{color  | json}}< /tt><br/>
  19378              </form>
  19379              Note that  `ng-value= "specialVa lue"` sets  radio ite m's value  to be the  value of ` $scope.spe cialValue` .
  19380           </ file>
  19381           <f ile name=" protractor .js" type= "protracto r">
  19382              it('should  change st ate', func tion() {
  19383                var colo r = elemen t(by.bindi ng('color' ));
  19384  
  19385                expect(c olor.getTe xt()).toCo ntain('blu e');
  19386  
  19387                element. all(by.mod el('color' )).get(0). click();
  19388  
  19389                expect(c olor.getTe xt()).toCo ntain('red ');
  19390              });
  19391           </ file>
  19392         </ex ample>
  19393      */
  19394     'radio':  radioInpu tType,
  19395  
  19396  
  19397     /**
  19398      * @ngdo c input
  19399      * @name  input[che ckbox]
  19400      *
  19401      * @desc ription
  19402      * HTML  checkbox.
  19403      *
  19404      * @para m {string}  ngModel A ssignable  angular ex pression t o data-bin d to.
  19405      * @para m {string= } name Pro perty name  of the fo rm under w hich the c ontrol is  published.
  19406      * @para m {express ion=} ngTr ueValue Th e value to  which the  expressio n should b e set when  selected.
  19407      * @para m {express ion=} ngFa lseValue T he value t o which th e expressi on should  be set whe n not sele cted.
  19408      * @para m {string= } ngChange  Angular e xpression  to be exec uted when  input chan ges due to  user
  19409      *    in teraction  with the i nput eleme nt.
  19410      *
  19411      * @exam ple
  19412         <exa mple name= "checkbox- input-dire ctive" mod ule="check boxExample ">
  19413           <f ile name=" index.html ">
  19414            < script>
  19415               angular.m odule('che ckboxExamp le', [])
  19416                 .contro ller('Exam pleControl ler', ['$s cope', fun ction($sco pe) {
  19417                   $scop e.value1 =  true;
  19418                   $scop e.value2 =  'YES'
  19419                 }]);
  19420            < /script>
  19421            < form name= "myForm" n g-controll er="Exampl eControlle r">
  19422               Value1: < input type ="checkbox " ng-model ="value1">  <br/>
  19423               Value2: < input type ="checkbox " ng-model ="value2"
  19424                               ng-t rue-value= "'YES'" ng -false-val ue="'NO'">  <br/>
  19425               <tt>value 1 = {{valu e1}}</tt>< br/>
  19426               <tt>value 2 = {{valu e2}}</tt>< br/>
  19427              </form>
  19428           </ file>
  19429           <f ile name=" protractor .js" type= "protracto r">
  19430              it('should  change st ate', func tion() {
  19431                var valu e1 = eleme nt(by.bind ing('value 1'));
  19432                var valu e2 = eleme nt(by.bind ing('value 2'));
  19433  
  19434                expect(v alue1.getT ext()).toC ontain('tr ue');
  19435                expect(v alue2.getT ext()).toC ontain('YE S');
  19436  
  19437                element( by.model(' value1')). click();
  19438                element( by.model(' value2')). click();
  19439  
  19440                expect(v alue1.getT ext()).toC ontain('fa lse');
  19441                expect(v alue2.getT ext()).toC ontain('NO ');
  19442              });
  19443           </ file>
  19444         </ex ample>
  19445      */
  19446     'checkbo x': checkb oxInputTyp e,
  19447  
  19448     'hidden' : noop,
  19449     'button' : noop,
  19450     'submit' : noop,
  19451     'reset':  noop,
  19452     'file':  noop
  19453   };
  19454  
  19455   function s tringBased InputType( ctrl) {
  19456     ctrl.$fo rmatters.p ush(functi on(value)  {
  19457       return  ctrl.$isE mpty(value ) ? value  : value.to String();
  19458     });
  19459   }
  19460  
  19461   function t extInputTy pe(scope,  element, a ttr, ctrl,  $sniffer,  $browser)  {
  19462     baseInpu tType(scop e, element , attr, ct rl, $sniff er, $brows er);
  19463     stringBa sedInputTy pe(ctrl);
  19464   }
  19465  
  19466   function b aseInputTy pe(scope,  element, a ttr, ctrl,  $sniffer,  $browser)  {
  19467     var plac eholder =  element[0] .placehold er, noeven t = {};
  19468     var type  = lowerca se(element [0].type);
  19469  
  19470     // In co mposition  mode, user s are stil l inputing  intermedi ate text b uffer,
  19471     // hold  the listen er until c omposition  is done.
  19472     // More  about comp osition ev ents: http s://develo per.mozill a.org/en-U S/docs/Web /API/Compo sitionEven t
  19473     if (!$sn iffer.andr oid) {
  19474       var co mposing =  false;
  19475  
  19476       elemen t.on('comp ositionsta rt', funct ion(data)  {
  19477         comp osing = tr ue;
  19478       });
  19479  
  19480       elemen t.on('comp ositionend ', functio n() {
  19481         comp osing = fa lse;
  19482         list ener();
  19483       });
  19484     }
  19485  
  19486     var list ener = fun ction(ev)  {
  19487       if (co mposing) r eturn;
  19488       var va lue = elem ent.val(),
  19489           ev ent = ev & & ev.type;
  19490  
  19491       // IE  (11 and un der) seem  to emit an  'input' e vent if th e placehol der value  changes.
  19492       // We  don't want  to dirty  the value  when this  happens, s o we abort  here. Unf ortunately ,
  19493       // IE  also sends  input eve nts for ot her non-in put-relate d things,  (such as f ocusing on  a
  19494       // for m control) , so this  change is  not entire ly enough  to solve t his.
  19495       if (ms ie && (ev  || noevent ).type ===  'input' & & element[ 0].placeho lder !== p laceholder ) {
  19496         plac eholder =  element[0] .placehold er;
  19497         retu rn;
  19498       }
  19499  
  19500       // By  default we  will trim  the value
  19501       // If  the attrib ute ng-tri m exists w e will avo id trimmin g
  19502       // If  input type  is 'passw ord', the  value is n ever trimm ed
  19503       if (ty pe !== 'pa ssword' &&  (!attr.ng Trim || at tr.ngTrim  !== 'false ')) {
  19504         valu e = trim(v alue);
  19505       }
  19506  
  19507       // If  a control  is sufferi ng from ba d input (d ue to nati ve validat ors), brow sers disca rd its
  19508       // val ue, so it  may be nec essary to  revalidate  (by calli ng $setVie wValue aga in) even i f the
  19509       // con trol's val ue is the  same empty  value twi ce in a ro w.
  19510       if (ct rl.$viewVa lue !== va lue || (va lue === ''  && ctrl.$ $hasNative Validators )) {
  19511         ctrl .$setViewV alue(value , event);
  19512       }
  19513     };
  19514  
  19515     // if th e browser  does suppo rt "input"  event, we  are fine  - except o n IE9 whic h doesn't  fire the
  19516     // input  event on  backspace,  delete or  cut
  19517     if ($sni ffer.hasEv ent('input ')) {
  19518       elemen t.on('inpu t', listen er);
  19519     } else {
  19520       var ti meout;
  19521  
  19522       var de ferListene r = functi on(ev) {
  19523         if ( !timeout)  {
  19524           ti meout = $b rowser.def er(functio n() {
  19525              listener(e v);
  19526              timeout =  null;
  19527           }) ;
  19528         }
  19529       };
  19530  
  19531       elemen t.on('keyd own', func tion(event ) {
  19532         var  key = even t.keyCode;
  19533  
  19534         // i gnore
  19535         //     command              modifiers                     a rrows
  19536         if ( key === 91  || (15 <  key && key  < 19) ||  (37 <= key  && key <=  40)) retu rn;
  19537  
  19538         defe rListener( event);
  19539       });
  19540  
  19541       // if  user modif ies input  value usin g context  menu in IE , we need  "paste" an d "cut" ev ents to ca tch it
  19542       if ($s niffer.has Event('pas te')) {
  19543         elem ent.on('pa ste cut',  deferListe ner);
  19544       }
  19545     }
  19546  
  19547     // if us er paste i nto input  using mous e on older  browser
  19548     // or fo rm autocom plete on n ewer brows er, we nee d "change"  event to  catch it
  19549     element. on('change ', listene r);
  19550  
  19551     ctrl.$re nder = fun ction() {
  19552       elemen t.val(ctrl .$isEmpty( ctrl.$view Value) ? ' ' : ctrl.$ viewValue) ;
  19553     };
  19554   }
  19555  
  19556   function w eekParser( isoWeek, e xistingDat e) {
  19557     if (isDa te(isoWeek )) {
  19558       return  isoWeek;
  19559     }
  19560  
  19561     if (isSt ring(isoWe ek)) {
  19562       WEEK_R EGEXP.last Index = 0;
  19563       var pa rts = WEEK _REGEXP.ex ec(isoWeek );
  19564       if (pa rts) {
  19565         var  year = +pa rts[1],
  19566              week = +pa rts[2],
  19567              hours = 0,
  19568              minutes =  0,
  19569              seconds =  0,
  19570              millisecon ds = 0,
  19571              firstThurs  = getFirs tThursdayO fYear(year ),
  19572              addDays =  (week - 1)  * 7;
  19573  
  19574         if ( existingDa te) {
  19575           ho urs = exis tingDate.g etHours();
  19576           mi nutes = ex istingDate .getMinute s();
  19577           se conds = ex istingDate .getSecond s();
  19578           mi lliseconds  = existin gDate.getM illisecond s();
  19579         }
  19580  
  19581         retu rn new Dat e(year, 0,  firstThur s.getDate( ) + addDay s, hours,  minutes, s econds, mi lliseconds );
  19582       }
  19583     }
  19584  
  19585     return N aN;
  19586   }
  19587  
  19588   function c reateDateP arser(rege xp, mappin g) {
  19589     return f unction(is o, date) {
  19590       var pa rts, map;
  19591  
  19592       if (is Date(iso))  {
  19593         retu rn iso;
  19594       }
  19595  
  19596       if (is String(iso )) {
  19597         // W hen a date  is JSON'i fied to wr aps itself  inside of  an extra
  19598         // s et of doub le quotes.  This make s the date  parsing c ode unable
  19599         // t o match th e date str ing and pa rse it as  a date.
  19600         if ( iso.charAt (0) == '"'  && iso.ch arAt(iso.l ength - 1)  == '"') {
  19601           is o = iso.su bstring(1,  iso.lengt h - 1);
  19602         }
  19603         if ( ISO_DATE_R EGEXP.test (iso)) {
  19604           re turn new D ate(iso);
  19605         }
  19606         rege xp.lastInd ex = 0;
  19607         part s = regexp .exec(iso) ;
  19608  
  19609         if ( parts) {
  19610           pa rts.shift( );
  19611           if  (date) {
  19612              map = {
  19613                yyyy: da te.getFull Year(),
  19614                MM: date .getMonth( ) + 1,
  19615                dd: date .getDate() ,
  19616                HH: date .getHours( ),
  19617                mm: date .getMinute s(),
  19618                ss: date .getSecond s(),
  19619                sss: dat e.getMilli seconds()  / 1000
  19620              };
  19621           }  else {
  19622              map = { yy yy: 1970,  MM: 1, dd:  1, HH: 0,  mm: 0, ss : 0, sss:  0 };
  19623           }
  19624  
  19625           fo rEach(part s, functio n(part, in dex) {
  19626              if (index  < mapping. length) {
  19627                map[mapp ing[index] ] = +part;
  19628              }
  19629           }) ;
  19630           re turn new D ate(map.yy yy, map.MM  - 1, map. dd, map.HH , map.mm,  map.ss ||  0, map.sss  * 1000 ||  0);
  19631         }
  19632       }
  19633  
  19634       return  NaN;
  19635     };
  19636   }
  19637  
  19638   function c reateDateI nputType(t ype, regex p, parseDa te, format ) {
  19639     return f unction dy namicDateI nputType(s cope, elem ent, attr,  ctrl, $sn iffer, $br owser, $fi lter) {
  19640       badInp utChecker( scope, ele ment, attr , ctrl);
  19641       baseIn putType(sc ope, eleme nt, attr,  ctrl, $sni ffer, $bro wser);
  19642       var ti mezone = c trl && ctr l.$options  && ctrl.$ options.ti mezone;
  19643       var pr eviousDate ;
  19644  
  19645       ctrl.$ $parserNam e = type;
  19646       ctrl.$ parsers.pu sh(functio n(value) {
  19647         if ( ctrl.$isEm pty(value) ) return n ull;
  19648         if ( regexp.tes t(value))  {
  19649           //  Note: We  cannot rea d ctrl.$mo delValue,  as there m ight be a  different
  19650           //  parser/fo rmatter in  the proce ssing chai n so that  the model
  19651           //  contains  some diffe rent data  format!
  19652           va r parsedDa te = parse Date(value , previous Date);
  19653           if  (timezone  === 'UTC' ) {
  19654              parsedDate .setMinute s(parsedDa te.getMinu tes() - pa rsedDate.g etTimezone Offset());
  19655           }
  19656           re turn parse dDate;
  19657         }
  19658         retu rn undefin ed;
  19659       });
  19660  
  19661       ctrl.$ formatters .push(func tion(value ) {
  19662         if ( value && ! isDate(val ue)) {
  19663           th row $ngMod elMinErr(' datefmt',  'Expected  `{0}` to b e a date',  value);
  19664         }
  19665         if ( isValidDat e(value))  {
  19666           pr eviousDate  = value;
  19667           if  (previous Date && ti mezone ===  'UTC') {
  19668              var timezo neOffset =  60000 * p reviousDat e.getTimez oneOffset( );
  19669              previousDa te = new D ate(previo usDate.get Time() + t imezoneOff set);
  19670           }
  19671           re turn $filt er('date') (value, fo rmat, time zone);
  19672         } el se {
  19673           pr eviousDate  = null;
  19674           re turn '';
  19675         }
  19676       });
  19677  
  19678       if (is Defined(at tr.min) ||  attr.ngMi n) {
  19679         var  minVal;
  19680         ctrl .$validato rs.min = f unction(va lue) {
  19681           re turn !isVa lidDate(va lue) || is Undefined( minVal) ||  parseDate (value) >=  minVal;
  19682         };
  19683         attr .$observe( 'min', fun ction(val)  {
  19684           mi nVal = par seObserved DateValue( val);
  19685           ct rl.$valida te();
  19686         });
  19687       }
  19688  
  19689       if (is Defined(at tr.max) ||  attr.ngMa x) {
  19690         var  maxVal;
  19691         ctrl .$validato rs.max = f unction(va lue) {
  19692           re turn !isVa lidDate(va lue) || is Undefined( maxVal) ||  parseDate (value) <=  maxVal;
  19693         };
  19694         attr .$observe( 'max', fun ction(val)  {
  19695           ma xVal = par seObserved DateValue( val);
  19696           ct rl.$valida te();
  19697         });
  19698       }
  19699  
  19700       functi on isValid Date(value ) {
  19701         // I nvalid Dat e: getTime () returns  NaN
  19702         retu rn value & & !(value. getTime &&  value.get Time() !==  value.get Time());
  19703       }
  19704  
  19705       functi on parseOb servedDate Value(val)  {
  19706         retu rn isDefin ed(val) ?  (isDate(va l) ? val :  parseDate (val)) : u ndefined;
  19707       }
  19708     };
  19709   }
  19710  
  19711   function b adInputChe cker(scope , element,  attr, ctr l) {
  19712     var node  = element [0];
  19713     var nati veValidati on = ctrl. $$hasNativ eValidator s = isObje ct(node.va lidity);
  19714     if (nati veValidati on) {
  19715       ctrl.$ parsers.pu sh(functio n(value) {
  19716         var  validity =  element.p rop(VALIDI TY_STATE_P ROPERTY) | | {};
  19717         // D etect bug  in FF35 fo r input[em ail] (http s://bugzil la.mozilla .org/show_ bug.cgi?id =1064430):
  19718         // -  also sets  validity. badInput ( should onl y be valid ity.typeMi smatch).
  19719         // -  see http: //www.what wg.org/spe cs/web-app s/current- work/multi page/forms .html#e-ma il-state-( type=email )
  19720         // -  can ignor e this cas e as we ca n still re ad out the  erroneous  email...
  19721         retu rn validit y.badInput  && !valid ity.typeMi smatch ? u ndefined :  value;
  19722       });
  19723     }
  19724   }
  19725  
  19726   function n umberInput Type(scope , element,  attr, ctr l, $sniffe r, $browse r) {
  19727     badInput Checker(sc ope, eleme nt, attr,  ctrl);
  19728     baseInpu tType(scop e, element , attr, ct rl, $sniff er, $brows er);
  19729  
  19730     ctrl.$$p arserName  = 'number' ;
  19731     ctrl.$pa rsers.push (function( value) {
  19732       if (ct rl.$isEmpt y(value))       retur n null;
  19733       if (NU MBER_REGEX P.test(val ue)) retur n parseFlo at(value);
  19734       return  undefined ;
  19735     });
  19736  
  19737     ctrl.$fo rmatters.p ush(functi on(value)  {
  19738       if (!c trl.$isEmp ty(value))  {
  19739         if ( !isNumber( value)) {
  19740           th row $ngMod elMinErr(' numfmt', ' Expected ` {0}` to be  a number' , value);
  19741         }
  19742         valu e = value. toString() ;
  19743       }
  19744       return  value;
  19745     });
  19746  
  19747     if (attr .min || at tr.ngMin)  {
  19748       var mi nVal;
  19749       ctrl.$ validators .min = fun ction(valu e) {
  19750         retu rn ctrl.$i sEmpty(val ue) || isU ndefined(m inVal) ||  value >= m inVal;
  19751       };
  19752  
  19753       attr.$ observe('m in', funct ion(val) {
  19754         if ( isDefined( val) && !i sNumber(va l)) {
  19755           va l = parseF loat(val,  10);
  19756         }
  19757         minV al = isNum ber(val) & & !isNaN(v al) ? val  : undefine d;
  19758         // T ODO(matsko ): impleme nt validat eLater to  reduce num ber of val idations
  19759         ctrl .$validate ();
  19760       });
  19761     }
  19762  
  19763     if (attr .max || at tr.ngMax)  {
  19764       var ma xVal;
  19765       ctrl.$ validators .max = fun ction(valu e) {
  19766         retu rn ctrl.$i sEmpty(val ue) || isU ndefined(m axVal) ||  value <= m axVal;
  19767       };
  19768  
  19769       attr.$ observe('m ax', funct ion(val) {
  19770         if ( isDefined( val) && !i sNumber(va l)) {
  19771           va l = parseF loat(val,  10);
  19772         }
  19773         maxV al = isNum ber(val) & & !isNaN(v al) ? val  : undefine d;
  19774         // T ODO(matsko ): impleme nt validat eLater to  reduce num ber of val idations
  19775         ctrl .$validate ();
  19776       });
  19777     }
  19778   }
  19779  
  19780   function u rlInputTyp e(scope, e lement, at tr, ctrl,  $sniffer,  $browser)  {
  19781     // Note:  no badInp utChecker  here by pu rpose as ` url` is on ly a valid ation
  19782     // in br owsers, i. e. we can  always rea d out inpu t.value ev en if it i s not vali d!
  19783     baseInpu tType(scop e, element , attr, ct rl, $sniff er, $brows er);
  19784     stringBa sedInputTy pe(ctrl);
  19785  
  19786     ctrl.$$p arserName  = 'url';
  19787     ctrl.$va lidators.u rl = funct ion(modelV alue, view Value) {
  19788       var va lue = mode lValue ||  viewValue;
  19789       return  ctrl.$isE mpty(value ) || URL_R EGEXP.test (value);
  19790     };
  19791   }
  19792  
  19793   function e mailInputT ype(scope,  element,  attr, ctrl , $sniffer , $browser ) {
  19794     // Note:  no badInp utChecker  here by pu rpose as ` url` is on ly a valid ation
  19795     // in br owsers, i. e. we can  always rea d out inpu t.value ev en if it i s not vali d!
  19796     baseInpu tType(scop e, element , attr, ct rl, $sniff er, $brows er);
  19797     stringBa sedInputTy pe(ctrl);
  19798  
  19799     ctrl.$$p arserName  = 'email';
  19800     ctrl.$va lidators.e mail = fun ction(mode lValue, vi ewValue) {
  19801       var va lue = mode lValue ||  viewValue;
  19802       return  ctrl.$isE mpty(value ) || EMAIL _REGEXP.te st(value);
  19803     };
  19804   }
  19805  
  19806   function r adioInputT ype(scope,  element,  attr, ctrl ) {
  19807     // make  the name u nique, if  not define d
  19808     if (isUn defined(at tr.name))  {
  19809       elemen t.attr('na me', nextU id());
  19810     }
  19811  
  19812     var list ener = fun ction(ev)  {
  19813       if (el ement[0].c hecked) {
  19814         ctrl .$setViewV alue(attr. value, ev  && ev.type );
  19815       }
  19816     };
  19817  
  19818     element. on('click' , listener );
  19819  
  19820     ctrl.$re nder = fun ction() {
  19821       var va lue = attr .value;
  19822       elemen t[0].check ed = (valu e == ctrl. $viewValue );
  19823     };
  19824  
  19825     attr.$ob serve('val ue', ctrl. $render);
  19826   }
  19827  
  19828   function p arseConsta ntExpr($pa rse, conte xt, name,  expression , fallback ) {
  19829     var pars eFn;
  19830     if (isDe fined(expr ession)) {
  19831       parseF n = $parse (expressio n);
  19832       if (!p arseFn.con stant) {
  19833         thro w minErr(' ngModel')( 'constexpr ', 'Expect ed constan t expressi on for `{0 }`, but sa w ' +
  19834                                         '`{1} `.', name,  expressio n);
  19835       }
  19836       return  parseFn(c ontext);
  19837     }
  19838     return f allback;
  19839   }
  19840  
  19841   function c heckboxInp utType(sco pe, elemen t, attr, c trl, $snif fer, $brow ser, $filt er, $parse ) {
  19842     var true Value = pa rseConstan tExpr($par se, scope,  'ngTrueVa lue', attr .ngTrueVal ue, true);
  19843     var fals eValue = p arseConsta ntExpr($pa rse, scope , 'ngFalse Value', at tr.ngFalse Value, fal se);
  19844  
  19845     var list ener = fun ction(ev)  {
  19846       ctrl.$ setViewVal ue(element [0].checke d, ev && e v.type);
  19847     };
  19848  
  19849     element. on('click' , listener );
  19850  
  19851     ctrl.$re nder = fun ction() {
  19852       elemen t[0].check ed = ctrl. $viewValue ;
  19853     };
  19854  
  19855     // Overr ide the st andard `$i sEmpty` be cause the  $viewValue  of an emp ty checkbo x is alway s set to ` false`
  19856     // This  is because  of the pa rser below , which co mpares the  `$modelVa lue` with  `trueValue ` to conve rt
  19857     // it to  a boolean .
  19858     ctrl.$is Empty = fu nction(val ue) {
  19859       return  value ===  false;
  19860     };
  19861  
  19862     ctrl.$fo rmatters.p ush(functi on(value)  {
  19863       return  equals(va lue, trueV alue);
  19864     });
  19865  
  19866     ctrl.$pa rsers.push (function( value) {
  19867       return  value ? t rueValue :  falseValu e;
  19868     });
  19869   }
  19870  
  19871  
  19872   /**
  19873    * @ngdoc  directive
  19874    * @name t extarea
  19875    * @restri ct E
  19876    *
  19877    * @descri ption
  19878    * HTML te xtarea ele ment contr ol with an gular data -binding.  The data-b inding and  validatio n
  19879    * propert ies of thi s element  are exactl y the same  as those  of the
  19880    * {@link  ng.directi ve:input i nput eleme nt}.
  19881    *
  19882    * @param  {string} n gModel Ass ignable an gular expr ession to  data-bind  to.
  19883    * @param  {string=}  name Prope rty name o f the form  under whi ch the con trol is pu blished.
  19884    * @param  {string=}  required S ets `requi red` valid ation erro r key if t he value i s not ente red.
  19885    * @param  {string=}  ngRequired  Adds `req uired` att ribute and  `required ` validati on constra int to
  19886    *    the  element wh en the ngR equired ex pression e valuates t o true. Us e `ngRequi red` inste ad of
  19887    *    `req uired` whe n you want  to data-b ind to the  `required ` attribut e.
  19888    * @param  {number=}  ngMinlengt h Sets `mi nlength` v alidation  error key  if the val ue is shor ter than
  19889    *    minl ength.
  19890    * @param  {number=}  ngMaxlengt h Sets `ma xlength` v alidation  error key  if the val ue is long er than
  19891    *    maxl ength. Set ting the a ttribute t o a negati ve or non- numeric va lue, allow s view val ues of any
  19892    *    leng th.
  19893    * @param  {string=}  ngPattern  Sets `patt ern` valid ation erro r key if t he value d oes not ma tch the
  19894    *    RegE xp pattern  expressio n. Expecte d value is  `/regexp/ ` for inli ne pattern s or `rege xp` for
  19895    *    patt erns defin ed as scop e expressi ons.
  19896    * @param  {string=}  ngChange A ngular exp ression to  be execut ed when in put change s due to u ser
  19897    *    inte raction wi th the inp ut element .
  19898    * @param  {boolean=}  [ngTrim=t rue] If se t to false  Angular w ill not au tomaticall y trim the  input.
  19899    */
  19900  
  19901  
  19902   /**
  19903    * @ngdoc  directive
  19904    * @name i nput
  19905    * @restri ct E
  19906    *
  19907    * @descri ption
  19908    * HTML in put elemen t control.  When used  together  with {@lin k ngModel  `ngModel`} , it provi des data-b inding,
  19909    * input s tate contr ol, and va lidation.
  19910    * Input c ontrol fol lows HTML5  input typ es and pol yfills the  HTML5 val idation be havior for  older bro wsers.
  19911    *
  19912    * <div cl ass="alert  alert-war ning">
  19913    * **Note: ** Not eve ry feature  offered i s availabl e for all  input type s.
  19914    * Specifi cally, dat a binding  and event  handling v ia `ng-mod el` is uns upported f or `input[ file]`.
  19915    * </div>
  19916    *
  19917    * @param  {string} n gModel Ass ignable an gular expr ession to  data-bind  to.
  19918    * @param  {string=}  name Prope rty name o f the form  under whi ch the con trol is pu blished.
  19919    * @param  {string=}  required S ets `requi red` valid ation erro r key if t he value i s not ente red.
  19920    * @param  {boolean=}  ngRequire d Sets `re quired` at tribute if  set to tr ue
  19921    * @param  {number=}  ngMinlengt h Sets `mi nlength` v alidation  error key  if the val ue is shor ter than
  19922    *    minl ength.
  19923    * @param  {number=}  ngMaxlengt h Sets `ma xlength` v alidation  error key  if the val ue is long er than
  19924    *    maxl ength. Set ting the a ttribute t o a negati ve or non- numeric va lue, allow s view val ues of any
  19925    *    leng th.
  19926    * @param  {string=}  ngPattern  Sets `patt ern` valid ation erro r key if t he value d oes not ma tch the
  19927    *    RegE xp pattern  expressio n. Expecte d value is  `/regexp/ ` for inli ne pattern s or `rege xp` for
  19928    *    patt erns defin ed as scop e expressi ons.
  19929    * @param  {string=}  ngChange A ngular exp ression to  be execut ed when in put change s due to u ser
  19930    *    inte raction wi th the inp ut element .
  19931    * @param  {boolean=}  [ngTrim=t rue] If se t to false  Angular w ill not au tomaticall y trim the  input.
  19932    *    This  parameter  is ignore d for inpu t[type=pas sword] con trols, whi ch will ne ver trim t he
  19933    *    inpu t.
  19934    *
  19935    * @exampl e
  19936       <examp le name="i nput-direc tive" modu le="inputE xample">
  19937         <fil e name="in dex.html">
  19938          <sc ript>
  19939              angular.mo dule('inpu tExample',  [])
  19940                .control ler('Examp leControll er', ['$sc ope', func tion($scop e) {
  19941                  $scope .user = {n ame: 'gues t', last:  'visitor'} ;
  19942                }]);
  19943          </s cript>
  19944          <di v ng-contr oller="Exa mpleContro ller">
  19945            < form name= "myForm">
  19946               User name : <input t ype="text"  name="use rName" ng- model="use r.name" re quired>
  19947               <span cla ss="error"  ng-show=" myForm.use rName.$err or.require d">
  19948                 Require d!</span>< br>
  19949               Last name : <input t ype="text"  name="las tName" ng- model="use r.last"
  19950                 ng-minl ength="3"  ng-maxleng th="10">
  19951               <span cla ss="error"  ng-show=" myForm.las tName.$err or.minleng th">
  19952                 Too sho rt!</span>
  19953               <span cla ss="error"  ng-show=" myForm.las tName.$err or.maxleng th">
  19954                 Too lon g!</span>< br>
  19955            < /form>
  19956            < hr>
  19957            < tt>user =  {{user}}</ tt><br/>
  19958            < tt>myForm. userName.$ valid = {{ myForm.use rName.$val id}}</tt>< br>
  19959            < tt>myForm. userName.$ error = {{ myForm.use rName.$err or}}</tt>< br>
  19960            < tt>myForm. lastName.$ valid = {{ myForm.las tName.$val id}}</tt>< br>
  19961            < tt>myForm. lastName.$ error = {{ myForm.las tName.$err or}}</tt>< br>
  19962            < tt>myForm. $valid = { {myForm.$v alid}}</tt ><br>
  19963            < tt>myForm. $error.req uired = {{ !!myForm.$ error.requ ired}}</tt ><br>
  19964            < tt>myForm. $error.min length = { {!!myForm. $error.min length}}</ tt><br>
  19965            < tt>myForm. $error.max length = { {!!myForm. $error.max length}}</ tt><br>
  19966          </d iv>
  19967         </fi le>
  19968         <fil e name="pr otractor.j s" type="p rotractor" >
  19969           va r user = e lement(by. exactBindi ng('user') );
  19970           va r userName Valid = el ement(by.b inding('my Form.userN ame.$valid '));
  19971           va r lastName Valid = el ement(by.b inding('my Form.lastN ame.$valid '));
  19972           va r lastName Error = el ement(by.b inding('my Form.lastN ame.$error '));
  19973           va r formVali d = elemen t(by.bindi ng('myForm .$valid')) ;
  19974           va r userName Input = el ement(by.m odel('user .name'));
  19975           va r userLast Input = el ement(by.m odel('user .last'));
  19976  
  19977           it ('should i nitialize  to model',  function( ) {
  19978              expect(use r.getText( )).toConta in('{"name ":"guest", "last":"vi sitor"}');
  19979              expect(use rNameValid .getText() ).toContai n('true');
  19980              expect(for mValid.get Text()).to Contain('t rue');
  19981           }) ;
  19982  
  19983           it ('should b e invalid  if empty w hen requir ed', funct ion() {
  19984              userNameIn put.clear( );
  19985              userNameIn put.sendKe ys('');
  19986  
  19987              expect(use r.getText( )).toConta in('{"last ":"visitor "}');
  19988              expect(use rNameValid .getText() ).toContai n('false') ;
  19989              expect(for mValid.get Text()).to Contain('f alse');
  19990           }) ;
  19991  
  19992           it ('should b e valid if  empty whe n min leng th is set' , function () {
  19993              userLastIn put.clear( );
  19994              userLastIn put.sendKe ys('');
  19995  
  19996              expect(use r.getText( )).toConta in('{"name ":"guest", "last":""} ');
  19997              expect(las tNameValid .getText() ).toContai n('true');
  19998              expect(for mValid.get Text()).to Contain('t rue');
  19999           }) ;
  20000  
  20001           it ('should b e invalid  if less th an require d min leng th', funct ion() {
  20002              userLastIn put.clear( );
  20003              userLastIn put.sendKe ys('xx');
  20004  
  20005              expect(use r.getText( )).toConta in('{"name ":"guest"} ');
  20006              expect(las tNameValid .getText() ).toContai n('false') ;
  20007              expect(las tNameError .getText() ).toContai n('minleng th');
  20008              expect(for mValid.get Text()).to Contain('f alse');
  20009           }) ;
  20010  
  20011           it ('should b e invalid  if longer  than max l ength', fu nction() {
  20012              userLastIn put.clear( );
  20013              userLastIn put.sendKe ys('some r idiculousl y long nam e');
  20014  
  20015              expect(use r.getText( )).toConta in('{"name ":"guest"} ');
  20016              expect(las tNameValid .getText() ).toContai n('false') ;
  20017              expect(las tNameError .getText() ).toContai n('maxleng th');
  20018              expect(for mValid.get Text()).to Contain('f alse');
  20019           }) ;
  20020         </fi le>
  20021       </exam ple>
  20022    */
  20023   var inputD irective =  ['$browse r', '$snif fer', '$fi lter', '$p arse',
  20024       functi on($browse r, $sniffe r, $filter , $parse)  {
  20025     return {
  20026       restri ct: 'E',
  20027       requir e: ['?ngMo del'],
  20028       link:  {
  20029         pre:  function( scope, ele ment, attr , ctrls) {
  20030           if  (ctrls[0] ) {
  20031              (inputType [lowercase (attr.type )] || inpu tType.text )(scope, e lement, at tr, ctrls[ 0], $sniff er,
  20032                                                                       $browser , $filter,  $parse);
  20033           }
  20034         }
  20035       }
  20036     };
  20037   }];
  20038  
  20039   var VALID_ CLASS = 'n g-valid',
  20040       INVALI D_CLASS =  'ng-invali d',
  20041       PRISTI NE_CLASS =  'ng-prist ine',
  20042       DIRTY_ CLASS = 'n g-dirty',
  20043       UNTOUC HED_CLASS  = 'ng-unto uched',
  20044       TOUCHE D_CLASS =  'ng-touche d',
  20045       PENDIN G_CLASS =  'ng-pendin g';
  20046  
  20047   /**
  20048    * @ngdoc  type
  20049    * @name n gModel.NgM odelContro ller
  20050    *
  20051    * @proper ty {string } $viewVal ue Actual  string val ue in the  view.
  20052    * @proper ty {*} $mo delValue T he value i n the mode l that the  control i s bound to .
  20053    * @proper ty {Array. <Function> } $parsers  Array of  functions  to execute , as a pip eline, whe never
  20054          the  control r eads value  from the  DOM. The f unctions a re called  in array o rder, each  passing
  20055          its  return va lue throug h to the n ext. The l ast return  value is  forwarded  to the
  20056          {@l ink ngMode l.NgModelC ontroller# $validator s `$valida tors`} col lection.
  20057  
  20058   Parsers ar e used to  sanitize /  convert t he {@link  ngModel.Ng ModelContr oller#$vie wValue
  20059   `$viewValu e`}.
  20060  
  20061   Returning  `undefined ` from a p arser mean s a parse  error occu rred. In t hat case,
  20062   no {@link  ngModel.Ng ModelContr oller#$val idators `$ validators `} will ru n and the  `ngModel`
  20063   will be se t to `unde fined` unl ess {@link  ngModelOp tions `ngM odelOption s.allowInv alid`}
  20064   is set to  `true`. Th e parse er ror is sto red in `ng Model.$err or.parse`.
  20065  
  20066    *
  20067    * @proper ty {Array. <Function> } $formatt ers Array  of functio ns to exec ute, as a  pipeline,  whenever
  20068          the  model val ue changes . The func tions are  called in  reverse ar ray order,  each pass ing the va lue throug h to the
  20069          nex t. The las t return v alue is us ed as the  actual DOM  value.
  20070          Use d to forma t / conver t values f or display  in the co ntrol.
  20071    * ```js
  20072    * functio n formatte r(value) {
  20073    *   if (v alue) {
  20074    *     ret urn value. toUpperCas e();
  20075    *   }
  20076    * }
  20077    * ngModel .$formatte rs.push(fo rmatter);
  20078    * ```
  20079    *
  20080    * @proper ty {Object .<string,  function>}  $validato rs A colle ction of v alidators  that are a pplied
  20081    *      wh enever the  model val ue changes . The key  value with in the obj ect refers  to the na me of the
  20082    *      va lidator wh ile the fu nction ref ers to the  validatio n operatio n. The val idation op eration is
  20083    *      pr ovided wit h the mode l value as  an argume nt and mus t return a  true or f alse value  depending
  20084    *      on  the respo nse of tha t validati on.
  20085    *
  20086    * ```js
  20087    * ngModel .$validato rs.validCh aracters =  function( modelValue , viewValu e) {
  20088    *   var v alue = mod elValue ||  viewValue ;
  20089    *   retur n /[0-9]+/ .test(valu e) &&
  20090    *           /[a-z]+/ .test(valu e) &&
  20091    *           /[A-Z]+/ .test(valu e) &&
  20092    *           /\W+/.te st(value);
  20093    * };
  20094    * ```
  20095    *
  20096    * @proper ty {Object .<string,  function>}  $asyncVal idators A  collection  of valida tions that  are expec ted to
  20097    *      pe rform an a synchronou s validati on (e.g. a  HTTP requ est). The  validation  function  that is pr ovided
  20098    *      is  expected  to return  a promise  when it is  run durin g the mode l validati on process . Once the  promise
  20099    *      is  delivered  then the  validation  status wi ll be set  to true wh en fulfill ed and fal se when re jected.
  20100    *      Wh en the asy nchronous  validators  are trigg ered, each  of the va lidators w ill run in  parallel  and the mo del
  20101    *      va lue will o nly be upd ated once  all valida tors have  been fulfi lled. As l ong as an  asynchrono us validat or
  20102    *      is  unfulfill ed, its ke y will be  added to t he control lers `$pen ding` prop erty. Also , all asyn chronous v alidators
  20103    *      wi ll only ru n once all  synchrono us validat ors have p assed.
  20104    *
  20105    * Please  note that  if $http i s used the n it is im portant th at the ser ver return s a succes s HTTP res ponse code
  20106    * in orde r to fulfi ll the val idation an d a status  level of  `4xx` in o rder to re ject the v alidation.
  20107    *
  20108    * ```js
  20109    * ngModel .$asyncVal idators.un iqueUserna me = funct ion(modelV alue, view Value) {
  20110    *   var v alue = mod elValue ||  viewValue ;
  20111    *
  20112    *   // Lo okup user  by usernam e
  20113    *   retur n $http.ge t('/api/us ers/' + va lue).
  20114    *      th en(functio n resolved () {
  20115    *         //username  exists, t his means  validation  fails
  20116    *         return $q. reject('ex ists');
  20117    *      },  function  rejected()  {
  20118    *         //username  does not  exist, the refore thi s validati on passes
  20119    *         return tru e;
  20120    *      }) ;
  20121    * };
  20122    * ```
  20123    *
  20124    * @proper ty {Array. <Function> } $viewCha ngeListene rs Array o f function s to execu te wheneve r the
  20125    *     vie w value ha s changed.  It is cal led with n o argument s, and its  return va lue is ign ored.
  20126    *     Thi s can be u sed in pla ce of addi tional $wa tches agai nst the mo del value.
  20127    *
  20128    * @proper ty {Object } $error A n object h ash with a ll failing  validator  ids as ke ys.
  20129    * @proper ty {Object } $pending  An object  hash with  all pendi ng validat or ids as  keys.
  20130    *
  20131    * @proper ty {boolea n} $untouc hed True i f control  has not lo st focus y et.
  20132    * @proper ty {boolea n} $touche d True if  control ha s lost foc us.
  20133    * @proper ty {boolea n} $pristi ne True if  user has  not intera cted with  the contro l yet.
  20134    * @proper ty {boolea n} $dirty  True if us er has alr eady inter acted with  the contr ol.
  20135    * @proper ty {boolea n} $valid  True if th ere is no  error.
  20136    * @proper ty {boolea n} $invali d True if  at least o ne error o n the cont rol.
  20137    * @proper ty {string } $name Th e name att ribute of  the contro l.
  20138    *
  20139    * @descri ption
  20140    *
  20141    * `NgMode lControlle r` provide s API for  the {@link  ngModel ` ngModel`}  directive.
  20142    * The con troller co ntains ser vices for  data-bindi ng, valida tion, CSS  updates, a nd value f ormatting
  20143    * and par sing. It p urposefull y does not  contain a ny logic w hich deals  with DOM  rendering  or
  20144    * listeni ng to DOM  events.
  20145    * Such DO M related  logic shou ld be prov ided by ot her direct ives which  make use  of
  20146    * `NgMode lControlle r` for dat a-binding  to control  elements.
  20147    * Angular  provides  this DOM l ogic for m ost {@link  input `in put`} elem ents.
  20148    * At the  end of thi s page you  can find  a {@link n gModel.NgM odelContro ller#custo m-control- example
  20149    * custom  control ex ample} tha t uses `ng ModelContr oller` to  bind to `c ontentedit able` elem ents.
  20150    *
  20151    * @exampl e
  20152    * ### Cus tom Contro l Example
  20153    * This ex ample show s how to u se `NgMode lControlle r` with a  custom con trol to ac hieve
  20154    * data-bi nding. Not ice how di fferent di rectives ( `contented itable`, ` ng-model`,  and `requ ired`)
  20155    * collabo rate toget her to ach ieve the d esired res ult.
  20156    *
  20157    * Note th at `conten teditable`  is an HTM L5 attribu te, which  tells the  browser to  let the e lement
  20158    * content s be edite d in place  by the us er.  This  will not w ork on old er browser s.
  20159    *
  20160    * We are  using the  {@link ng. service:$s ce $sce} s ervice her e and incl ude the {@ link ngSan itize $san itize}
  20161    * module  to automat ically rem ove "bad"  content li ke inline  event list ener (e.g.  `<span on click="... ">`).
  20162    * However , as we ar e using `$ sce` the m odel can s till decid e to provi de unsafe  content if  it marks
  20163    * that co ntent usin g the `$sc e` service .
  20164    *
  20165    * <exampl e name="Ng ModelContr oller" mod ule="custo mControl"  deps="angu lar-saniti ze.js">
  20166       <file  name="styl e.css">
  20167         [con tenteditab le] {
  20168           bo rder: 1px  solid blac k;
  20169           ba ckground-c olor: whit e;
  20170           mi n-height:  20px;
  20171         }
  20172  
  20173         .ng- invalid {
  20174           bo rder: 1px  solid red;
  20175         }
  20176  
  20177       </file >
  20178       <file  name="scri pt.js">
  20179         angu lar.module ('customCo ntrol', [' ngSanitize ']).
  20180           di rective('c ontentedit able', ['$ sce', func tion($sce)  {
  20181              return {
  20182                restrict : 'A', //  only activ ate on ele ment attri bute
  20183                require:  '?ngModel ', // get  a hold of  NgModelCon troller
  20184                link: fu nction(sco pe, elemen t, attrs,  ngModel) {
  20185                  if (!n gModel) re turn; // d o nothing  if no ng-m odel
  20186  
  20187                  // Spe cify how U I should b e updated
  20188                  ngMode l.$render  = function () {
  20189                    elem ent.html($ sce.getTru stedHtml(n gModel.$vi ewValue ||  ''));
  20190                  };
  20191  
  20192                  // Lis ten for ch ange event s to enabl e binding
  20193                  elemen t.on('blur  keyup cha nge', func tion() {
  20194                      scope.$e DNS    ync(read);
  20195                  });
  20196                  read() ; // initi alize
  20197  
  20198                  // Wri te data to  the model
  20199                  functi on read()  {
  20200                    var  html = ele ment.html( );
  20201                    // W hen we cle ar the con tent edita ble the br owser leav es a <br>  behind
  20202                    // I f strip-br  attribute  is provid ed then we  strip thi s out
  20203                    if (  attrs.str ipBr && ht ml == '<br >' ) {
  20204                      ht ml = '';
  20205                    }
  20206                    ngMo del.$setVi ewValue(ht ml);
  20207                  }
  20208                }
  20209              };
  20210           }] );
  20211       </file >
  20212       <file  name="inde x.html">
  20213         <for m name="my Form">
  20214          <di v contente ditable
  20215                name="my Widget" ng -model="us erContent"
  20216                strip-br ="true"
  20217                required >Change me !</div>
  20218           <s pan ng-sho w="myForm. myWidget.$ error.requ ired">Requ ired!</spa n>
  20219          <hr >
  20220          <te xtarea ng- model="use rContent"> </textarea >
  20221         </fo rm>
  20222       </file >
  20223       <file  name="prot ractor.js"  type="pro tractor">
  20224       it('sh ould data- bind and b ecome inva lid', func tion() {
  20225         if ( browser.pa rams.brows er == 'saf ari' || br owser.para ms.browser  == 'firef ox') {
  20226           //  SafariDri ver can't  handle con tenteditab le
  20227           //  and Firef ox driver  can't clea r contente ditables v ery well
  20228           re turn;
  20229         }
  20230         var  contentEdi table = el ement(by.c ss('[conte nteditable ]'));
  20231         var  content =  'Change me !';
  20232  
  20233         expe ct(content Editable.g etText()). toEqual(co ntent);
  20234  
  20235         cont entEditabl e.clear();
  20236         cont entEditabl e.sendKeys (protracto r.Key.BACK _SPACE);
  20237         expe ct(content Editable.g etText()). toEqual('' );
  20238         expe ct(content Editable.g etAttribut e('class') ).toMatch( /ng-invali d-required /);
  20239       });
  20240       </file >
  20241    * </examp le>
  20242    *
  20243    *
  20244    */
  20245   var NgMode lControlle r = ['$sco pe', '$exc eptionHand ler', '$at trs', '$el ement', '$ parse', '$ animate',  '$timeout' , '$rootSc ope', '$q' , '$interp olate',
  20246       functi on($scope,  $exceptio nHandler,  $attr, $el ement, $pa rse, $anim ate, $time out, $root Scope, $q,  $interpol ate) {
  20247     this.$vi ewValue =  Number.NaN ;
  20248     this.$mo delValue =  Number.Na N;
  20249     this.$$r awModelVal ue = undef ined; // s tores the  parsed mod elValue /  model set  from scope  regardles s of valid ity.
  20250     this.$va lidators =  {};
  20251     this.$as yncValidat ors = {};
  20252     this.$pa rsers = [] ;
  20253     this.$fo rmatters =  [];
  20254     this.$vi ewChangeLi steners =  [];
  20255     this.$un touched =  true;
  20256     this.$to uched = fa lse;
  20257     this.$pr istine = t rue;
  20258     this.$di rty = fals e;
  20259     this.$va lid = true ;
  20260     this.$in valid = fa lse;
  20261     this.$er ror = {};  // keep in valid keys  here
  20262     this.$$s uccess = { }; // keep  valid key s here
  20263     this.$pe nding = un defined; / / keep pen ding keys  here
  20264     this.$na me = $inte rpolate($a ttr.name | | '', fals e)($scope) ;
  20265  
  20266  
  20267     var pars edNgModel  = $parse($ attr.ngMod el),
  20268         pars edNgModelA ssign = pa rsedNgMode l.assign,
  20269         ngMo delGet = p arsedNgMod el,
  20270         ngMo delSet = p arsedNgMod elAssign,
  20271         pend ingDebounc e = null,
  20272         ctrl  = this;
  20273  
  20274     this.$$s etOptions  = function (options)  {
  20275       ctrl.$ options =  options;
  20276       if (op tions && o ptions.get terSetter)  {
  20277         var  invokeMode lGetter =  $parse($at tr.ngModel  + '()'),
  20278              invokeMode lSetter =  $parse($at tr.ngModel  + '($$$p) ');
  20279  
  20280         ngMo delGet = f unction($s cope) {
  20281           va r modelVal ue = parse dNgModel($ scope);
  20282           if  (isFuncti on(modelVa lue)) {
  20283              modelValue  = invokeM odelGetter ($scope);
  20284           }
  20285           re turn model Value;
  20286         };
  20287         ngMo delSet = f unction($s cope, newV alue) {
  20288           if  (isFuncti on(parsedN gModel($sc ope))) {
  20289              invokeMode lSetter($s cope, {$$$ p: ctrl.$m odelValue} );
  20290           }  else {
  20291              parsedNgMo delAssign( $scope, ct rl.$modelV alue);
  20292           }
  20293         };
  20294       } else  if (!pars edNgModel. assign) {
  20295         thro w $ngModel MinErr('no nassign',  "Expressio n '{0}' is  non-assig nable. Ele ment: {1}" ,
  20296              $attr.ngMo del, start ingTag($el ement));
  20297       }
  20298     };
  20299  
  20300     /**
  20301      * @ngdo c method
  20302      * @name  ngModel.N gModelCont roller#$re nder
  20303      *
  20304      * @desc ription
  20305      * Calle d when the  view need s to be up dated. It  is expecte d that the  user of t he ng-mode l
  20306      * direc tive will  implement  this metho d.
  20307      *
  20308      * The ` $render()`  method is  invoked i n the foll owing situ ations:
  20309      *
  20310      * * `$r ollbackVie wValue()`  is called.   If we ar e rolling  back the v iew value  to the las t
  20311      *   com mitted val ue then `$ render()`  is called  to update  the input  control.
  20312      * * The  value ref erenced by  `ng-model ` is chang ed program matically  and both t he `$model Value` and
  20313      *   the  `$viewVal ue` are di fferent to  last time .
  20314      *
  20315      * Since  `ng-model ` does not  do a deep  watch, `$ render()`  is only in voked if t he values  of
  20316      * `$mod elValue` a nd `$viewV alue` are  actually d ifferent t o their pr evious val ue. If `$m odelValue`
  20317      * or `$ viewValue`  are objec ts (rather  than a st ring or nu mber) then  `$render( )` will no t be
  20318      * invok ed if you  only chang e a proper ty on the  objects.
  20319      */
  20320     this.$re nder = noo p;
  20321  
  20322     /**
  20323      * @ngdo c method
  20324      * @name  ngModel.N gModelCont roller#$is Empty
  20325      *
  20326      * @desc ription
  20327      * This  is called  when we ne ed to dete rmine if t he value o f an input  is empty.
  20328      *
  20329      * For i nstance, t he require d directiv e does thi s to work  out if the  input has  data or n ot.
  20330      *
  20331      * The d efault `$i sEmpty` fu nction che cks whethe r the valu e is `unde fined`, `' '`, `null`  or `NaN`.
  20332      *
  20333      * You c an overrid e this for  input dir ectives wh ose concep t of being  empty is  different  to the
  20334      * defau lt. The `c heckboxInp utType` di rective do es this be cause in i ts case a  value of ` false`
  20335      * impli es empty.
  20336      *
  20337      * @para m {*} valu e The valu e of the i nput to ch eck for em ptiness.
  20338      * @retu rns {boole an} True i f `value`  is "empty" .
  20339      */
  20340     this.$is Empty = fu nction(val ue) {
  20341       return  isUndefin ed(value)  || value = == '' || v alue === n ull || val ue !== val ue;
  20342     };
  20343  
  20344       var parent Form = $el ement.inhe ritedData( '$f DNS     troller')  || nullFor mCtrl,
  20345         curr entValidat ionRunId =  0;
  20346  
  20347     /**
  20348      * @ngdo c method
  20349      * @name  ngModel.N gModelCont roller#$se tValidity
  20350      *
  20351      * @desc ription
  20352      * Chang e the vali dity state , and noti fy the for m.
  20353      *
  20354      * This  method can  be called  within $p arsers/$fo rmatters o r a custom  validatio n implemen tation.
  20355      * Howev er, in mos t cases it  should be  sufficien t to use t he `ngMode l.$validat ors` and
  20356      * `ngMo del.$async Validators ` collecti ons which  will call  `$setValid ity` autom atically.
  20357      *
  20358      * @para m {string}  validatio nErrorKey  Name of th e validato r. The `va lidationEr rorKey` wi ll be assi gned
  20359      *         to eithe r `$error[ validation ErrorKey]`  or `$pend ing[valida tionErrorK ey]`
  20360      *         (for unf ulfilled ` $asyncVali dators`),  so that it  is availa ble for da ta-binding .
  20361      *         The `val idationErr orKey` sho uld be in  camelCase  and will g et convert ed into da sh-case
  20362      *         for clas s name. Ex ample: `my Error` wil l result i n `ng-vali d-my-error ` and `ng- invalid-my -error`
  20363      *         class an d can be b ound to as   `{{someF orm.someCo ntrol.$err or.myError }}` .
  20364      * @para m {boolean } isValid  Whether th e current  state is v alid (true ), invalid  (false),  pending (u ndefined),
  20365      *                             or skipped  (null). P ending is  used for u nfulfilled  `$asyncVa lidators`.
  20366      *                             Skipped is  used by A ngular whe n validato rs do not  run becaus e of parse  errors an d
  20367      *                             when `$asy ncValidato rs` do not  run becau se any of  the `$vali dators` fa iled.
  20368      */
  20369     addSetVa lidityMeth od({
  20370       ctrl:  this,
  20371       $eleme nt: $eleme nt,
  20372       set: f unction(ob ject, prop erty) {
  20373         obje ct[propert y] = true;
  20374       },
  20375       unset:  function( object, pr operty) {
  20376         dele te object[ property];
  20377       },
  20378       parent Form: pare ntForm,
  20379       $anima te: $anima te
  20380     });
  20381  
  20382     /**
  20383      * @ngdo c method
  20384      * @name  ngModel.N gModelCont roller#$se tPristine
  20385      *
  20386      * @desc ription
  20387      * Sets  the contro l to its p ristine st ate.
  20388      *
  20389      * This  method can  be called  to remove  the `ng-d irty` clas s and set  the contro l to its p ristine
  20390      * state  (`ng-pris tine` clas s). A mode l is consi dered to b e pristine  when the  control
  20391      * has n ot been ch anged from  when firs t compiled .
  20392      */
  20393     this.$se tPristine  = function () {
  20394       ctrl.$ dirty = fa lse;
  20395       ctrl.$ pristine =  true;
  20396       $anima te.removeC lass($elem ent, DIRTY _CLASS);
  20397       $anima te.addClas s($element , PRISTINE _CLASS);
  20398     };
  20399  
  20400     /**
  20401      * @ngdo c method
  20402      * @name  ngModel.N gModelCont roller#$se tDirty
  20403      *
  20404      * @desc ription
  20405      * Sets  the contro l to its d irty state .
  20406      *
  20407      * This  method can  be called  to remove  the `ng-p ristine` c lass and s et the con trol to it s dirty
  20408      * state  (`ng-dirt y` class).  A model i s consider ed to be d irty when  the contro l has been  changed
  20409      * from  when first  compiled.
  20410      */
  20411     this.$se tDirty = f unction()  {
  20412       ctrl.$ dirty = tr ue;
  20413       ctrl.$ pristine =  false;
  20414       $anima te.removeC lass($elem ent, PRIST INE_CLASS) ;
  20415       $anima te.addClas s($element , DIRTY_CL ASS);
  20416       parent Form.$setD irty();
  20417     };
  20418  
  20419     /**
  20420      * @ngdo c method
  20421      * @name  ngModel.N gModelCont roller#$se tUntouched
  20422      *
  20423      * @desc ription
  20424      * Sets  the contro l to its u ntouched s tate.
  20425      *
  20426      * This  method can  be called  to remove  the `ng-t ouched` cl ass and se t the cont rol to its
  20427      * untou ched state  (`ng-unto uched` cla ss). Upon  compilatio n, a model  is set as  untouched
  20428      * by de fault, how ever this  function c an be used  to restor e that sta te if the  model has
  20429      * alrea dy been to uched by t he user.
  20430      */
  20431     this.$se tUntouched  = functio n() {
  20432       ctrl.$ touched =  false;
  20433       ctrl.$ untouched  = true;
  20434       $anima te.setClas s($element , UNTOUCHE D_CLASS, T OUCHED_CLA SS);
  20435     };
  20436  
  20437     /**
  20438      * @ngdo c method
  20439      * @name  ngModel.N gModelCont roller#$se tTouched
  20440      *
  20441      * @desc ription
  20442      * Sets  the contro l to its t ouched sta te.
  20443      *
  20444      * This  method can  be called  to remove  the `ng-u ntouched`  class and  set the co ntrol to i ts
  20445      * touch ed state ( `ng-touche d` class).  A model i s consider ed to be t ouched whe n the user  has
  20446      * first  focused t he control  element a nd then sh ifted focu s away fro m the cont rol (blur  event).
  20447      */
  20448     this.$se tTouched =  function( ) {
  20449       ctrl.$ touched =  true;
  20450       ctrl.$ untouched  = false;
  20451       $anima te.setClas s($element , TOUCHED_ CLASS, UNT OUCHED_CLA SS);
  20452     };
  20453  
  20454     /**
  20455      * @ngdo c method
  20456      * @name  ngModel.N gModelCont roller#$ro llbackView Value
  20457      *
  20458      * @desc ription
  20459      * Cance l an updat e and rese t the inpu t element' s value to  prevent a n update t o the `$mo delValue`,
  20460      * which  may be ca used by a  pending de bounced ev ent or bec ause the i nput is wa iting for  a some
  20461      * futur e event.
  20462      *
  20463      * If yo u have an  input that  uses `ng- model-opti ons` to se t up debou nced event s or event s such
  20464      * as bl ur you can  have a si tuation wh ere there  is a perio d when the  `$viewVal ue`
  20465      * is ou t of synch  with the  ngModel's  `$modelVal ue`.
  20466      *
  20467      * In th is case, y ou can run  into diff iculties i f you try  to update  the ngMode l's `$mode lValue`
  20468      * progr ammaticall y before t hese debou nced/futur e events h ave resolv ed/occurre d, because  Angular's
  20469      * dirty  checking  mechanism  is not abl e to tell  whether th e model ha s actually  changed o r not.
  20470      *
  20471      * The ` $rollbackV iewValue() ` method s hould be c alled befo re program matically  changing t he model o f an
  20472      * input  which may  have such  events pe nding. Thi s is impor tant in or der to mak e sure tha t the
  20473      * input  field wil l be updat ed with th e new mode l value an d any pend ing operat ions are c ancelled.
  20474      *
  20475      * <exam ple name=" ng-model-c ancel-upda te" module ="cancel-u pdate-exam ple">
  20476      *   <fi le name="a pp.js">
  20477      *     a ngular.mod ule('cance l-update-e xample', [ ])
  20478      *
  20479      *     . controller ('CancelUp dateContro ller', ['$ scope', fu nction($sc ope) {
  20480      *        $scope.re setWithCan cel = func tion(e) {
  20481      *          if (e.k eyCode ==  27) {
  20482      *            $scop e.myForm.m yInput1.$r ollbackVie wValue();
  20483      *            $scop e.myValue  = '';
  20484      *          }
  20485      *        };
  20486      *        $scope.re setWithout Cancel = f unction(e)  {
  20487      *          if (e.k eyCode ==  27) {
  20488      *            $scop e.myValue  = '';
  20489      *          }
  20490      *        };
  20491      *     } ]);
  20492      *   </f ile>
  20493      *   <fi le name="i ndex.html" >
  20494      *     < div ng-con troller="C ancelUpdat eControlle r">
  20495      *        <p>Try ty ping somet hing in ea ch input.   See that  the model  only updat es when yo u
  20496      *           blur o ff the inp ut.
  20497      *         </p>
  20498      *         <p>Now s ee what ha ppens if y ou start t yping then  press the  Escape ke y</p>
  20499      *
  20500      *        <form nam e="myForm"  ng-model- options="{  updateOn:  'blur' }" >
  20501      *          <p>With  $rollback ViewValue( )</p>
  20502      *          <input  name="myIn put1" ng-m odel="myVa lue" ng-ke ydown="res etWithCanc el($event) "><br/>
  20503      *          myValue : "{{ myVa lue }}"
  20504      *
  20505      *          <p>With out $rollb ackViewVal ue()</p>
  20506      *          <input  name="myIn put2" ng-m odel="myVa lue" ng-ke ydown="res etWithoutC ancel($eve nt)"><br/>
  20507      *          myValue : "{{ myVa lue }}"
  20508      *        </form>
  20509      *     < /div>
  20510      *   </f ile>
  20511      * </exa mple>
  20512      */
  20513     this.$ro llbackView Value = fu nction() {
  20514       $timeo ut.cancel( pendingDeb ounce);
  20515       ctrl.$ viewValue  = ctrl.$$l astCommitt edViewValu e;
  20516       ctrl.$ render();
  20517     };
  20518  
  20519     /**
  20520      * @ngdo c method
  20521      * @name  ngModel.N gModelCont roller#$va lidate
  20522      *
  20523      * @desc ription
  20524      * Runs  each of th e register ed validat ors (first  synchrono us validat ors and th en
  20525      * async hronous va lidators).
  20526      * If th e validity  changes t o invalid,  the model  will be s et to `und efined`,
  20527      * unles s {@link n gModelOpti ons `ngMod elOptions. allowInval id`} is `t rue`.
  20528      * If th e validity  changes t o valid, i t will set  the model  to the la st availab le valid
  20529      * model Value, i.e . either t he last pa rsed value  or the la st value s et from th e scope.
  20530      */
  20531     this.$va lidate = f unction()  {
  20532       // ign ore $valid ate before  model is  initialize d
  20533       if (is Number(ctr l.$modelVa lue) && is NaN(ctrl.$ modelValue )) {
  20534         retu rn;
  20535       }
  20536  
  20537       var vi ewValue =  ctrl.$$las tCommitted ViewValue;
  20538       // Not e: we use  the $$rawM odelValue  as $modelV alue might  have been
  20539       // set  to undefi ned during  a view ->  model upd ate that f ound valid ation
  20540       // err ors. We ca n't parse  the view h ere, since  that coul d change
  20541       // the  model alt hough neit her viewVa lue nor th e model on  the scope  changed
  20542       var mo delValue =  ctrl.$$ra wModelValu e;
  20543  
  20544       // Che ck if the  there's a  parse erro r, so we d on't unset  it accide ntially
  20545       var pa rserName =  ctrl.$$pa rserName | | 'parse';
  20546       var pa rserValid  = ctrl.$er ror[parser Name] ? fa lse : unde fined;
  20547  
  20548       var pr evValid =  ctrl.$vali d;
  20549       var pr evModelVal ue = ctrl. $modelValu e;
  20550  
  20551       var al lowInvalid  = ctrl.$o ptions &&  ctrl.$opti ons.allowI nvalid;
  20552  
  20553       ctrl.$ $runValida tors(parse rValid, mo delValue,  viewValue,  function( allValid)  {
  20554         // I f there wa s no chang e in valid ity, don't  update th e model
  20555         // T his preven ts changin g an inval id modelVa lue to und efined
  20556         if ( !allowInva lid && pre vValid !==  allValid)  {
  20557           //  Note: Don 't check c trl.$valid  here, as  we could h ave
  20558           //  external  validators  (e.g. cal culated on  the serve r),
  20559           //  that just  call $set Validity a nd need th e model va lue
  20560           //  to calcul ate their  validity.
  20561           ct rl.$modelV alue = all Valid ? mo delValue :  undefined ;
  20562  
  20563           if  (ctrl.$mo delValue ! == prevMod elValue) {
  20564              ctrl.$$wri teModelToS cope();
  20565           }
  20566         }
  20567       });
  20568  
  20569     };
  20570  
  20571     this.$$r unValidato rs = funct ion(parseV alid, mode lValue, vi ewValue, d oneCallbac k) {
  20572       curren tValidatio nRunId++;
  20573       var lo calValidat ionRunId =  currentVa lidationRu nId;
  20574  
  20575       // che ck parser  error
  20576       if (!p rocessPars eErrors(pa rseValid))  {
  20577         vali dationDone (false);
  20578         retu rn;
  20579       }
  20580       if (!p rocessSync Validators ()) {
  20581         vali dationDone (false);
  20582         retu rn;
  20583       }
  20584       proces sAsyncVali dators();
  20585  
  20586       functi on process ParseError s(parseVal id) {
  20587         var  errorKey =  ctrl.$$pa rserName | | 'parse';
  20588         if ( parseValid  === undef ined) {
  20589           se tValidity( errorKey,  null);
  20590         } el se {
  20591           se tValidity( errorKey,  parseValid );
  20592           if  (!parseVa lid) {
  20593              forEach(ct rl.$valida tors, func tion(v, na me) {
  20594                setValid ity(name,  null);
  20595              });
  20596              forEach(ct rl.$asyncV alidators,  function( v, name) {
  20597                setValid ity(name,  null);
  20598              });
  20599              return fal se;
  20600           }
  20601         }
  20602         retu rn true;
  20603       }
  20604  
  20605       functi on process SyncValida tors() {
  20606         var  syncValida torsValid  = true;
  20607         forE ach(ctrl.$ validators , function (validator , name) {
  20608           va r result =  validator (modelValu e, viewVal ue);
  20609           sy ncValidato rsValid =  syncValida torsValid  && result;
  20610           se tValidity( name, resu lt);
  20611         });
  20612         if ( !syncValid atorsValid ) {
  20613           fo rEach(ctrl .$asyncVal idators, f unction(v,  name) {
  20614              setValidit y(name, nu ll);
  20615           }) ;
  20616           re turn false ;
  20617         }
  20618         retu rn true;
  20619       }
  20620  
  20621       functi on process AsyncValid ators() {
  20622         var  validatorP romises =  [];
  20623         var  allValid =  true;
  20624         forE ach(ctrl.$ asyncValid ators, fun ction(vali dator, nam e) {
  20625           va r promise  = validato r(modelVal ue, viewVa lue);
  20626           if  (!isPromi seLike(pro mise)) {
  20627              throw $ngM odelMinErr ("$asyncVa lidators",
  20628                "Expecte d asynchro nous valid ator to re turn a pro mise but g ot '{0}' i nstead.",  promise);
  20629           }
  20630           se tValidity( name, unde fined);
  20631           va lidatorPro mises.push (promise.t hen(functi on() {
  20632              setValidit y(name, tr ue);
  20633           },  function( error) {
  20634              allValid =  false;
  20635              setValidit y(name, fa lse);
  20636           }) );
  20637         });
  20638         if ( !validator Promises.l ength) {
  20639           va lidationDo ne(true);
  20640         } el se {
  20641           $q .all(valid atorPromis es).then(f unction()  {
  20642              validation Done(allVa lid);
  20643           },  noop);
  20644         }
  20645       }
  20646  
  20647       functi on setVali dity(name,  isValid)  {
  20648         if ( localValid ationRunId  === curre ntValidati onRunId) {
  20649           ct rl.$setVal idity(name , isValid) ;
  20650         }
  20651       }
  20652  
  20653       functi on validat ionDone(al lValid) {
  20654         if ( localValid ationRunId  === curre ntValidati onRunId) {
  20655  
  20656           do neCallback (allValid) ;
  20657         }
  20658       }
  20659     };
  20660  
  20661     /**
  20662      * @ngdo c method
  20663      * @name  ngModel.N gModelCont roller#$co mmitViewVa lue
  20664      *
  20665      * @desc ription
  20666      * Commi t a pendin g update t o the `$mo delValue`.
  20667      *
  20668      * Updat es may be  pending by  a debounc ed event o r because  the input  is waiting  for a som e future
  20669      * event  defined i n `ng-mode l-options` . this met hod is rar ely needed  as `NgMod elControll er`
  20670      * usual ly handles  calling t his in res ponse to i nput event s.
  20671      */
  20672     this.$co mmitViewVa lue = func tion() {
  20673       var vi ewValue =  ctrl.$view Value;
  20674  
  20675       $timeo ut.cancel( pendingDeb ounce);
  20676  
  20677       // If  the view v alue has n ot changed  then we s hould just  exit, exc ept in the  case wher e there is
  20678       // a n ative vali dator on t he element . In this  case the v alidation  state may  have chang ed even th ough
  20679       // the  viewValue  has staye d empty.
  20680       if (ct rl.$$lastC ommittedVi ewValue == = viewValu e && (view Value !==  '' || !ctr l.$$hasNat iveValidat ors)) {
  20681         retu rn;
  20682       }
  20683       ctrl.$ $lastCommi ttedViewVa lue = view Value;
  20684  
  20685       // cha nge to dir ty
  20686       if (ct rl.$pristi ne) {
  20687         this .$setDirty ();
  20688       }
  20689       this.$ $parseAndV alidate();
  20690     };
  20691  
  20692     this.$$p arseAndVal idate = fu nction() {
  20693       var vi ewValue =  ctrl.$$las tCommitted ViewValue;
  20694       var mo delValue =  viewValue ;
  20695       var pa rserValid  = isUndefi ned(modelV alue) ? un defined :  true;
  20696  
  20697       if (pa rserValid)  {
  20698         for  (var i = 0 ; i < ctrl .$parsers. length; i+ +) {
  20699           mo delValue =  ctrl.$par sers[i](mo delValue);
  20700           if  (isUndefi ned(modelV alue)) {
  20701              parserVali d = false;
  20702              break;
  20703           }
  20704         }
  20705       }
  20706       if (is Number(ctr l.$modelVa lue) && is NaN(ctrl.$ modelValue )) {
  20707         // c trl.$model Value has  not been t ouched yet ...
  20708         ctrl .$modelVal ue = ngMod elGet($sco pe);
  20709       }
  20710       var pr evModelVal ue = ctrl. $modelValu e;
  20711       var al lowInvalid  = ctrl.$o ptions &&  ctrl.$opti ons.allowI nvalid;
  20712       ctrl.$ $rawModelV alue = mod elValue;
  20713       if (al lowInvalid ) {
  20714         ctrl .$modelVal ue = model Value;
  20715         writ eToModelIf Needed();
  20716       }
  20717       ctrl.$ $runValida tors(parse rValid, mo delValue,  viewValue,  function( allValid)  {
  20718         if ( !allowInva lid) {
  20719           //  Note: Don 't check c trl.$valid  here, as  we could h ave
  20720           //  external  validators  (e.g. cal culated on  the serve r),
  20721           //  that just  call $set Validity a nd need th e model va lue
  20722           //  to calcul ate their  validity.
  20723           ct rl.$modelV alue = all Valid ? mo delValue :  undefined ;
  20724           wr iteToModel IfNeeded() ;
  20725         }
  20726       });
  20727  
  20728       functi on writeTo ModelIfNee ded() {
  20729         if ( ctrl.$mode lValue !==  prevModel Value) {
  20730           ct rl.$$write ModelToSco pe();
  20731         }
  20732       }
  20733     };
  20734  
  20735     this.$$w riteModelT oScope = f unction()  {
  20736       ngMode lSet($scop e, ctrl.$m odelValue) ;
  20737       forEac h(ctrl.$vi ewChangeLi steners, f unction(li stener) {
  20738         try  {
  20739           li stener();
  20740         } ca tch (e) {
  20741           $e xceptionHa ndler(e);
  20742         }
  20743       });
  20744     };
  20745  
  20746     /**
  20747      * @ngdo c method
  20748      * @name  ngModel.N gModelCont roller#$se tViewValue
  20749      *
  20750      * @desc ription
  20751      * Updat e the view  value.
  20752      *
  20753      * This  method sho uld be cal led when a n input di rective wa nt to chan ge the vie w value; t ypically,
  20754      * this  is done fr om within  a DOM even t handler.
  20755      *
  20756      * For e xample {@l ink ng.dir ective:inp ut input}  calls it w hen the va lue of the  input cha nges and
  20757      * {@lin k ng.direc tive:selec t select}  calls it w hen an opt ion is sel ected.
  20758      *
  20759      * If th e new `val ue` is an  object (ra ther than  a string o r a number ), we shou ld make a  copy of th e
  20760      * objec t before p assing it  to `$setVi ewValue`.   This is b ecause `ng Model` doe s not perf orm a deep
  20761      * watch  of object s, it only  looks for  a change  of identit y. If you  only chang e the prop erty of
  20762      * the o bject then  ngModel w ill not re alise that  the objec t has chan ged and wi ll not inv oke the
  20763      * `$par sers` and  `$validato rs` pipeli nes.
  20764      *
  20765      * For t his reason , you shou ld not cha nge proper ties of th e copy onc e it has b een passed  to
  20766      * `$set ViewValue` . Otherwis e you may  cause the  model valu e on the s cope to ch ange incor rectly.
  20767      *
  20768      * When  this metho d is calle d, the new  `value` w ill be sta ged for co mmitting t hrough the  `$parsers `
  20769      * and ` $validator s` pipelin es. If the re are no  special {@ link ngMod elOptions}  specified  then the  staged
  20770      * value  sent dire ctly for p rocessing,  finally t o be appli ed to `$mo delValue`  and then t he
  20771      * **exp ression**  specified  in the `ng -model` at tribute.
  20772      *
  20773      * Lastl y, all the  registere d change l isteners,  in the `$v iewChangeL isteners`  list, are  called.
  20774      *
  20775      * In ca se the {@l ink ng.dir ective:ngM odelOption s ngModelO ptions} di rective is  used with  `updateOn `
  20776      * and t he `defaul t` trigger  is not li sted, all  those acti ons will r emain pend ing until  one of the
  20777      * `upda teOn` even ts is trig gered on t he DOM ele ment.
  20778      * All t hese actio ns will be  debounced  if the {@ link ng.di rective:ng ModelOptio ns ngModel Options}
  20779      * direc tive is us ed with a  custom deb ounce for  this parti cular even t.
  20780      *
  20781      * Note  that calli ng this fu nction doe s not trig ger a `$di gest`.
  20782      *
  20783      * @para m {string}  value Val ue from th e view.
  20784      * @para m {string}  trigger E vent that  triggered  the update .
  20785      */
  20786     this.$se tViewValue  = functio n(value, t rigger) {
  20787       ctrl.$ viewValue  = value;
  20788       if (!c trl.$optio ns || ctrl .$options. updateOnDe fault) {
  20789         ctrl .$$debounc eViewValue Commit(tri gger);
  20790       }
  20791     };
  20792  
  20793     this.$$d ebounceVie wValueComm it = funct ion(trigge r) {
  20794       var de bounceDela y = 0,
  20795           op tions = ct rl.$option s,
  20796           de bounce;
  20797  
  20798       if (op tions && i sDefined(o ptions.deb ounce)) {
  20799         debo unce = opt ions.debou nce;
  20800         if ( isNumber(d ebounce))  {
  20801           de bounceDela y = deboun ce;
  20802         } el se if (isN umber(debo unce[trigg er])) {
  20803           de bounceDela y = deboun ce[trigger ];
  20804         } el se if (isN umber(debo unce['defa ult'])) {
  20805           de bounceDela y = deboun ce['defaul t'];
  20806         }
  20807       }
  20808  
  20809       $timeo ut.cancel( pendingDeb ounce);
  20810       if (de bounceDela y) {
  20811         pend ingDebounc e = $timeo ut(functio n() {
  20812           ct rl.$commit ViewValue( );
  20813         }, d ebounceDel ay);
  20814       } else  if ($root Scope.$$ph ase) {
  20815         ctrl .$commitVi ewValue();
  20816       } else  {
  20817         $sco pe.$apply( function()  {
  20818           ct rl.$commit ViewValue( );
  20819         });
  20820       }
  20821     };
  20822  
  20823     // model  -> value
  20824     // Note:  we cannot  use a nor mal scope. $watch as  we want to  detect th e followin g:
  20825     // 1. sc ope value  is 'a'
  20826     // 2. us er enters  'b'
  20827     // 3. ng -change ki cks in and  reverts s cope value  to 'a'
  20828     //    ->  scope val ue did not  change si nce the la st digest  as
  20829     //        ng-change  executes  in apply p hase
  20830     // 4. vi ew should  be changed  back to ' a'
  20831     $scope.$ watch(func tion ngMod elWatch()  {
  20832       var mo delValue =  ngModelGe t($scope);
  20833  
  20834       // if  scope mode l value an d ngModel  value are  out of syn c
  20835       // TOD O(perf): w hy not mov e this to  the action  fn?
  20836       if (mo delValue ! == ctrl.$m odelValue)  {
  20837         ctrl .$modelVal ue = ctrl. $$rawModel Value = mo delValue;
  20838  
  20839         var  formatters  = ctrl.$f ormatters,
  20840              idx = form atters.len gth;
  20841  
  20842         var  viewValue  = modelVal ue;
  20843         whil e (idx--)  {
  20844           vi ewValue =  formatters [idx](view Value);
  20845         }
  20846         if ( ctrl.$view Value !==  viewValue)  {
  20847           ct rl.$viewVa lue = ctrl .$$lastCom mittedView Value = vi ewValue;
  20848           ct rl.$render ();
  20849  
  20850           ct rl.$$runVa lidators(u ndefined,  modelValue , viewValu e, noop);
  20851         }
  20852       }
  20853  
  20854       return  modelValu e;
  20855     });
  20856   }];
  20857  
  20858  
  20859   /**
  20860    * @ngdoc  directive
  20861    * @name n gModel
  20862    *
  20863    * @elemen t input
  20864    * @priori ty 1
  20865    *
  20866    * @descri ption
  20867    * The `ng Model` dir ective bin ds an `inp ut`,`selec t`, `texta rea` (or c ustom form  control)  to a
  20868    * propert y on the s cope using  {@link ng Model.NgMo delControl ler NgMode lControlle r},
  20869    * which i s created  and expose d by this  directive.
  20870    *
  20871    * `ngMode l` is resp onsible fo r:
  20872    *
  20873    * - Bindi ng the vie w into the  model, wh ich other  directives  such as ` input`, `t extarea` o r `select`
  20874    *   requi re.
  20875    * - Provi ding valid ation beha vior (i.e.  required,  number, e mail, url) .
  20876    * - Keepi ng the sta te of the  control (v alid/inval id, dirty/ pristine,  touched/un touched, v alidation  errors).
  20877    * - Setti ng related  css class es on the  element (` ng-valid`,  `ng-inval id`, `ng-d irty`, `ng -pristine` , `ng-touc hed`, `ng- untouched` ) includin g animatio ns.
  20878    * - Regis tering the  control w ith its pa rent {@lin k ng.direc tive:form  form}.
  20879    *
  20880    * Note: ` ngModel` w ill try to  bind to t he propert y given by  evaluatin g the expr ession on  the
  20881    * current  scope. If  the prope rty doesn' t already  exist on t his scope,  it will b e created
  20882    * implici tly and ad ded to the  scope.
  20883    *
  20884    * For bes t practice s on using  `ngModel` , see:
  20885    *
  20886    *  - [Und erstanding  Scopes](h ttps://git hub.com/an gular/angu lar.js/wik i/Understa nding-Scop es)
  20887    *
  20888    * For bas ic example s, how to  use `ngMod el`, see:
  20889    *
  20890    *  - {@li nk ng.dire ctive:inpu t input}
  20891    *    - {@ link input [text] tex t}
  20892    *    - {@ link input [checkbox]  checkbox}
  20893    *    - {@ link input [radio] ra dio}
  20894    *    - {@ link input [number] n umber}
  20895    *    - {@ link input [email] em ail}
  20896    *    - {@ link input [url] url}
  20897    *    - {@ link input [date] dat e}
  20898    *    - {@ link input [datetime- local] dat etime-loca l}
  20899    *    - {@ link input [time] tim e}
  20900    *    - {@ link input [month] mo nth}
  20901    *    - {@ link input [week] wee k}
  20902    *  - {@li nk ng.dire ctive:sele ct select}
  20903    *  - {@li nk ng.dire ctive:text area texta rea}
  20904    *
  20905    * # CSS c lasses
  20906    * The fol lowing CSS  classes a re added a nd removed  on the as sociated i nput/selec t/textarea  element
  20907    * dependi ng on the  validity o f the mode l.
  20908    *
  20909    *  - `ng- valid`: th e model is  valid
  20910    *  - `ng- invalid`:  the model  is invalid
  20911    *  - `ng- valid-[key ]`: for ea ch valid k ey added b y `$setVal idity`
  20912    *  - `ng- invalid-[k ey]`: for  each inval id key add ed by `$se tValidity`
  20913    *  - `ng- pristine`:  the contr ol hasn't  been inter acted with  yet
  20914    *  - `ng- dirty`: th e control  has been i nteracted  with
  20915    *  - `ng- touched`:  the contro l has been  blurred
  20916    *  - `ng- untouched` : the cont rol hasn't  been blur red
  20917    *  - `ng- pending`:  any `$asyn cValidator s` are unf ulfilled
  20918    *
  20919    * Keep in  mind that  ngAnimate  can detec t each of  these clas ses when a dded and r emoved.
  20920    *
  20921    * ## Anim ation Hook s
  20922    *
  20923    * Animati ons within  models ar e triggere d when any  of the as sociated C SS classes  are added  and remov ed
  20924    * on the  input elem ent which  is attache d to the m odel. Thes e classes  are: `.ng- pristine`,  `.ng-dirt y`,
  20925    * `.ng-in valid` and  `.ng-vali d` as well  as any ot her valida tions that  are perfo rmed on th e model it self.
  20926    * The ani mations th at are tri ggered wit hin ngMode l are simi lar to how  they work  in ngClas s and
  20927    * animati ons can be  hooked in to using C SS transit ions, keyf rames as w ell as JS  animations .
  20928    *
  20929    * The fol lowing exa mple shows  a simple  way to uti lize CSS t ransitions  to style  an input e lement
  20930    * that ha s been ren dered as i nvalid aft er it has  been valid ated:
  20931    *
  20932    * <pre>
  20933    * //be su re to incl ude ngAnim ate as a m odule to h ook into m ore
  20934    * //advan ced animat ions
  20935    * .my-inp ut {
  20936    *   trans ition:0.5s  linear al l;
  20937    *   backg round: whi te;
  20938    * }
  20939    * .my-inp ut.ng-inva lid {
  20940    *   backg round: red ;
  20941    *   color :white;
  20942    * }
  20943    * </pre>
  20944    *
  20945    * @exampl e
  20946    * <exampl e deps="an gular-anim ate.js" an imations=" true" fixB ase="true"  module="i nputExampl e">
  20947        <file  name="ind ex.html">
  20948          <sc ript>
  20949           an gular.modu le('inputE xample', [ ])
  20950              .controlle r('Example Controller ', ['$scop e', functi on($scope)  {
  20951                $scope.v al = '1';
  20952              }]);
  20953          </s cript>
  20954          <st yle>
  20955            . my-input {
  20956               -webkit-t ransition: all linear  0.5s;
  20957               transitio n:all line ar 0.5s;
  20958               backgroun d: transpa rent;
  20959            }
  20960            . my-input.n g-invalid  {
  20961               color:whi te;
  20962               backgroun d: red;
  20963            }
  20964          </s tyle>
  20965          Upd ate input  to see tra nsitions w hen valid/ invalid.
  20966          Int eger is a  valid valu e.
  20967          <fo rm name="t estForm" n g-controll er="Exampl eControlle r">
  20968            < input ng-m odel="val"  ng-patter n="/^\d+$/ " name="an im" class= "my-input"  />
  20969          </f orm>
  20970        </fil e>
  20971    * </examp le>
  20972    *
  20973    * ## Bind ing to a g etter/sett er
  20974    *
  20975    * Sometim es it's he lpful to b ind `ngMod el` to a g etter/sett er functio n.  A gett er/setter  is a
  20976    * functio n that ret urns a rep resentatio n of the m odel when  called wit h zero arg uments, an d sets
  20977    * the int ernal stat e of a mod el when ca lled with  an argumen t. It's so metimes us eful to us e this
  20978    * for mod els that h ave an int ernal repr esentation  that's di fferent th an what th e model ex poses
  20979    * to the  view.
  20980    *
  20981    * <div cl ass="alert  alert-suc cess">
  20982    * **Best  Practice:* * It's bes t to keep  getters fa st because  Angular i s likely t o call the m more
  20983    * frequen tly than o ther parts  of your c ode.
  20984    * </div>
  20985    *
  20986    * You use  this beha vior by ad ding `ng-m odel-optio ns="{ gett erSetter:  true }"` t o an eleme nt that
  20987    * has `ng -model` at tached to  it. You ca n also add  `ng-model -options=" { getterSe tter: true  }"` to
  20988    * a `<for m>`, which  will enab le this be havior for  all `<inp ut>`s with in it. See
  20989    * {@link  ng.directi ve:ngModel Options `n gModelOpti ons`} for  more.
  20990    *
  20991    * The fol lowing exa mple shows  how to us e `ngModel ` with a g etter/sett er:
  20992    *
  20993    * @exampl e
  20994    * <exampl e name="ng Model-gett er-setter"  module="g etterSette rExample">
  20995        <file  name="ind ex.html">
  20996          <di v ng-contr oller="Exa mpleContro ller">
  20997            < form name= "userForm" >
  20998               Name:
  20999               <input ty pe="text"  name="user Name"
  21000                      ng -model="us er.name"
  21001                      ng -model-opt ions="{ ge tterSetter : true }"  />
  21002            < /form>
  21003            < pre>user.n ame = <spa n ng-bind= "user.name ()"></span ></pre>
  21004          </d iv>
  21005        </fil e>
  21006        <file  name="app .js">
  21007          ang ular.modul e('getterS etterExamp le', [])
  21008            . controller ('ExampleC ontroller' , ['$scope ', functio n($scope)  {
  21009               var _name  = 'Brian' ;
  21010               $scope.us er = {
  21011                 name: f unction(ne wName) {
  21012                   if (a ngular.isD efined(new Name)) {
  21013                     _na me = newNa me;
  21014                   }
  21015                   retur n _name;
  21016                 }
  21017               };
  21018            } ]);
  21019        </fil e>
  21020    * </examp le>
  21021    */
  21022   var ngMode lDirective  = ['$root Scope', fu nction($ro otScope) {
  21023     return {
  21024       restri ct: 'A',
  21025       requir e: ['ngMod el', '^?fo rm', '^?ng ModelOptio ns'],
  21026       contro ller: NgMo delControl ler,
  21027       // Pre link needs  to run be fore any i nput direc tive
  21028       // so  that we ca n set the  NgModelOpt ions in Ng ModelContr oller
  21029       // bef ore anyone  else uses  it.
  21030       priori ty: 1,
  21031       compil e: functio n ngModelC ompile(ele ment) {
  21032         // S etup initi al state o f the cont rol
  21033         elem ent.addCla ss(PRISTIN E_CLASS).a ddClass(UN TOUCHED_CL ASS).addCl ass(VALID_ CLASS);
  21034  
  21035         retu rn {
  21036           pr e: functio n ngModelP reLink(sco pe, elemen t, attr, c trls) {
  21037              var modelC trl = ctrl s[0],
  21038                  formCt rl = ctrls [1] || nul lFormCtrl;
  21039  
  21040              modelCtrl. $$setOptio ns(ctrls[2 ] && ctrls [2].$optio ns);
  21041  
  21042              // notify  others, es pecially p arent form s
  21043              formCtrl.$ addControl (modelCtrl );
  21044  
  21045              attr.$obse rve('name' , function (newValue)  {
  21046                if (mode lCtrl.$nam e !== newV alue) {
  21047                  formCt rl.$$renam eControl(m odelCtrl,  newValue);
  21048                }
  21049              });
  21050  
  21051              scope.$on( '$destroy' , function () {
  21052                formCtrl .$removeCo ntrol(mode lCtrl);
  21053              });
  21054           },
  21055           po st: functi on ngModel PostLink(s cope, elem ent, attr,  ctrls) {
  21056              var modelC trl = ctrl s[0];
  21057              if (modelC trl.$optio ns && mode lCtrl.$opt ions.updat eOn) {
  21058                element. on(modelCt rl.$option s.updateOn , function (ev) {
  21059                  modelC trl.$$debo unceViewVa lueCommit( ev && ev.t ype);
  21060                });
  21061              }
  21062  
  21063              element.on ('blur', f unction(ev ) {
  21064                if (mode lCtrl.$tou ched) retu rn;
  21065  
  21066                if ($roo tScope.$$p hase) {
  21067                    scope.$e DNS    ync(modelC trl.$setTo uched);
  21068                } else {
  21069                  scope. $apply(mod elCtrl.$se tTouched);
  21070                }
  21071              });
  21072           }
  21073         };
  21074       }
  21075     };
  21076   }];
  21077  
  21078  
  21079   /**
  21080    * @ngdoc  directive
  21081    * @name n gChange
  21082    *
  21083    * @descri ption
  21084    * Evaluat e the give n expressi on when th e user cha nges the i nput.
  21085    * The exp ression is  evaluated  immediate ly, unlike  the JavaS cript onch ange event
  21086    * which o nly trigge rs at the  end of a c hange (usu ally, when  the user  leaves the
  21087    * form el ement or p resses the  return ke y).
  21088    *
  21089    * The `ng Change` ex pression i s only eva luated whe n a change  in the in put value  causes
  21090    * a new v alue to be  committed  to the mo del.
  21091    *
  21092    * It will  not be ev aluated:
  21093    * * if th e value re turned fro m the `$pa rsers` tra nsformatio n pipeline  has not c hanged
  21094    * * if th e input ha s continue d to be in valid sinc e the mode l will sta y `null`
  21095    * * if th e model is  changed p rogrammati cally and  not by a c hange to t he input v alue
  21096    *
  21097    *
  21098    * Note, t his direct ive requir es `ngMode l` to be p resent.
  21099    *
  21100    * @elemen t input
  21101    * @param  {expressio n} ngChang e {@link g uide/expre ssion Expr ession} to  evaluate  upon chang e
  21102    * in inpu t value.
  21103    *
  21104    * @exampl e
  21105    * <exampl e name="ng Change-dir ective" mo dule="chan geExample" >
  21106    *   <file  name="ind ex.html">
  21107    *     <sc ript>
  21108    *       a ngular.mod ule('chang eExample',  [])
  21109    *          .controll er('Exampl eControlle r', ['$sco pe', funct ion($scope ) {
  21110    *            $scope. counter =  0;
  21111    *            $scope. change = f unction()  {
  21112    *              $scop e.counter+ +;
  21113    *            };
  21114    *          }]);
  21115    *     </s cript>
  21116    *     <di v ng-contr oller="Exa mpleContro ller">
  21117    *       < input type ="checkbox " ng-model ="confirme d" ng-chan ge="change ()" id="ng -change-ex ample1" />
  21118    *       < input type ="checkbox " ng-model ="confirme d" id="ng- change-exa mple2" />
  21119    *       < label for= "ng-change -example2" >Confirmed </label><b r />
  21120    *       < tt>debug =  {{confirm ed}}</tt>< br/>
  21121    *       < tt>counter  = {{count er}}</tt>< br/>
  21122    *     </d iv>
  21123    *   </fil e>
  21124    *   <file  name="pro tractor.js " type="pr otractor">
  21125    *     var  counter =  element(b y.binding( 'counter') );
  21126    *     var  debug = e lement(by. binding('c onfirmed') );
  21127    *
  21128    *     it( 'should ev aluate the  expressio n if chang ing from v iew', func tion() {
  21129    *       e xpect(coun ter.getTex t()).toCon tain('0');
  21130    *
  21131    *       e lement(by. id('ng-cha nge-exampl e1')).clic k();
  21132    *
  21133    *       e xpect(coun ter.getTex t()).toCon tain('1');
  21134    *       e xpect(debu g.getText( )).toConta in('true') ;
  21135    *     });
  21136    *
  21137    *     it( 'should no t evaluate  the expre ssion if c hanging fr om model',  function( ) {
  21138    *       e lement(by. id('ng-cha nge-exampl e2')).clic k();
  21139  
  21140    *       e xpect(coun ter.getTex t()).toCon tain('0');
  21141    *       e xpect(debu g.getText( )).toConta in('true') ;
  21142    *     });
  21143    *   </fil e>
  21144    * </examp le>
  21145    */
  21146   var ngChan geDirectiv e = valueF n({
  21147     restrict : 'A',
  21148     require:  'ngModel' ,
  21149     link: fu nction(sco pe, elemen t, attr, c trl) {
  21150       ctrl.$ viewChange Listeners. push(funct ion() {
  21151         scop e.$eval(at tr.ngChang e);
  21152       });
  21153     }
  21154   });
  21155  
  21156  
  21157   var requir edDirectiv e = functi on() {
  21158     return {
  21159       restri ct: 'A',
  21160       requir e: '?ngMod el',
  21161       link:  function(s cope, elm,  attr, ctr l) {
  21162         if ( !ctrl) ret urn;
  21163         attr .required  = true; //  force tru thy in cas e we are o n non inpu t element
  21164  
  21165         ctrl .$validato rs.require d = functi on(modelVa lue, viewV alue) {
  21166           re turn !attr .required  || !ctrl.$ isEmpty(vi ewValue);
  21167         };
  21168  
  21169         attr .$observe( 'required' , function () {
  21170           ct rl.$valida te();
  21171         });
  21172       }
  21173     };
  21174   };
  21175  
  21176  
  21177   var patter nDirective  = functio n() {
  21178     return {
  21179       restri ct: 'A',
  21180       requir e: '?ngMod el',
  21181       link:  function(s cope, elm,  attr, ctr l) {
  21182         if ( !ctrl) ret urn;
  21183  
  21184         var  regexp, pa tternExp =  attr.ngPa ttern || a ttr.patter n;
  21185         attr .$observe( 'pattern',  function( regex) {
  21186           if  (isString (regex) &&  regex.len gth > 0) {
  21187              regex = ne w RegExp(' ^' + regex  + '$');
  21188           }
  21189  
  21190           if  (regex &&  !regex.te st) {
  21191              throw minE rr('ngPatt ern')('nor egexp',
  21192                'Expecte d {0} to b e a RegExp  but was { 1}. Elemen t: {2}', p atternExp,
  21193                regex, s tartingTag (elm));
  21194           }
  21195  
  21196           re gexp = reg ex || unde fined;
  21197           ct rl.$valida te();
  21198         });
  21199  
  21200         ctrl .$validato rs.pattern  = functio n(value) {
  21201           re turn ctrl. $isEmpty(v alue) || i sUndefined (regexp) | | regexp.t est(value) ;
  21202         };
  21203       }
  21204     };
  21205   };
  21206  
  21207  
  21208   var maxlen gthDirecti ve = funct ion() {
  21209     return {
  21210       restri ct: 'A',
  21211       requir e: '?ngMod el',
  21212       link:  function(s cope, elm,  attr, ctr l) {
  21213         if ( !ctrl) ret urn;
  21214  
  21215         var  maxlength  = -1;
  21216         attr .$observe( 'maxlength ', functio n(value) {
  21217           va r intVal =  int(value );
  21218           ma xlength =  isNaN(intV al) ? -1 :  intVal;
  21219           ct rl.$valida te();
  21220         });
  21221         ctrl .$validato rs.maxleng th = funct ion(modelV alue, view Value) {
  21222           re turn (maxl ength < 0)  || ctrl.$ isEmpty(mo delValue)  || (viewVa lue.length  <= maxlen gth);
  21223         };
  21224       }
  21225     };
  21226   };
  21227  
  21228   var minlen gthDirecti ve = funct ion() {
  21229     return {
  21230       restri ct: 'A',
  21231       requir e: '?ngMod el',
  21232       link:  function(s cope, elm,  attr, ctr l) {
  21233         if ( !ctrl) ret urn;
  21234  
  21235         var  minlength  = 0;
  21236         attr .$observe( 'minlength ', functio n(value) {
  21237           mi nlength =  int(value)  || 0;
  21238           ct rl.$valida te();
  21239         });
  21240         ctrl .$validato rs.minleng th = funct ion(modelV alue, view Value) {
  21241           re turn ctrl. $isEmpty(v iewValue)  || viewVal ue.length  >= minleng th;
  21242         };
  21243       }
  21244     };
  21245   };
  21246  
  21247  
  21248   /**
  21249    * @ngdoc  directive
  21250    * @name n gList
  21251    *
  21252    * @descri ption
  21253    * Text in put that c onverts be tween a de limited st ring and a n array of  strings.  The defaul t
  21254    * delimit er is a co mma follow ed by a sp ace - equi valent to  `ng-list=" , "`. You  can specif y a custom
  21255    * delimit er as the  value of t he `ngList ` attribut e - for ex ample, `ng -list=" |  "`.
  21256    *
  21257    * The beh aviour of  the direct ive is aff ected by t he use of  the `ngTri m` attribu te.
  21258    * * If `n gTrim` is  set to `"f alse"` the n whitespa ce around  both the s eparator a nd each
  21259    *   list  item is re spected. T his implie s that the  user of t he directi ve is resp onsible fo r
  21260    *   deali ng with wh itespace b ut also al lows you t o use whit espace as  a delimite r, such as  a
  21261    *   tab o r newline  character.
  21262    * * Other wise white space arou nd the del imiter is  ignored wh en splitti ng (althou gh it is r espected
  21263    *   when  joining th e list ite ms back to gether) an d whitespa ce around  each list  item is st ripped
  21264    *   befor e it is ad ded to the  model.
  21265    *
  21266    * ### Exa mple with  Validation
  21267    *
  21268    * <exampl e name="ng List-direc tive" modu le="listEx ample">
  21269    *   <file  name="app .js">
  21270    *      an gular.modu le('listEx ample', [] )
  21271    *         .controlle r('Example Controller ', ['$scop e', functi on($scope)  {
  21272    *           $scope.n ames = ['m orpheus',  'neo', 'tr inity'];
  21273    *         }]);
  21274    *   </fil e>
  21275    *   <file  name="ind ex.html">
  21276    *    <for m name="my Form" ng-c ontroller= "ExampleCo ntroller">
  21277    *      Li st: <input  name="nam esInput" n g-model="n ames" ng-l ist requir ed>
  21278    *      <s pan class= "error" ng -show="myF orm.namesI nput.$erro r.required ">
  21279    *         Required!< /span>
  21280    *      <b r>
  21281    *      <t t>names =  {{names}}< /tt><br/>
  21282    *      <t t>myForm.n amesInput. $valid = { {myForm.na mesInput.$ valid}}</t t><br/>
  21283    *      <t t>myForm.n amesInput. $error = { {myForm.na mesInput.$ error}}</t t><br/>
  21284    *      <t t>myForm.$ valid = {{ myForm.$va lid}}</tt> <br/>
  21285    *      <t t>myForm.$ error.requ ired = {{! !myForm.$e rror.requi red}}</tt> <br/>
  21286    *     </f orm>
  21287    *   </fil e>
  21288    *   <file  name="pro tractor.js " type="pr otractor">
  21289    *     var  listInput  = element (by.model( 'names'));
  21290    *     var  names = e lement(by. exactBindi ng('names' ));
  21291    *     var  valid = e lement(by. binding('m yForm.name sInput.$va lid'));
  21292    *     var  error = e lement(by. css('span. error'));
  21293    *
  21294    *     it( 'should in itialize t o model',  function()  {
  21295    *       e xpect(name s.getText( )).toConta in('["morp heus","neo ","trinity "]');
  21296    *       e xpect(vali d.getText( )).toConta in('true') ;
  21297    *       e xpect(erro r.getCssVa lue('displ ay')).toBe ('none');
  21298    *     });
  21299    *
  21300    *     it( 'should be  invalid i f empty',  function()  {
  21301    *       l istInput.c lear();
  21302    *       l istInput.s endKeys('' );
  21303    *
  21304    *       e xpect(name s.getText( )).toConta in('');
  21305    *       e xpect(vali d.getText( )).toConta in('false' );
  21306    *       e xpect(erro r.getCssVa lue('displ ay')).not. toBe('none ');
  21307    *     });
  21308    *   </fil e>
  21309    * </examp le>
  21310    *
  21311    * ### Exa mple - spl itting on  whitespace
  21312    * <exampl e name="ng List-direc tive-newli nes">
  21313    *   <file  name="ind ex.html">
  21314    *    <tex tarea ng-m odel="list " ng-list= "&#10;" ng -trim="fal se"></text area>
  21315    *    <pre >{{ list |  json }}</ pre>
  21316    *   </fil e>
  21317    *   <file  name="pro tractor.js " type="pr otractor">
  21318    *     it( "should sp lit the te xt by newl ines", fun ction() {
  21319    *       v ar listInp ut = eleme nt(by.mode l('list')) ;
  21320    *       v ar output  = element( by.binding ('list | j son'));
  21321    *       l istInput.s endKeys('a bc\ndef\ng hi');
  21322    *       e xpect(outp ut.getText ()).toCont ain('[\n   "abc",\n   "def",\n   "ghi"\n]') ;
  21323    *     });
  21324    *   </fil e>
  21325    * </examp le>
  21326    *
  21327    * @elemen t input
  21328    * @param  {string=}  ngList opt ional deli miter that  should be  used to s plit the v alue.
  21329    */
  21330   var ngList Directive  = function () {
  21331     return {
  21332       restri ct: 'A',
  21333       priori ty: 100,
  21334       requir e: 'ngMode l',
  21335       link:  function(s cope, elem ent, attr,  ctrl) {
  21336         // W e want to  control wh itespace t rimming so  we use th is convolu ted approa ch
  21337         // t o access t he ngList  attribute,  which doe sn't pre-t rim the at tribute
  21338         var  ngList = e lement.att r(attr.$at tr.ngList)  || ', ';
  21339         var  trimValues  = attr.ng Trim !== ' false';
  21340         var  separator  = trimValu es ? trim( ngList) :  ngList;
  21341  
  21342         var  parse = fu nction(vie wValue) {
  21343           //  If the vi ewValue is  invalid ( say requir ed but emp ty) it wil l be `unde fined`
  21344           if  (isUndefi ned(viewVa lue)) retu rn;
  21345  
  21346           va r list = [ ];
  21347  
  21348           if  (viewValu e) {
  21349              forEach(vi ewValue.sp lit(separa tor), func tion(value ) {
  21350                if (valu e) list.pu sh(trimVal ues ? trim (value) :  value);
  21351              });
  21352           }
  21353  
  21354           re turn list;
  21355         };
  21356  
  21357         ctrl .$parsers. push(parse );
  21358         ctrl .$formatte rs.push(fu nction(val ue) {
  21359           if  (isArray( value)) {
  21360              return val ue.join(ng List);
  21361           }
  21362  
  21363           re turn undef ined;
  21364         });
  21365  
  21366         // O verride th e standard  $isEmpty  because an  empty arr ay means t he input i s empty.
  21367         ctrl .$isEmpty  = function (value) {
  21368           re turn !valu e || !valu e.length;
  21369         };
  21370       }
  21371     };
  21372   };
  21373  
  21374  
  21375   var CONSTA NT_VALUE_R EGEXP = /^ (true|fals e|\d+)$/;
  21376   /**
  21377    * @ngdoc  directive
  21378    * @name n gValue
  21379    *
  21380    * @descri ption
  21381    * Binds t he given e xpression  to the val ue of `<op tion>` or  {@link inp ut[radio]  `input[rad io]`},
  21382    * so that  when the  element is  selected,  the {@lin k ngModel  `ngModel`}  of that e lement is  set to
  21383    * the bou nd value.
  21384    *
  21385    * `ngValu e` is usef ul when dy namically  generating  lists of  radio butt ons using
  21386    * {@link  ngRepeat ` ngRepeat`} , as shown  below.
  21387    *
  21388    * Likewis e, `ngValu e` can be  used to ge nerate `<o ption>` el ements for
  21389    * the {@l ink select  `select`}  element.  In that ca se however , only str ings are s upported
  21390    * for the  `value `a ttribute,  so the res ulting `ng Model` wil l always b e a string .
  21391    * Support  for `sele ct` models  with non- string val ues is ava ilable via  `ngOption s`.
  21392    *
  21393    * @elemen t input
  21394    * @param  {string=}  ngValue an gular expr ession, wh ose value  will be bo und to the  `value` a ttribute
  21395    *   of th e `input`  element
  21396    *
  21397    * @exampl e
  21398       <examp le name="n gValue-dir ective" mo dule="valu eExample">
  21399         <fil e name="in dex.html">
  21400          <sc ript>
  21401              angular.mo dule('valu eExample',  [])
  21402                .control ler('Examp leControll er', ['$sc ope', func tion($scop e) {
  21403                  $scope .names = [ 'pizza', ' unicorns',  'robots'] ;
  21404                  $scope .my = { fa vorite: 'u nicorns' } ;
  21405                }]);
  21406          </s cript>
  21407           <f orm ng-con troller="E xampleCont roller">
  21408              <h2>Which  is your fa vorite?</h 2>
  21409                <label n g-repeat=" name in na mes" for=" {{name}}">
  21410                  {{name }}
  21411                  <input  type="rad io"
  21412                          ng-model= "my.favori te"
  21413                          ng-value= "name"
  21414                          id="{{nam e}}"
  21415                          name="fav orite">
  21416                </label>
  21417              <div>You c hose {{my. favorite}} </div>
  21418           </ form>
  21419         </fi le>
  21420         <fil e name="pr otractor.j s" type="p rotractor" >
  21421           va r favorite  = element (by.bindin g('my.favo rite'));
  21422  
  21423           it ('should i nitialize  to model',  function( ) {
  21424              expect(fav orite.getT ext()).toC ontain('un icorns');
  21425           }) ;
  21426           it ('should b ind the va lues to th e inputs',  function( ) {
  21427              element.al l(by.model ('my.favor ite')).get (0).click( );
  21428              expect(fav orite.getT ext()).toC ontain('pi zza');
  21429           }) ;
  21430         </fi le>
  21431       </exam ple>
  21432    */
  21433   var ngValu eDirective  = functio n() {
  21434     return {
  21435       restri ct: 'A',
  21436       priori ty: 100,
  21437       compil e: functio n(tpl, tpl Attr) {
  21438         if ( CONSTANT_V ALUE_REGEX P.test(tpl Attr.ngVal ue)) {
  21439           re turn funct ion ngValu eConstantL ink(scope,  elm, attr ) {
  21440              attr.$set( 'value', s cope.$eval (attr.ngVa lue));
  21441           };
  21442         } el se {
  21443           re turn funct ion ngValu eLink(scop e, elm, at tr) {
  21444              scope.$wat ch(attr.ng Value, fun ction valu eWatchActi on(value)  {
  21445                attr.$se t('value',  value);
  21446              });
  21447           };
  21448         }
  21449       }
  21450     };
  21451   };
  21452  
  21453   /**
  21454    * @ngdoc  directive
  21455    * @name n gModelOpti ons
  21456    *
  21457    * @descri ption
  21458    * Allows  tuning how  model upd ates are d one. Using  `ngModelO ptions` yo u can spec ify a cust om list of
  21459    * events  that will  trigger a  model upda te and/or  a debounci ng delay s o that the  actual up date only
  21460    * takes p lace when  a timer ex pires; thi s timer wi ll be rese t after an other chan ge takes p lace.
  21461    *
  21462    * Given t he nature  of `ngMode lOptions`,  the value  displayed  inside in put fields  in the vi ew might
  21463    * be diff erent than  the value  in the ac tual model . This mea ns that if  you updat e the mode l you
  21464    * should  also invok e {@link n gModel.NgM odelContro ller `$rol lbackViewV alue`} on  the releva nt input f ield in
  21465    * order t o make sur e it is sy nchronized  with the  model and  that any d ebounced a ction is c anceled.
  21466    *
  21467    * The eas iest way t o referenc e the cont rol's {@li nk ngModel .NgModelCo ntroller ` $rollbackV iewValue`}
  21468    * method  is by maki ng sure th e input is  placed in side a for m that has  a `name`  attribute.  This is
  21469    * importa nt because  `form` co ntrollers  are publis hed to the  related s cope under  the name  in their
  21470    * `name`  attribute.
  21471    *
  21472    * Any pen ding chang es will ta ke place i mmediately  when an e nclosing f orm is sub mitted via  the
  21473    * `submit ` event. N ote that ` ngClick` e vents will  occur bef ore the mo del is upd ated. Use  `ngSubmit`
  21474    * to have  access to  the updat ed model.
  21475    *
  21476    * `ngMode lOptions`  has an eff ect on the  element i t's declar ed on and  its descen dants.
  21477    *
  21478    * @param  {Object} n gModelOpti ons option s to apply  to the cu rrent mode l. Valid k eys are:
  21479    *   - `up dateOn`: s tring spec ifying whi ch event s hould the  input be b ound to. Y ou can set  several
  21480    *     eve nts using  an space d elimited l ist. There  is a spec ial event  called `de fault` tha t
  21481    *     mat ches the d efault eve nts belong ing of the  control.
  21482    *   - `de bounce`: i nteger val ue which c ontains th e debounce  model upd ate value  in millise conds. A
  21483    *     val ue of 0 tr iggers an  immediate  update. If  an object  is suppli ed instead , you can  specify a
  21484    *     cus tom value  for each e vent. For  example:
  21485    *     `ng -model-opt ions="{ up dateOn: 'd efault blu r', deboun ce: {'defa ult': 500,  'blur': 0 } }"`
  21486    *   - `al lowInvalid `: boolean  value whi ch indicat es that th e model ca n be set w ith values  that did
  21487    *     not  validate  correctly  instead of  the defau lt behavio r of setti ng the mod el to unde fined.
  21488    *   - `ge tterSetter `: boolean  value whi ch determi nes whethe r or not t o treat fu nctions bo und to
  21489          `ng Model` as  getters/se tters.
  21490    *   - `ti mezone`: D efines the  timezone  to be used  to read/w rite the ` Date` inst ance in th e model fo r
  21491    *     `<i nput type= "date">`,  `<input ty pe="time"> `, ... . R ight now,  the only s upported v alue is `' UTC'`,
  21492    *     oth erwise the  default t imezone of  the brows er will be  used.
  21493    *
  21494    * @exampl e
  21495  
  21496     The foll owing exam ple shows  how to ove rride imme diate upda tes. Chang es on the  inputs wit hin the
  21497     form wil l update t he model o nly when t he control  loses foc us (blur e vent). If  `escape` k ey is
  21498     pressed  while the  input fiel d is focus ed, the va lue is res et to the  value in t he current  model.
  21499  
  21500     <example  name="ngM odelOption s-directiv e-blur" mo dule="opti onsExample ">
  21501       <file  name="inde x.html">
  21502         <div  ng-contro ller="Exam pleControl ler">
  21503           <f orm name=" userForm">
  21504              Name:
  21505              <input typ e="text" n ame="userN ame"
  21506                     ng- model="use r.name"
  21507                     ng- model-opti ons="{ upd ateOn: 'bl ur' }"
  21508                     ng- keyup="can cel($event )" /><br / >
  21509  
  21510              Other data :
  21511              <input typ e="text" n g-model="u ser.data"  /><br />
  21512           </ form>
  21513           <p re>user.na me = <span  ng-bind=" user.name" ></span></ pre>
  21514         </di v>
  21515       </file >
  21516       <file  name="app. js">
  21517         angu lar.module ('optionsE xample', [ ])
  21518           .c ontroller( 'ExampleCo ntroller',  ['$scope' , function ($scope) {
  21519              $scope.use r = { name : 'say', d ata: '' };
  21520  
  21521              $scope.can cel = func tion(e) {
  21522                if (e.ke yCode == 2 7) {
  21523                  $scope .userForm. userName.$ rollbackVi ewValue();
  21524                }
  21525              };
  21526           }] );
  21527       </file >
  21528       <file  name="prot ractor.js"  type="pro tractor">
  21529         var  model = el ement(by.b inding('us er.name')) ;
  21530         var  input = el ement(by.m odel('user .name'));
  21531         var  other = el ement(by.m odel('user .data'));
  21532  
  21533         it(' should all ow custom  events', f unction()  {
  21534           in put.sendKe ys(' hello ');
  21535           in put.click( );
  21536           ex pect(model .getText() ).toEqual( 'say');
  21537           ot her.click( );
  21538           ex pect(model .getText() ).toEqual( 'say hello ');
  21539         });
  21540  
  21541         it(' should $ro llbackView Value when  model cha nges', fun ction() {
  21542           in put.sendKe ys(' hello ');
  21543           ex pect(input .getAttrib ute('value ')).toEqua l('say hel lo');
  21544           in put.sendKe ys(protrac tor.Key.ES CAPE);
  21545           ex pect(input .getAttrib ute('value ')).toEqua l('say');
  21546           ot her.click( );
  21547           ex pect(model .getText() ).toEqual( 'say');
  21548         });
  21549       </file >
  21550     </exampl e>
  21551  
  21552     This one  shows how  to deboun ce model c hanges. Mo del will b e updated  only 1 sec  after las t change.
  21553     If the ` Clear` but ton is pre ssed, any  debounced  action is  canceled a nd the val ue becomes  empty.
  21554  
  21555     <example  name="ngM odelOption s-directiv e-debounce " module=" optionsExa mple">
  21556       <file  name="inde x.html">
  21557         <div  ng-contro ller="Exam pleControl ler">
  21558           <f orm name=" userForm">
  21559              Name:
  21560              <input typ e="text" n ame="userN ame"
  21561                     ng- model="use r.name"
  21562                     ng- model-opti ons="{ deb ounce: 100 0 }" />
  21563              <button ng -click="us erForm.use rName.$rol lbackViewV alue(); us er.name='' ">Clear</b utton><br  />
  21564           </ form>
  21565           <p re>user.na me = <span  ng-bind=" user.name" ></span></ pre>
  21566         </di v>
  21567       </file >
  21568       <file  name="app. js">
  21569         angu lar.module ('optionsE xample', [ ])
  21570           .c ontroller( 'ExampleCo ntroller',  ['$scope' , function ($scope) {
  21571              $scope.use r = { name : 'say' };
  21572           }] );
  21573       </file >
  21574     </exampl e>
  21575  
  21576     This one  shows how  to bind t o getter/s etters:
  21577  
  21578     <example  name="ngM odelOption s-directiv e-getter-s etter" mod ule="gette rSetterExa mple">
  21579       <file  name="inde x.html">
  21580         <div  ng-contro ller="Exam pleControl ler">
  21581           <f orm name=" userForm">
  21582              Name:
  21583              <input typ e="text" n ame="userN ame"
  21584                     ng- model="use r.name"
  21585                     ng- model-opti ons="{ get terSetter:  true }" / >
  21586           </ form>
  21587           <p re>user.na me = <span  ng-bind=" user.name( )"></span> </pre>
  21588         </di v>
  21589       </file >
  21590       <file  name="app. js">
  21591         angu lar.module ('getterSe tterExampl e', [])
  21592           .c ontroller( 'ExampleCo ntroller',  ['$scope' , function ($scope) {
  21593              var _name  = 'Brian';
  21594              $scope.use r = {
  21595                name: fu nction(new Name) {
  21596                  return  angular.i sDefined(n ewName) ?  (_name = n ewName) :  _name;
  21597                }
  21598              };
  21599           }] );
  21600       </file >
  21601     </exampl e>
  21602    */
  21603   var ngMode lOptionsDi rective =  function()  {
  21604     return {
  21605       restri ct: 'A',
  21606       contro ller: ['$s cope', '$a ttrs', fun ction($sco pe, $attrs ) {
  21607         var  that = thi s;
  21608         this .$options  = $scope.$ eval($attr s.ngModelO ptions);
  21609         // A llow addin g/overridi ng bound e vents
  21610         if ( this.$opti ons.update On !== und efined) {
  21611           th is.$option s.updateOn Default =  false;
  21612           //  extract " default" p seudo-even t from lis t of event s that can  trigger a  model upd ate
  21613           th is.$option s.updateOn  = trim(th is.$option s.updateOn .replace(D EFAULT_REG EXP, funct ion() {
  21614              that.$opti ons.update OnDefault  = true;
  21615              return ' ' ;
  21616           }) );
  21617         } el se {
  21618           th is.$option s.updateOn Default =  true;
  21619         }
  21620       }]
  21621     };
  21622   };
  21623  
  21624   // helper  methods
  21625   function a ddSetValid ityMethod( context) {
  21626     var ctrl  = context .ctrl,
  21627         $ele ment = con text.$elem ent,
  21628         clas sCache = { },
  21629         set  = context. set,
  21630         unse t = contex t.unset,
  21631         pare ntForm = c ontext.par entForm,
  21632         $ani mate = con text.$anim ate;
  21633  
  21634     classCac he[INVALID _CLASS] =  !(classCac he[VALID_C LASS] = $e lement.has Class(VALI D_CLASS));
  21635  
  21636     ctrl.$se tValidity  = setValid ity;
  21637  
  21638     function  setValidi ty(validat ionErrorKe y, state,  options) {
  21639       if (st ate === un defined) {
  21640         crea teAndSet(' $pending',  validatio nErrorKey,  options);
  21641       } else  {
  21642         unse tAndCleanu p('$pendin g', valida tionErrorK ey, option s);
  21643       }
  21644       if (!i sBoolean(s tate)) {
  21645         unse t(ctrl.$er ror, valid ationError Key, optio ns);
  21646         unse t(ctrl.$$s uccess, va lidationEr rorKey, op tions);
  21647       } else  {
  21648         if ( state) {
  21649           un set(ctrl.$ error, val idationErr orKey, opt ions);
  21650           se t(ctrl.$$s uccess, va lidationEr rorKey, op tions);
  21651         } el se {
  21652           se t(ctrl.$er ror, valid ationError Key, optio ns);
  21653           un set(ctrl.$ $success,  validation ErrorKey,  options);
  21654         }
  21655       }
  21656       if (ct rl.$pendin g) {
  21657         cach edToggleCl ass(PENDIN G_CLASS, t rue);
  21658         ctrl .$valid =  ctrl.$inva lid = unde fined;
  21659         togg leValidati onCss('',  null);
  21660       } else  {
  21661         cach edToggleCl ass(PENDIN G_CLASS, f alse);
  21662         ctrl .$valid =  isObjectEm pty(ctrl.$ error);
  21663         ctrl .$invalid  = !ctrl.$v alid;
  21664         togg leValidati onCss('',  ctrl.$vali d);
  21665       }
  21666  
  21667       // re- read the s tate as th e set/unse t methods  could have
  21668       // com bined stat e in ctrl. $error[val idationErr or] (used  for forms) ,
  21669       // whe re setting /unsetting  only incr ements/dec rements th e value,
  21670       // and  does not  replace it .
  21671       var co mbinedStat e;
  21672       if (ct rl.$pendin g && ctrl. $pending[v alidationE rrorKey])  {
  21673         comb inedState  = undefine d;
  21674       } else  if (ctrl. $error[val idationErr orKey]) {
  21675         comb inedState  = false;
  21676       } else  if (ctrl. $$success[ validation ErrorKey])  {
  21677         comb inedState  = true;
  21678       } else  {
  21679         comb inedState  = null;
  21680       }
  21681       toggle Validation Css(valida tionErrorK ey, combin edState);
  21682       parent Form.$setV alidity(va lidationEr rorKey, co mbinedStat e, ctrl);
  21683     }
  21684  
  21685     function  createAnd Set(name,  value, opt ions) {
  21686       if (!c trl[name])  {
  21687         ctrl [name] = { };
  21688       }
  21689       set(ct rl[name],  value, opt ions);
  21690     }
  21691  
  21692     function  unsetAndC leanup(nam e, value,  options) {
  21693       if (ct rl[name])  {
  21694         unse t(ctrl[nam e], value,  options);
  21695       }
  21696       if (is ObjectEmpt y(ctrl[nam e])) {
  21697         ctrl [name] = u ndefined;
  21698       }
  21699     }
  21700  
  21701     function  cachedTog gleClass(c lassName,  switchValu e) {
  21702       if (sw itchValue  && !classC ache[class Name]) {
  21703         $ani mate.addCl ass($eleme nt, classN ame);
  21704         clas sCache[cla ssName] =  true;
  21705       } else  if (!swit chValue &&  classCach e[classNam e]) {
  21706         $ani mate.remov eClass($el ement, cla ssName);
  21707         clas sCache[cla ssName] =  false;
  21708       }
  21709     }
  21710  
  21711     function  toggleVal idationCss (validatio nErrorKey,  isValid)  {
  21712       valida tionErrorK ey = valid ationError Key ? '-'  + snake_ca se(validat ionErrorKe y, '-') :  '';
  21713  
  21714       cached ToggleClas s(VALID_CL ASS + vali dationErro rKey, isVa lid === tr ue);
  21715       cached ToggleClas s(INVALID_ CLASS + va lidationEr rorKey, is Valid ===  false);
  21716     }
  21717   }
  21718  
  21719   function i sObjectEmp ty(obj) {
  21720     if (obj)  {
  21721       for (v ar prop in  obj) {
  21722         retu rn false;
  21723       }
  21724     }
  21725     return t rue;
  21726   }
  21727  
  21728   /**
  21729    * @ngdoc  directive
  21730    * @name n gBind
  21731    * @restri ct AC
  21732    *
  21733    * @descri ption
  21734    * The `ng Bind` attr ibute tell s Angular  to replace  the text  content of  the speci fied HTML  element
  21735    * with th e value of  a given e xpression,  and to up date the t ext conten t when the  value of  that
  21736    * express ion change s.
  21737    *
  21738    * Typical ly, you do n't use `n gBind` dir ectly, but  instead y ou use the  double cu rly markup  like
  21739    * `{{ exp ression }} ` which is  similar b ut less ve rbose.
  21740    *
  21741    * It is p referable  to use `ng Bind` inst ead of `{{  expressio n }}` if a  template  is momenta rily
  21742    * display ed by the  browser in  its raw s tate befor e Angular  compiles i t. Since ` ngBind` is  an
  21743    * element  attribute , it makes  the bindi ngs invisi ble to the  user whil e the page  is loadin g.
  21744    *
  21745    * An alte rnative so lution to  this probl em would b e using th e
  21746    * {@link  ng.directi ve:ngCloak  ngCloak}  directive.
  21747    *
  21748    *
  21749    * @elemen t ANY
  21750    * @param  {expressio n} ngBind  {@link gui de/express ion Expres sion} to e valuate.
  21751    *
  21752    * @exampl e
  21753    * Enter a  name in t he Live Pr eview text  box; the  greeting b elow the t ext box ch anges inst antly.
  21754      <exampl e module=" bindExampl e">
  21755        <file  name="ind ex.html">
  21756          <sc ript>
  21757            a ngular.mod ule('bindE xample', [ ])
  21758               .controll er('Exampl eControlle r', ['$sco pe', funct ion($scope ) {
  21759                 $scope. name = 'Wh irled';
  21760               }]);
  21761          </s cript>
  21762          <di v ng-contr oller="Exa mpleContro ller">
  21763            E nter name:  <input ty pe="text"  ng-model=" name"><br>
  21764            H ello <span  ng-bind=" name"></sp an>!
  21765          </d iv>
  21766        </fil e>
  21767        <file  name="pro tractor.js " type="pr otractor">
  21768          it( 'should ch eck ng-bin d', functi on() {
  21769            v ar nameInp ut = eleme nt(by.mode l('name')) ;
  21770  
  21771            e xpect(elem ent(by.bin ding('name ')).getTex t()).toBe( 'Whirled') ;
  21772            n ameInput.c lear();
  21773            n ameInput.s endKeys('w orld');
  21774            e xpect(elem ent(by.bin ding('name ')).getTex t()).toBe( 'world');
  21775          });
  21776        </fil e>
  21777      </examp le>
  21778    */
  21779   var ngBind Directive  = ['$compi le', funct ion($compi le) {
  21780     return {
  21781       restri ct: 'AC',
  21782       compil e: functio n ngBindCo mpile(temp lateElemen t) {
  21783         $com pile.$$add BindingCla ss(templat eElement);
  21784         retu rn functio n ngBindLi nk(scope,  element, a ttr) {
  21785           $c ompile.$$a ddBindingI nfo(elemen t, attr.ng Bind);
  21786           el ement = el ement[0];
  21787           sc ope.$watch (attr.ngBi nd, functi on ngBindW atchAction (value) {
  21788              element.te xtContent  = value == = undefine d ? '' : v alue;
  21789           }) ;
  21790         };
  21791       }
  21792     };
  21793   }];
  21794  
  21795  
  21796   /**
  21797    * @ngdoc  directive
  21798    * @name n gBindTempl ate
  21799    *
  21800    * @descri ption
  21801    * The `ng BindTempla te` direct ive specif ies that t he element
  21802    * text co ntent shou ld be repl aced with  the interp olation of  the templ ate
  21803    * in the  `ngBindTem plate` att ribute.
  21804    * Unlike  `ngBind`,  the `ngBin dTemplate`  can conta in multipl e `{{` `}} `
  21805    * express ions. This  directive  is needed  since som e HTML ele ments
  21806    * (such a s TITLE an d OPTION)  cannot con tain SPAN  elements.
  21807    *
  21808    * @elemen t ANY
  21809    * @param  {string} n gBindTempl ate templa te of form
  21810    *   <tt>{ {</tt> <tt >expressio n</tt> <tt >}}</tt> t o eval.
  21811    *
  21812    * @exampl e
  21813    * Try it  here: ente r text in  text box a nd watch t he greetin g change.
  21814      <exampl e module=" bindExampl e">
  21815        <file  name="ind ex.html">
  21816          <sc ript>
  21817            a ngular.mod ule('bindE xample', [ ])
  21818               .controll er('Exampl eControlle r', ['$sco pe', funct ion($scope ) {
  21819                 $scope. salutation  = 'Hello' ;
  21820                 $scope. name = 'Wo rld';
  21821               }]);
  21822          </s cript>
  21823          <di v ng-contr oller="Exa mpleContro ller">
  21824           Sa lutation:  <input typ e="text" n g-model="s alutation" ><br>
  21825           Na me: <input  type="tex t" ng-mode l="name">< br>
  21826           <p re ng-bind -template= "{{salutat ion}} {{na me}}!"></p re>
  21827          </d iv>
  21828        </fil e>
  21829        <file  name="pro tractor.js " type="pr otractor">
  21830          it( 'should ch eck ng-bin d', functi on() {
  21831            v ar salutat ionElem =  element(by .binding(' salutation '));
  21832            v ar salutat ionInput =  element(b y.model('s alutation' ));
  21833            v ar nameInp ut = eleme nt(by.mode l('name')) ;
  21834  
  21835            e xpect(salu tationElem .getText() ).toBe('He llo World! ');
  21836  
  21837            s alutationI nput.clear ();
  21838            s alutationI nput.sendK eys('Greet ings');
  21839            n ameInput.c lear();
  21840            n ameInput.s endKeys('u ser');
  21841  
  21842            e xpect(salu tationElem .getText() ).toBe('Gr eetings us er!');
  21843          });
  21844        </fil e>
  21845      </examp le>
  21846    */
  21847   var ngBind TemplateDi rective =  ['$interpo late', '$c ompile', f unction($i nterpolate , $compile ) {
  21848     return {
  21849       compil e: functio n ngBindTe mplateComp ile(templa teElement)  {
  21850         $com pile.$$add BindingCla ss(templat eElement);
  21851         retu rn functio n ngBindTe mplateLink (scope, el ement, att r) {
  21852           va r interpol ateFn = $i nterpolate (element.a ttr(attr.$ attr.ngBin dTemplate) );
  21853           $c ompile.$$a ddBindingI nfo(elemen t, interpo lateFn.exp ressions);
  21854           el ement = el ement[0];
  21855           at tr.$observ e('ngBindT emplate',  function(v alue) {
  21856              element.te xtContent  = value == = undefine d ? '' : v alue;
  21857           }) ;
  21858         };
  21859       }
  21860     };
  21861   }];
  21862  
  21863  
  21864   /**
  21865    * @ngdoc  directive
  21866    * @name n gBindHtml
  21867    *
  21868    * @descri ption
  21869    * Evaluat es the exp ression an d inserts  the result ing HTML i nto the el ement in a  secure wa y. By defa ult,
  21870    * the res ulting HTM L content  will be sa nitized us ing the {@ link ngSan itize.$san itize $san itize} ser vice.
  21871    * To util ize this f unctionali ty, ensure  that `$sa nitize` is  available , for exam ple, by in cluding {@ link
  21872    * ngSanit ize} in yo ur module' s dependen cies (not  in core An gular). In  order to  use {@link  ngSanitiz e}
  21873    * in your  module's  dependenci es, you ne ed to incl ude "angul ar-sanitiz e.js" in y our applic ation.
  21874    *
  21875    * You may  also bypa ss sanitiz ation for  values you  know are  safe. To d o so, bind  to
  21876    * an expl icitly tru sted value  via {@lin k ng.$sce# trustAsHtm l $sce.tru stAsHtml}.   See the  example
  21877    * under { @link ng.$ sce#show-m e-an-examp le-using-s ce- Strict  Contextua l Escaping  (SCE)}.
  21878    *
  21879    * Note: I f a `$sani tize` serv ice is una vailable a nd the bou nd value i sn't expli citly trus ted, you
  21880    * will ha ve an exce ption (ins tead of an  exploit.)
  21881    *
  21882    * @elemen t ANY
  21883    * @param  {expressio n} ngBindH tml {@link  guide/exp ression Ex pression}  to evaluat e.
  21884    *
  21885    * @exampl e
  21886  
  21887      <exampl e module=" bindHtmlEx ample" dep s="angular -sanitize. js">
  21888        <file  name="ind ex.html">
  21889          <di v ng-contr oller="Exa mpleContro ller">
  21890           <p  ng-bind-h tml="myHTM L"></p>
  21891          </d iv>
  21892        </fil e>
  21893  
  21894        <file  name="scr ipt.js">
  21895          ang ular.modul e('bindHtm lExample',  ['ngSanit ize'])
  21896            . controller ('ExampleC ontroller' , ['$scope ', functio n($scope)  {
  21897               $scope.my HTML =
  21898                  'I am  an <code>H TML</code> string wit h ' +
  21899                  '<a hr ef="#">lin ks!</a> an d other <e m>stuff</e m>';
  21900            } ]);
  21901        </fil e>
  21902  
  21903        <file  name="pro tractor.js " type="pr otractor">
  21904          it( 'should ch eck ng-bin d-html', f unction()  {
  21905            e xpect(elem ent(by.bin ding('myHT ML')).getT ext()).toB e(
  21906                 'I am a n HTMLstri ng with li nks! and o ther stuff ');
  21907          });
  21908        </fil e>
  21909      </examp le>
  21910    */
  21911   var ngBind HtmlDirect ive = ['$s ce', '$par se', '$com pile', fun ction($sce , $parse,  $compile)  {
  21912     return {
  21913       restri ct: 'A',
  21914       compil e: functio n ngBindHt mlCompile( tElement,  tAttrs) {
  21915         var  ngBindHtml Getter = $ parse(tAtt rs.ngBindH tml);
  21916         var  ngBindHtml Watch = $p arse(tAttr s.ngBindHt ml, functi on getStri ngValue(va lue) {
  21917           re turn (valu e || '').t oString();
  21918         });
  21919         $com pile.$$add BindingCla ss(tElemen t);
  21920  
  21921         retu rn functio n ngBindHt mlLink(sco pe, elemen t, attr) {
  21922           $c ompile.$$a ddBindingI nfo(elemen t, attr.ng BindHtml);
  21923  
  21924           sc ope.$watch (ngBindHtm lWatch, fu nction ngB indHtmlWat chAction()  {
  21925              // we re-e valuate th e expr bec ause we wa nt a Trust edValueHol derType
  21926              // for $sc e, not a s tring
  21927              element.ht ml($sce.ge tTrustedHt ml(ngBindH tmlGetter( scope)) ||  '');
  21928           }) ;
  21929         };
  21930       }
  21931     };
  21932   }];
  21933  
  21934   function c lassDirect ive(name,  selector)  {
  21935     name = ' ngClass' +  name;
  21936     return [ '$animate' , function ($animate)  {
  21937       return  {
  21938         rest rict: 'AC' ,
  21939         link : function (scope, el ement, att r) {
  21940           va r oldVal;
  21941  
  21942           sc ope.$watch (attr[name ], ngClass WatchActio n, true);
  21943  
  21944           at tr.$observ e('class',  function( value) {
  21945              ngClassWat chAction(s cope.$eval (attr[name ]));
  21946           }) ;
  21947  
  21948  
  21949           if  (name !==  'ngClass' ) {
  21950              scope.$wat ch('$index ', functio n($index,  old$index)  {
  21951                // jshin t bitwise:  false
  21952                var mod  = $index &  1;
  21953                if (mod  !== (old$i ndex & 1))  {
  21954                  var cl asses = ar rayClasses (scope.$ev al(attr[na me]));
  21955                  mod == = selector  ?
  21956                    addC lasses(cla sses) :
  21957                    remo veClasses( classes);
  21958                }
  21959              });
  21960           }
  21961  
  21962           fu nction add Classes(cl asses) {
  21963              var newCla sses = dig estClassCo unts(class es, 1);
  21964              attr.$addC lass(newCl asses);
  21965           }
  21966  
  21967           fu nction rem oveClasses (classes)  {
  21968              var newCla sses = dig estClassCo unts(class es, -1);
  21969              attr.$remo veClass(ne wClasses);
  21970           }
  21971  
  21972           fu nction dig estClassCo unts(class es, count)  {
  21973              var classC ounts = el ement.data ('$classCo unts') ||  {};
  21974              var classe sToUpdate  = [];
  21975              forEach(cl asses, fun ction(clas sName) {
  21976                if (coun t > 0 || c lassCounts [className ]) {
  21977                  classC ounts[clas sName] = ( classCount s[classNam e] || 0) +  count;
  21978                  if (cl assCounts[ className]  === +(cou nt > 0)) {
  21979                    clas sesToUpdat e.push(cla ssName);
  21980                  }
  21981                }
  21982              });
  21983              element.da ta('$class Counts', c lassCounts );
  21984              return cla ssesToUpda te.join('  ');
  21985           }
  21986  
  21987           fu nction upd ateClasses (oldClasse s, newClas ses) {
  21988              var toAdd  = arrayDif ference(ne wClasses,  oldClasses );
  21989              var toRemo ve = array Difference (oldClasse s, newClas ses);
  21990              toAdd = di gestClassC ounts(toAd d, 1);
  21991              toRemove =  digestCla ssCounts(t oRemove, - 1);
  21992              if (toAdd  && toAdd.l ength) {
  21993                $animate .addClass( element, t oAdd);
  21994              }
  21995              if (toRemo ve && toRe move.lengt h) {
  21996                $animate .removeCla ss(element , toRemove );
  21997              }
  21998           }
  21999  
  22000           fu nction ngC lassWatchA ction(newV al) {
  22001              if (select or === tru e || scope .$index %  2 === sele ctor) {
  22002                var newC lasses = a rrayClasse s(newVal | | []);
  22003                if (!old Val) {
  22004                  addCla sses(newCl asses);
  22005                } else i f (!equals (newVal,ol dVal)) {
  22006                  var ol dClasses =  arrayClas ses(oldVal );
  22007                  update Classes(ol dClasses,  newClasses );
  22008                }
  22009              }
  22010              oldVal = s hallowCopy (newVal);
  22011           }
  22012         }
  22013       };
  22014  
  22015       functi on arrayDi fference(t okens1, to kens2) {
  22016         var  values = [ ];
  22017  
  22018         oute r:
  22019         for  (var i = 0 ; i < toke ns1.length ; i++) {
  22020           va r token =  tokens1[i] ;
  22021           fo r (var j =  0; j < to kens2.leng th; j++) {
  22022              if (token  == tokens2 [j]) conti nue outer;
  22023           }
  22024           va lues.push( token);
  22025         }
  22026         retu rn values;
  22027       }
  22028  
  22029       functi on arrayCl asses(clas sVal) {
  22030         if ( isArray(cl assVal)) {
  22031           re turn class Val;
  22032         } el se if (isS tring(clas sVal)) {
  22033           re turn class Val.split( ' ');
  22034         } el se if (isO bject(clas sVal)) {
  22035           va r classes  = [];
  22036           fo rEach(clas sVal, func tion(v, k)  {
  22037              if (v) {
  22038                classes  = classes. concat(k.s plit(' ')) ;
  22039              }
  22040           }) ;
  22041           re turn class es;
  22042         }
  22043         retu rn classVa l;
  22044       }
  22045     }];
  22046   }
  22047  
  22048   /**
  22049    * @ngdoc  directive
  22050    * @name n gClass
  22051    * @restri ct AC
  22052    *
  22053    * @descri ption
  22054    * The `ng Class` dir ective all ows you to  dynamical ly set CSS  classes o n an HTML  element by  databindi ng
  22055    * an expr ession tha t represen ts all cla sses to be  added.
  22056    *
  22057    * The dir ective ope rates in t hree diffe rent ways,  depending  on which  of three t ypes the e xpression
  22058    * evaluat es to:
  22059    *
  22060    * 1. If t he express ion evalua tes to a s tring, the  string sh ould be on e or more  space-deli mited clas s
  22061    * names.
  22062    *
  22063    * 2. If t he express ion evalua tes to an  array, eac h element  of the arr ay should  be a strin g that is
  22064    * one or  more space -delimited  class nam es.
  22065    *
  22066    * 3. If t he express ion evalua tes to an  object, th en for eac h key-valu e pair of  the
  22067    * object  with a tru thy value  the corres ponding ke y is used  as a class  name.
  22068    *
  22069    * The dir ective won 't add dup licate cla sses if a  particular  class was  already s et.
  22070    *
  22071    * When th e expressi on changes , the prev iously add ed classes  are remov ed and onl y then the
  22072    * new cla sses are a dded.
  22073    *
  22074    * @animat ions
  22075    * add - h appens jus t before t he class i s applied  to the ele ment
  22076    * remove  - happens  just befor e the clas s is remov ed from th e element
  22077    *
  22078    * @elemen t ANY
  22079    * @param  {expressio n} ngClass  {@link gu ide/expres sion Expre ssion} to  eval. The  result
  22080    *   of th e evaluati on can be  a string r epresentin g space de limited cl ass
  22081    *   names , an array , or a map  of class  names to b oolean val ues. In th e case of  a map, the
  22082    *   names  of the pr operties w hose value s are trut hy will be  added as  css classe s to the
  22083    *   eleme nt.
  22084    *
  22085    * @exampl e Example  that demon strates ba sic bindin gs via ngC lass direc tive.
  22086      <exampl e>
  22087        <file  name="ind ex.html">
  22088          <p  ng-class=" {strike: d eleted, bo ld: import ant, red:  error}">Ma p Syntax E xample</p>
  22089          <in put type=" checkbox"  ng-model=" deleted">  deleted (a pply "stri ke" class) <br>
  22090          <in put type=" checkbox"  ng-model=" important" > importan t (apply " bold" clas s)<br>
  22091          <in put type=" checkbox"  ng-model=" error"> er ror (apply  "red" cla ss)
  22092          <hr >
  22093          <p  ng-class=" style">Usi ng String  Syntax</p>
  22094          <in put type=" text" ng-m odel="styl e" placeho lder="Type : bold str ike red">
  22095          <hr >
  22096          <p  ng-class=" [style1, s tyle2, sty le3]">Usin g Array Sy ntax</p>
  22097          <in put ng-mod el="style1 " placehol der="Type:  bold, str ike or red "><br>
  22098          <in put ng-mod el="style2 " placehol der="Type:  bold, str ike or red "><br>
  22099          <in put ng-mod el="style3 " placehol der="Type:  bold, str ike or red "><br>
  22100        </fil e>
  22101        <file  name="sty le.css">
  22102          .st rike {
  22103            t ext-decora tion: line -through;
  22104          }
  22105          .bo ld {
  22106               font-weig ht: bold;
  22107          }
  22108          .re d {
  22109               color: re d;
  22110          }
  22111        </fil e>
  22112        <file  name="pro tractor.js " type="pr otractor">
  22113          var  ps = elem ent.all(by .css('p')) ;
  22114  
  22115          it( 'should le t you togg le the cla ss', funct ion() {
  22116  
  22117            e xpect(ps.f irst().get Attribute( 'class')). not.toMatc h(/bold/);
  22118            e xpect(ps.f irst().get Attribute( 'class')). not.toMatc h(/red/);
  22119  
  22120            e lement(by. model('imp ortant')). click();
  22121            e xpect(ps.f irst().get Attribute( 'class')). toMatch(/b old/);
  22122  
  22123            e lement(by. model('err or')).clic k();
  22124            e xpect(ps.f irst().get Attribute( 'class')). toMatch(/r ed/);
  22125          });
  22126  
  22127          it( 'should le t you togg le string  example',  function()  {
  22128            e xpect(ps.g et(1).getA ttribute(' class')).t oBe('');
  22129            e lement(by. model('sty le')).clea r();
  22130            e lement(by. model('sty le')).send Keys('red' );
  22131            e xpect(ps.g et(1).getA ttribute(' class')).t oBe('red') ;
  22132          });
  22133  
  22134          it( 'array exa mple shoul d have 3 c lasses', f unction()  {
  22135            e xpect(ps.l ast().getA ttribute(' class')).t oBe('');
  22136            e lement(by. model('sty le1')).sen dKeys('bol d');
  22137            e lement(by. model('sty le2')).sen dKeys('str ike');
  22138            e lement(by. model('sty le3')).sen dKeys('red ');
  22139            e xpect(ps.l ast().getA ttribute(' class')).t oBe('bold  strike red ');
  22140          });
  22141        </fil e>
  22142      </examp le>
  22143  
  22144      ## Anim ations
  22145  
  22146      The exa mple below  demonstra tes how to  perform a nimations  using ngCl ass.
  22147  
  22148      <exampl e module=" ngAnimate"  deps="ang ular-anima te.js" ani mations="t rue">
  22149        <file  name="ind ex.html">
  22150         <inp ut id="set btn" type= "button" v alue="set"  ng-click= "myVar='my -class'">
  22151         <inp ut id="cle arbtn" typ e="button"  value="cl ear" ng-cl ick="myVar =''">
  22152         <br>
  22153         <spa n class="b ase-class"  ng-class= "myVar">Sa mple Text< /span>
  22154        </fil e>
  22155        <file  name="sty le.css">
  22156          .ba se-class {
  22157            - webkit-tra nsition:al l cubic-be zier(0.250 , 0.460, 0 .450, 0.94 0) 0.5s;
  22158            t ransition: all cubic- bezier(0.2 50, 0.460,  0.450, 0. 940) 0.5s;
  22159          }
  22160  
  22161          .ba se-class.m y-class {
  22162            c olor: red;
  22163            f ont-size:3 em;
  22164          }
  22165        </fil e>
  22166        <file  name="pro tractor.js " type="pr otractor">
  22167          it( 'should ch eck ng-cla ss', funct ion() {
  22168            e xpect(elem ent(by.css ('.base-cl ass')).get Attribute( 'class')). not.
  22169               toMatch(/ my-class/) ;
  22170  
  22171            e lement(by. id('setbtn ')).click( );
  22172  
  22173            e xpect(elem ent(by.css ('.base-cl ass')).get Attribute( 'class')).
  22174               toMatch(/ my-class/) ;
  22175  
  22176            e lement(by. id('clearb tn')).clic k();
  22177  
  22178            e xpect(elem ent(by.css ('.base-cl ass')).get Attribute( 'class')). not.
  22179               toMatch(/ my-class/) ;
  22180          });
  22181        </fil e>
  22182      </examp le>
  22183  
  22184  
  22185      ## ngCl ass and pr e-existing  CSS3 Tran sitions/An imations
  22186      The ngC lass direc tive still  supports  CSS3 Trans itions/Ani mations ev en if they  do not fo llow the n gAnimate C SS naming  structure.
  22187      Upon an imation ng Animate wi ll apply s upplementa ry CSS cla sses to tr ack the st art and en d of an an imation, b ut this wi ll not hin der
  22188      any pre -existing  CSS transi tions alre ady on the  element.  To get an  idea of wh at happens  during a  class-base d animatio n, be sure
  22189      to view  the step  by step de tails of { @link ng.$ animate#ad dClass $an imate.addC lass} and
  22190      {@link  ng.$animat e#removeCl ass $anima te.removeC lass}.
  22191    */
  22192   var ngClas sDirective  = classDi rective('' , true);
  22193  
  22194   /**
  22195    * @ngdoc  directive
  22196    * @name n gClassOdd
  22197    * @restri ct AC
  22198    *
  22199    * @descri ption
  22200    * The `ng ClassOdd`  and `ngCla ssEven` di rectives w ork exactl y as
  22201    * {@link  ng.directi ve:ngClass  ngClass},  except th ey work in
  22202    * conjunc tion with  `ngRepeat`  and take  effect onl y on odd ( even) rows .
  22203    *
  22204    * This di rective ca n be appli ed only wi thin the s cope of an
  22205    * {@link  ng.directi ve:ngRepea t ngRepeat }.
  22206    *
  22207    * @elemen t ANY
  22208    * @param  {expressio n} ngClass Odd {@link  guide/exp ression Ex pression}  to eval. T he result
  22209    *   of th e evaluati on can be  a string r epresentin g space de limited cl ass names  or an arra y.
  22210    *
  22211    * @exampl e
  22212      <exampl e>
  22213        <file  name="ind ex.html">
  22214           <o l ng-init= "names=['J ohn', 'Mar y', 'Cate' , 'Suz']">
  22215              <li ng-rep eat="name  in names">
  22216               <span ng- class-odd= "'odd'" ng -class-eve n="'even'" >
  22217                 {{name} }
  22218               </span>
  22219              </li>
  22220           </ ol>
  22221        </fil e>
  22222        <file  name="sty le.css">
  22223          .od d {
  22224            c olor: red;
  22225          }
  22226          .ev en {
  22227            c olor: blue ;
  22228          }
  22229        </fil e>
  22230        <file  name="pro tractor.js " type="pr otractor">
  22231          it( 'should ch eck ng-cla ss-odd and  ng-class- even', fun ction() {
  22232            e xpect(elem ent(by.rep eater('nam e in names ').row(0). column('na me')).getA ttribute(' class')).
  22233               toMatch(/ odd/);
  22234            e xpect(elem ent(by.rep eater('nam e in names ').row(1). column('na me')).getA ttribute(' class')).
  22235               toMatch(/ even/);
  22236          });
  22237        </fil e>
  22238      </examp le>
  22239    */
  22240   var ngClas sOddDirect ive = clas sDirective ('Odd', 0) ;
  22241  
  22242   /**
  22243    * @ngdoc  directive
  22244    * @name n gClassEven
  22245    * @restri ct AC
  22246    *
  22247    * @descri ption
  22248    * The `ng ClassOdd`  and `ngCla ssEven` di rectives w ork exactl y as
  22249    * {@link  ng.directi ve:ngClass  ngClass},  except th ey work in
  22250    * conjunc tion with  `ngRepeat`  and take  effect onl y on odd ( even) rows .
  22251    *
  22252    * This di rective ca n be appli ed only wi thin the s cope of an
  22253    * {@link  ng.directi ve:ngRepea t ngRepeat }.
  22254    *
  22255    * @elemen t ANY
  22256    * @param  {expressio n} ngClass Even {@lin k guide/ex pression E xpression}  to eval.  The
  22257    *   resul t of the e valuation  can be a s tring repr esenting s pace delim ited class  names or  an array.
  22258    *
  22259    * @exampl e
  22260      <exampl e>
  22261        <file  name="ind ex.html">
  22262           <o l ng-init= "names=['J ohn', 'Mar y', 'Cate' , 'Suz']">
  22263              <li ng-rep eat="name  in names">
  22264               <span ng- class-odd= "'odd'" ng -class-eve n="'even'" >
  22265                 {{name} } &nbsp; & nbsp; &nbs p;
  22266               </span>
  22267              </li>
  22268           </ ol>
  22269        </fil e>
  22270        <file  name="sty le.css">
  22271          .od d {
  22272            c olor: red;
  22273          }
  22274          .ev en {
  22275            c olor: blue ;
  22276          }
  22277        </fil e>
  22278        <file  name="pro tractor.js " type="pr otractor">
  22279          it( 'should ch eck ng-cla ss-odd and  ng-class- even', fun ction() {
  22280            e xpect(elem ent(by.rep eater('nam e in names ').row(0). column('na me')).getA ttribute(' class')).
  22281               toMatch(/ odd/);
  22282            e xpect(elem ent(by.rep eater('nam e in names ').row(1). column('na me')).getA ttribute(' class')).
  22283               toMatch(/ even/);
  22284          });
  22285        </fil e>
  22286      </examp le>
  22287    */
  22288   var ngClas sEvenDirec tive = cla ssDirectiv e('Even',  1);
  22289  
  22290   /**
  22291    * @ngdoc  directive
  22292    * @name n gCloak
  22293    * @restri ct AC
  22294    *
  22295    * @descri ption
  22296    * The `ng Cloak` dir ective is  used to pr event the  Angular ht ml templat e from bei ng briefly
  22297    * display ed by the  browser in  its raw ( uncompiled ) form whi le your ap plication  is loading . Use this
  22298    * directi ve to avoi d the unde sirable fl icker effe ct caused  by the htm l template  display.
  22299    *
  22300    * The dir ective can  be applie d to the ` <body>` el ement, but  the prefe rred usage  is to app ly
  22301    * multipl e `ngCloak ` directiv es to smal l portions  of the pa ge to perm it progres sive rende ring
  22302    * of the  browser vi ew.
  22303    *
  22304    * `ngCloa k` works i n cooperat ion with t he followi ng css rul e embedded  within `a ngular.js`  and
  22305    * `angula r.min.js`.
  22306    * For CSP  mode plea se add `an gular-csp. css` to yo ur html fi le (see {@ link ng.di rective:ng Csp ngCsp} ).
  22307    *
  22308    * ```css
  22309    * [ng\:cl oak], [ng- cloak], [d ata-ng-clo ak], [x-ng -cloak], . ng-cloak,  .x-ng-cloa k {
  22310    *   displ ay: none ! important;
  22311    * }
  22312    * ```
  22313    *
  22314    * When th is css rul e is loade d by the b rowser, al l html ele ments (inc luding the ir childre n) that
  22315    * are tag ged with t he `ngCloa k` directi ve are hid den. When  Angular en counters t his direct ive
  22316    * during  the compil ation of t he templat e it delet es the `ng Cloak` ele ment attri bute, maki ng
  22317    * the com piled elem ent visibl e.
  22318    *
  22319    * For the  best resu lt, the `a ngular.js`  script mu st be load ed in the  head secti on of the  html
  22320    * documen t; alterna tively, th e css rule  above mus t be inclu ded in the  external  stylesheet  of the
  22321    * applica tion.
  22322    *
  22323    * Legacy  browsers,  like IE7,  do not pro vide attri bute selec tor suppor t (added i n CSS 2.1)  so they
  22324    * cannot  match the  `[ng\:cloa k]` select or. To wor k around t his limita tion, you  must add t he css
  22325    * class ` ng-cloak`  in additio n to the ` ngCloak` d irective a s shown in  the examp le below.
  22326    *
  22327    * @elemen t ANY
  22328    *
  22329    * @exampl e
  22330      <exampl e>
  22331        <file  name="ind ex.html">
  22332           <d iv id="tem plate1" ng -cloak>{{  'hello' }} </div>
  22333           <d iv id="tem plate2" ng -cloak cla ss="ng-clo ak">{{ 'he llo IE7' } }</div>
  22334        </fil e>
  22335        <file  name="pro tractor.js " type="pr otractor">
  22336          it( 'should re move the t emplate di rective an d css clas s', functi on() {
  22337            e xpect($('# template1' ).getAttri bute('ng-c loak')).
  22338               toBeNull( );
  22339            e xpect($('# template2' ).getAttri bute('ng-c loak')).
  22340               toBeNull( );
  22341          });
  22342        </fil e>
  22343      </examp le>
  22344    *
  22345    */
  22346   var ngCloa kDirective  = ngDirec tive({
  22347     compile:  function( element, a ttr) {
  22348       attr.$ set('ngClo ak', undef ined);
  22349       elemen t.removeCl ass('ng-cl oak');
  22350     }
  22351   });
  22352  
  22353   /**
  22354    * @ngdoc  directive
  22355    * @name n gControlle r
  22356    *
  22357    * @descri ption
  22358    * The `ng Controller ` directiv e attaches  a control ler class  to the vie w. This is  a key asp ect of how  angular
  22359    * support s the prin ciples beh ind the Mo del-View-C ontroller  design pat tern.
  22360    *
  22361    * MVC com ponents in  angular:
  22362    *
  22363    * * Model  â€” Model s are the  properties  of a scop e; scopes  are attach ed to the  DOM where  scope prop erties
  22364    *   are a ccessed th rough bind ings.
  22365    * * View  — The te mplate (HT ML with da ta binding s) that is  rendered  into the V iew.
  22366    * * Contr oller â€”  The `ngCon troller` d irective s pecifies a  Controlle r class; t he class c ontains bu siness
  22367    *   logic  behind th e applicat ion to dec orate the  scope with  functions  and value s
  22368    *
  22369    * Note th at you can  also atta ch control lers to th e DOM by d eclaring i t in a rou te definit ion
  22370    * via the  {@link ng Route.$rou te $route}  service.  A common m istake is  to declare  the contr oller
  22371    * again u sing `ng-c ontroller`  in the te mplate its elf.  This  will caus e the cont roller to  be attache d
  22372    * and exe cuted twic e.
  22373    *
  22374    * @elemen t ANY
  22375    * @scope
  22376    * @priori ty 500
  22377    * @param  {expressio n} ngContr oller Name  of a cons tructor fu nction reg istered wi th the cur rent
  22378    * {@link  ng.$contro llerProvid er $contro llerProvid er} or an  {@link gui de/express ion expres sion}
  22379    * that on  the curre nt scope e valuates t o a constr uctor func tion.
  22380    *
  22381    * The con troller in stance can  be publis hed into a  scope pro perty by s pecifying
  22382    * `ng-con troller="a s property Name"`.
  22383    *
  22384    * If the  current `$ controller Provider`  is configu red to use  globals ( via
  22385    * {@link  ng.$contro llerProvid er#allowGl obals `$co ntrollerPr ovider.all owGlobals( )` }), thi s may
  22386    * also be  the name  of a globa lly access ible const ructor fun ction (not  recommend ed).
  22387    *
  22388    * @exampl e
  22389    * Here is  a simple  form for e diting use r contact  informatio n. Adding,  removing,  clearing,  and
  22390    * greetin g are meth ods declar ed on the  controller  (see sour ce tab). T hese metho ds can
  22391    * easily  be called  from the a ngular mar kup. Any c hanges to  the data a re automat ically ref lected
  22392    * in the  View witho ut the nee d for a ma nual updat e.
  22393    *
  22394    * Two dif ferent dec laration s tyles are  included b elow:
  22395    *
  22396    * * one b inds metho ds and pro perties di rectly ont o the cont roller usi ng `this`:
  22397    * `ng-con troller="S ettingsCon troller1 a s settings "`
  22398    * * one i njects `$s cope` into  the contr oller:
  22399    * `ng-con troller="S ettingsCon troller2"`
  22400    *
  22401    * The sec ond option  is more c ommon in t he Angular  community , and is g enerally u sed in boi lerplates
  22402    * and in  this guide . However,  there are  advantage s to bindi ng propert ies direct ly to the  controller
  22403    * and avo iding scop e.
  22404    *
  22405    * * Using  `controll er as` mak es it obvi ous which  controller  you are a ccessing i n the temp late when
  22406    * multipl e controll ers apply  to an elem ent.
  22407    * * If yo u are writ ing your c ontrollers  as classe s you have  easier ac cess to th e properti es and
  22408    * methods , which wi ll appear  on the sco pe, from i nside the  controller  code.
  22409    * * Since  there is  always a ` .` in the  bindings,  you don't  have to wo rry about  prototypal
  22410    * inherit ance maski ng primiti ves.
  22411    *
  22412    * This ex ample demo nstrates t he `contro ller as` s yntax.
  22413    *
  22414    * <exampl e name="ng Controller As" module ="controll erAsExampl e">
  22415    *   <file  name="ind ex.html">
  22416    *    <div  id="ctrl- as-exmpl"  ng-control ler="Setti ngsControl ler1 as se ttings">
  22417    *      Na me: <input  type="tex t" ng-mode l="setting s.name"/>
  22418    *      [  <a href=""  ng-click= "settings. greet()">g reet</a> ] <br/>
  22419    *      Co ntact:
  22420    *      <u l>
  22421    *         <li ng-rep eat="conta ct in sett ings.conta cts">
  22422    *           <select  ng-model=" contact.ty pe">
  22423    *              <opti on>phone</ option>
  22424    *              <opti on>email</ option>
  22425    *           </select >
  22426    *           <input t ype="text"  ng-model= "contact.v alue"/>
  22427    *           [ <a hre f="" ng-cl ick="setti ngs.clearC ontact(con tact)">cle ar</a>
  22428    *           | <a hre f="" ng-cl ick="setti ngs.remove Contact(co ntact)">X< /a> ]
  22429    *         </li>
  22430    *         <li>[ <a h ref="" ng- click="set tings.addC ontact()"> add</a> ]< /li>
  22431    *     </u l>
  22432    *    </di v>
  22433    *   </fil e>
  22434    *   <file  name="app .js">
  22435    *    angu lar.module ('controll erAsExampl e', [])
  22436    *      .c ontroller( 'SettingsC ontroller1 ', Setting sControlle r1);
  22437    *
  22438    *    func tion Setti ngsControl ler1() {
  22439    *      th is.name =  "John Smit h";
  22440    *      th is.contact s = [
  22441    *         {type: 'ph one', valu e: '408 55 5 1212'},
  22442    *         {type: 'em ail', valu e: 'john.s mith@examp le.org'} ] ;
  22443    *    }
  22444    *
  22445    *    Sett ingsContro ller1.prot otype.gree t = functi on() {
  22446    *      al ert(this.n ame);
  22447    *    };
  22448    *
  22449    *    Sett ingsContro ller1.prot otype.addC ontact = f unction()  {
  22450    *      th is.contact s.push({ty pe: 'email ', value:  'yourname@ example.or g'});
  22451    *    };
  22452    *
  22453    *    Sett ingsContro ller1.prot otype.remo veContact  = function (contactTo Remove) {
  22454    *     var  index = t his.contac ts.indexOf (contactTo Remove);
  22455    *      th is.contact s.splice(i ndex, 1);
  22456    *    };
  22457    *
  22458    *    Sett ingsContro ller1.prot otype.clea rContact =  function( contact) {
  22459    *      co ntact.type  = 'phone' ;
  22460    *      co ntact.valu e = '';
  22461    *    };
  22462    *   </fil e>
  22463    *   <file  name="pro tractor.js " type="pr otractor">
  22464    *     it( 'should ch eck contro ller as',  function()  {
  22465    *       v ar contain er = eleme nt(by.id(' ctrl-as-ex mpl'));
  22466    *          expect(co ntainer.el ement(by.m odel('sett ings.name' ))
  22467    *            .getAtt ribute('va lue')).toB e('John Sm ith');
  22468    *
  22469    *       v ar firstRe peat =
  22470    *            contain er.element (by.repeat er('contac t in setti ngs.contac ts').row(0 ));
  22471    *       v ar secondR epeat =
  22472    *            contain er.element (by.repeat er('contac t in setti ngs.contac ts').row(1 ));
  22473    *
  22474    *       e xpect(firs tRepeat.el ement(by.m odel('cont act.value' )).getAttr ibute('val ue'))
  22475    *            .toBe(' 408 555 12 12');
  22476    *
  22477    *       e xpect(seco ndRepeat.e lement(by. model('con tact.value ')).getAtt ribute('va lue'))
  22478    *            .toBe(' john.smith @example.o rg');
  22479    *
  22480    *       f irstRepeat .element(b y.linkText ('clear')) .click();
  22481    *
  22482    *       e xpect(firs tRepeat.el ement(by.m odel('cont act.value' )).getAttr ibute('val ue'))
  22483    *            .toBe(' ');
  22484    *
  22485    *       c ontainer.e lement(by. linkText(' add')).cli ck();
  22486    *
  22487    *       e xpect(cont ainer.elem ent(by.rep eater('con tact in se ttings.con tacts').ro w(2))
  22488    *            .elemen t(by.model ('contact. value'))
  22489    *            .getAtt ribute('va lue'))
  22490    *            .toBe(' yourname@e xample.org ');
  22491    *     });
  22492    *   </fil e>
  22493    * </examp le>
  22494    *
  22495    * This ex ample demo nstrates t he "attach  to `$scop e`" style  of control ler.
  22496    *
  22497    * <exampl e name="ng Controller " module=" controller Example">
  22498    *  <file  name="inde x.html">
  22499    *   <div  id="ctrl-e xmpl" ng-c ontroller= "SettingsC ontroller2 ">
  22500    *     Nam e: <input  type="text " ng-model ="name"/>
  22501    *     [ < a href=""  ng-click=" greet()">g reet</a> ] <br/>
  22502    *     Con tact:
  22503    *     <ul >
  22504    *       < li ng-repe at="contac t in conta cts">
  22505    *          <select n g-model="c ontact.typ e">
  22506    *             <optio n>phone</o ption>
  22507    *             <optio n>email</o ption>
  22508    *          </select>
  22509    *          <input ty pe="text"  ng-model=" contact.va lue"/>
  22510    *          [ <a href ="" ng-cli ck="clearC ontact(con tact)">cle ar</a>
  22511    *          | <a href ="" ng-cli ck="remove Contact(co ntact)">X< /a> ]
  22512    *       < /li>
  22513    *       < li>[ <a hr ef="" ng-c lick="addC ontact()"> add</a> ]< /li>
  22514    *    </ul >
  22515    *   </div >
  22516    *  </file >
  22517    *  <file  name="app. js">
  22518    *   angul ar.module( 'controlle rExample',  [])
  22519    *     .co ntroller(' SettingsCo ntroller2' , ['$scope ', Setting sControlle r2]);
  22520    *
  22521    *   funct ion Settin gsControll er2($scope ) {
  22522    *     $sc ope.name =  "John Smi th";
  22523    *     $sc ope.contac ts = [
  22524    *       { type:'phon e', value: '408 555 1 212'},
  22525    *       { type:'emai l', value: 'john.smit h@example. org'} ];
  22526    *
  22527    *     $sc ope.greet  = function () {
  22528    *       a lert($scop e.name);
  22529    *     };
  22530    *
  22531    *     $sc ope.addCon tact = fun ction() {
  22532    *       $ scope.cont acts.push( {type:'ema il', value :'yourname @example.o rg'});
  22533    *     };
  22534    *
  22535    *     $sc ope.remove Contact =  function(c ontactToRe move) {
  22536    *       v ar index =  $scope.co ntacts.ind exOf(conta ctToRemove );
  22537    *       $ scope.cont acts.splic e(index, 1 );
  22538    *     };
  22539    *
  22540    *     $sc ope.clearC ontact = f unction(co ntact) {
  22541    *       c ontact.typ e = 'phone ';
  22542    *       c ontact.val ue = '';
  22543    *     };
  22544    *   }
  22545    *  </file >
  22546    *  <file  name="prot ractor.js"  type="pro tractor">
  22547    *    it(' should che ck control ler', func tion() {
  22548    *      va r containe r = elemen t(by.id('c trl-exmpl' ));
  22549    *
  22550    *      ex pect(conta iner.eleme nt(by.mode l('name'))
  22551    *           .getAttr ibute('val ue')).toBe ('John Smi th');
  22552    *
  22553    *      va r firstRep eat =
  22554    *           containe r.element( by.repeate r('contact  in contac ts').row(0 ));
  22555    *      va r secondRe peat =
  22556    *           containe r.element( by.repeate r('contact  in contac ts').row(1 ));
  22557    *
  22558    *      ex pect(first Repeat.ele ment(by.mo del('conta ct.value') ).getAttri bute('valu e'))
  22559    *           .toBe('4 08 555 121 2');
  22560    *      ex pect(secon dRepeat.el ement(by.m odel('cont act.value' )).getAttr ibute('val ue'))
  22561    *           .toBe('j ohn.smith@ example.or g');
  22562    *
  22563    *      fi rstRepeat. element(by .linkText( 'clear')). click();
  22564    *
  22565    *      ex pect(first Repeat.ele ment(by.mo del('conta ct.value') ).getAttri bute('valu e'))
  22566    *           .toBe('' );
  22567    *
  22568    *      co ntainer.el ement(by.l inkText('a dd')).clic k();
  22569    *
  22570    *      ex pect(conta iner.eleme nt(by.repe ater('cont act in con tacts').ro w(2))
  22571    *           .element (by.model( 'contact.v alue'))
  22572    *           .getAttr ibute('val ue'))
  22573    *           .toBe('y ourname@ex ample.org' );
  22574    *    });
  22575    *  </file >
  22576    *</exampl e>
  22577  
  22578    */
  22579   var ngCont rollerDire ctive = [f unction()  {
  22580     return {
  22581       restri ct: 'A',
  22582       scope:  true,
  22583       contro ller: '@',
  22584       priori ty: 500
  22585     };
  22586   }];
  22587  
  22588   /**
  22589    * @ngdoc  directive
  22590    * @name n gCsp
  22591    *
  22592    * @elemen t html
  22593    * @descri ption
  22594    * Enables  [CSP (Con tent Secur ity Policy )](https:/ /developer .mozilla.o rg/en/Secu rity/CSP)  support.
  22595    *
  22596    * This is  necessary  when deve loping thi ngs like G oogle Chro me Extensi ons or Uni versal Win dows Apps.
  22597    *
  22598    * CSP for bids apps  to use `ev al` or `Fu nction(str ing)` gene rated func tions (amo ng other t hings).
  22599    * For Ang ular to be  CSP compa tible ther e are only  two thing s that we  need to do  different ly:
  22600    *
  22601    * - don't  use `Func tion` cons tructor to  generate  optimized  value gett ers
  22602    * - don't  inject cu stom style sheet into  the docum ent
  22603    *
  22604    * Angular JS uses `F unction(st ring)` gen erated fun ctions as  a speed op timization . Applying  the `ngCs p`
  22605    * directi ve will ca use Angula r to use C SP compati bility mod e. When th is mode is  on Angula rJS will
  22606    * evaluat e all expr essions up  to 30% sl ower than  in non-CSP  mode, but  no securi ty violati ons will
  22607    * be rais ed.
  22608    *
  22609    * CSP for bids JavaS cript to i nline styl esheet rul es. In non  CSP mode  Angular au tomaticall y
  22610    * include s some CSS  rules (e. g. {@link  ng.directi ve:ngCloak  ngCloak}) .
  22611    * To make  those dir ectives wo rk in CSP  mode, incl ude the `a ngular-csp .css` manu ally.
  22612    *
  22613    * Angular  tries to  autodetect  if CSP is  active an d automati cally turn  on the CS P-safe mod e. This
  22614    * autodet ection how ever trigg ers a CSP  error to b e logged i n the cons ole:
  22615    *
  22616    * ```
  22617    * Refused  to evalua te a strin g as JavaS cript beca use 'unsaf e-eval' is  not an al lowed sour ce of
  22618    * script  in the fol lowing Con tent Secur ity Policy  directive : "default -src 'self '". Note t hat
  22619    * 'script -src' was  not explic itly set,  so 'defaul t-src' is  used as a  fallback.
  22620    * ```
  22621    *
  22622    * This er ror is har mless but  annoying.  To prevent  the error  from show ing up, pu t the `ngC sp`
  22623    * directi ve on the  root eleme nt of the  applicatio n or on th e `angular .js` scrip t tag, whi chever
  22624    * appears  first in  the html d ocument.
  22625    *
  22626    * *Note:  This direc tive is on ly availab le in the  `ng-csp` a nd `data-n g-csp` att ribute for m.*
  22627    *
  22628    * @exampl e
  22629    * This ex ample show s how to a pply the ` ngCsp` dir ective to  the `html`  tag.
  22630      ```html
  22631        <!doc type html>
  22632        <html  ng-app ng -csp>
  22633        ...
  22634        ...
  22635        </htm l>
  22636      ```
  22637     * @examp le
  22638         // N ote: the s uffix `.cs p` in the  example na me trigger s
  22639         // c sp mode in  our http  server!
  22640         <exa mple name= "example.c sp" module ="cspExamp le" ng-csp ="true">
  22641           <f ile name=" index.html ">
  22642              <div ng-co ntroller=" MainContro ller as ct rl">
  22643                <div>
  22644                  <butto n ng-click ="ctrl.inc ()" id="in c">Increme nt</button >
  22645                  <span  id="counte r">
  22646                    {{ct rl.counter }}
  22647                  </span >
  22648                </div>
  22649  
  22650                <div>
  22651                  <butto n ng-click ="ctrl.evi l()" id="e vil">Evil< /button>
  22652                  <span  id="evilEr ror">
  22653                    {{ct rl.evilErr or}}
  22654                  </span >
  22655                </div>
  22656              </div>
  22657           </ file>
  22658           <f ile name=" script.js" >
  22659               angular.m odule('csp Example',  [])
  22660                 .contro ller('Main Controller ', functio n() {
  22661                    this .counter =  0;
  22662                    this .inc = fun ction() {
  22663                      th is.counter ++;
  22664                    };
  22665                    this .evil = fu nction() {
  22666                      //  jshint ev il:true
  22667                      tr y {
  22668                         eval('1+2' );
  22669                      }  catch (e)  {
  22670                         this.evilE rror = e.m essage;
  22671                      }
  22672                    };
  22673                  });
  22674           </ file>
  22675           <f ile name=" protractor .js" type= "protracto r">
  22676              var util,  webdriver;
  22677  
  22678              var incBtn  = element (by.id('in c'));
  22679              var counte r = elemen t(by.id('c ounter'));
  22680              var evilBt n = elemen t(by.id('e vil'));
  22681              var evilEr ror = elem ent(by.id( 'evilError '));
  22682  
  22683              function g etAndClear SevereErro rs() {
  22684                return b rowser.man age().logs ().get('br owser').th en(functio n(browserL og) {
  22685                  return  browserLo g.filter(f unction(lo gEntry) {
  22686                    retu rn logEntr y.level.va lue > webd river.logg ing.Level. WARNING.va lue;
  22687                  });
  22688                });
  22689              }
  22690  
  22691              function c learErrors () {
  22692                getAndCl earSevereE rrors();
  22693              }
  22694  
  22695              function e xpectNoErr ors() {
  22696                getAndCl earSevereE rrors().th en(functio n(filtered Log) {
  22697                  expect (filteredL og.length) .toEqual(0 );
  22698                  if (fi lteredLog. length) {
  22699                    cons ole.log('b rowser con sole error s: ' + uti l.inspect( filteredLo g));
  22700                  }
  22701                });
  22702              }
  22703  
  22704              function e xpectError (regex) {
  22705                getAndCl earSevereE rrors().th en(functio n(filtered Log) {
  22706                  var fo und = fals e;
  22707                  filter edLog.forE ach(functi on(log) {
  22708                    if ( log.messag e.match(re gex)) {
  22709                      fo und = true ;
  22710                    }
  22711                  });
  22712                  if (!f ound) {
  22713                    thro w new Erro r('expecte d an error  that matc hes ' + re gex);
  22714                  }
  22715                });
  22716              }
  22717  
  22718              beforeEach (function( ) {
  22719                util = r equire('ut il');
  22720                webdrive r = requir e('protrac tor/node_m odules/sel enium-webd river');
  22721              });
  22722  
  22723              // For now , we only  test on Ch rome,
  22724              // as Safa ri does no t load the  page with  Protracto r's inject ed scripts ,
  22725              // and Fir efox webdr iver alway s disables  content s ecurity po licy (#635 8)
  22726              if (browse r.params.b rowser !==  'chrome')  {
  22727                return;
  22728              }
  22729  
  22730              it('should  not repor t errors w hen the pa ge is load ed', funct ion() {
  22731                // clear  errors so  we are no t dependen t on previ ous tests
  22732                clearErr ors();
  22733                // Need  to reload  the page a s the page  is alread y loaded w hen
  22734                // we co me here
  22735                browser. driver.get CurrentUrl ().then(fu nction(url ) {
  22736                  browse r.get(url) ;
  22737                });
  22738                expectNo Errors();
  22739              });
  22740  
  22741              it('should  evaluate  expression s', functi on() {
  22742                expect(c ounter.get Text()).to Equal('0') ;
  22743                incBtn.c lick();
  22744                expect(c ounter.get Text()).to Equal('1') ;
  22745                expectNo Errors();
  22746              });
  22747  
  22748              it('should  throw and  report an  error whe n using "e val"', fun ction() {
  22749                evilBtn. click();
  22750                expect(e vilError.g etText()). toMatch(/C ontent Sec urity Poli cy/);
  22751                expectEr ror(/Conte nt Securit y Policy/) ;
  22752              });
  22753           </ file>
  22754         </ex ample>
  22755     */
  22756  
  22757   // ngCsp i s not impl emented as  a proper  directive  any more,  because we  need it b e processe d while we
  22758   // bootstr ap the sys tem (befor e $parse i s instanti ated), for  this reas on we just  have
  22759   // the csp .isActive( ) fn that  looks for  ng-csp att ribute any where in t he current  doc
  22760  
  22761   /**
  22762    * @ngdoc  directive
  22763    * @name n gClick
  22764    *
  22765    * @descri ption
  22766    * The ngC lick direc tive allow s you to s pecify cus tom behavi or when
  22767    * an elem ent is cli cked.
  22768    *
  22769    * @elemen t ANY
  22770    * @priori ty 0
  22771    * @param  {expressio n} ngClick  {@link gu ide/expres sion Expre ssion} to  evaluate u pon
  22772    * click.  ({@link gu ide/expres sion#-even t- Event o bject is a vailable a s `$event` })
  22773    *
  22774    * @exampl e
  22775      <exampl e>
  22776        <file  name="ind ex.html">
  22777         <but ton ng-cli ck="count  = count +  1" ng-init ="count=0" >
  22778           In crement
  22779         </bu tton>
  22780         <spa n>
  22781           co unt: {{cou nt}}
  22782         </sp an>
  22783        </fil e>
  22784        <file  name="pro tractor.js " type="pr otractor">
  22785          it( 'should ch eck ng-cli ck', funct ion() {
  22786            e xpect(elem ent(by.bin ding('coun t')).getTe xt()).toMa tch('0');
  22787            e lement(by. css('butto n')).click ();
  22788            e xpect(elem ent(by.bin ding('coun t')).getTe xt()).toMa tch('1');
  22789          });
  22790        </fil e>
  22791      </examp le>
  22792    */
  22793   /*
  22794    * A colle ction of d irectives  that allow s creation  of custom  event han dlers that  are defin ed as
  22795    * angular  expressio ns and are  compiled  and execut ed within  the curren t scope.
  22796    */
  22797   var ngEven tDirective s = {};
  22798  
  22799   // For eve nts that m ight fire  synchronou sly during  DOM manip ulation
  22800   // we need  to execut e their ev ent handle rs asynchr onously us ing $e DNS    ync,
  22801   // so that  they are  not execut ed in an i nconsisten t state.
  22802   var forceA syncEvents  = {
  22803     'blur':  true,
  22804     'focus':  true
  22805   };
  22806   forEach(
  22807     'click d blclick mo usedown mo useup mous eover mous eout mouse move mouse enter mous eleave key down keyup  keypress  submit foc us blur co py cut pas te'.split( ' '),
  22808     function (eventName ) {
  22809       var di rectiveNam e = direct iveNormali ze('ng-' +  eventName );
  22810       ngEven tDirective s[directiv eName] = [ '$parse',  '$rootScop e', functi on($parse,  $rootScop e) {
  22811         retu rn {
  22812           re strict: 'A ',
  22813           co mpile: fun ction($ele ment, attr ) {
  22814              // We expo se the pow erful $eve nt object  on the sco pe that pr ovides acc ess to the  Window,
  22815              // etc. th at isn't p rotected b y the fast  paths in  $parse.  W e explicit ly request  better
  22816              // checks  at the cos t of speed  since eve nt handler  expressio ns are not  executed  as
  22817              // frequen tly as reg ular chang e detectio n.
  22818              var fn = $ parse(attr [directive Name], /*  intercepto rFn */ nul l, /* expe nsiveCheck s */ true) ;
  22819              return fun ction ngEv entHandler (scope, el ement) {
  22820                element. on(eventNa me, functi on(event)  {
  22821                  var ca llback = f unction()  {
  22822                    fn(s cope, {$ev ent:event} );
  22823                  };
  22824                  if (fo rceAsyncEv ents[event Name] && $ rootScope. $$phase) {
  22825                      scope.$e DNS    ync(callba ck);
  22826                  } else  {
  22827                    scop e.$apply(c allback);
  22828                  }
  22829                });
  22830              };
  22831           }
  22832         };
  22833       }];
  22834     }
  22835   );
  22836  
  22837   /**
  22838    * @ngdoc  directive
  22839    * @name n gDblclick
  22840    *
  22841    * @descri ption
  22842    * The `ng Dblclick`  directive  allows you  to specif y custom b ehavior on  a dblclic k event.
  22843    *
  22844    * @elemen t ANY
  22845    * @priori ty 0
  22846    * @param  {expressio n} ngDblcl ick {@link  guide/exp ression Ex pression}  to evaluat e upon
  22847    * a dblcl ick. (The  Event obje ct is avai lable as ` $event`)
  22848    *
  22849    * @exampl e
  22850      <exampl e>
  22851        <file  name="ind ex.html">
  22852         <but ton ng-dbl click="cou nt = count  + 1" ng-i nit="count =0">
  22853           In crement (o n double c lick)
  22854         </bu tton>
  22855         coun t: {{count }}
  22856        </fil e>
  22857      </examp le>
  22858    */
  22859  
  22860  
  22861   /**
  22862    * @ngdoc  directive
  22863    * @name n gMousedown
  22864    *
  22865    * @descri ption
  22866    * The ngM ousedown d irective a llows you  to specify  custom be havior on  mousedown  event.
  22867    *
  22868    * @elemen t ANY
  22869    * @priori ty 0
  22870    * @param  {expressio n} ngMouse down {@lin k guide/ex pression E xpression}  to evalua te upon
  22871    * mousedo wn. ({@lin k guide/ex pression#- event- Eve nt object  is availab le as `$ev ent`})
  22872    *
  22873    * @exampl e
  22874      <exampl e>
  22875        <file  name="ind ex.html">
  22876         <but ton ng-mou sedown="co unt = coun t + 1" ng- init="coun t=0">
  22877           In crement (o n mouse do wn)
  22878         </bu tton>
  22879         coun t: {{count }}
  22880        </fil e>
  22881      </examp le>
  22882    */
  22883  
  22884  
  22885   /**
  22886    * @ngdoc  directive
  22887    * @name n gMouseup
  22888    *
  22889    * @descri ption
  22890    * Specify  custom be havior on  mouseup ev ent.
  22891    *
  22892    * @elemen t ANY
  22893    * @priori ty 0
  22894    * @param  {expressio n} ngMouse up {@link  guide/expr ession Exp ression} t o evaluate  upon
  22895    * mouseup . ({@link  guide/expr ession#-ev ent- Event  object is  available  as `$even t`})
  22896    *
  22897    * @exampl e
  22898      <exampl e>
  22899        <file  name="ind ex.html">
  22900         <but ton ng-mou seup="coun t = count  + 1" ng-in it="count= 0">
  22901           In crement (o n mouse up )
  22902         </bu tton>
  22903         coun t: {{count }}
  22904        </fil e>
  22905      </examp le>
  22906    */
  22907  
  22908   /**
  22909    * @ngdoc  directive
  22910    * @name n gMouseover
  22911    *
  22912    * @descri ption
  22913    * Specify  custom be havior on  mouseover  event.
  22914    *
  22915    * @elemen t ANY
  22916    * @priori ty 0
  22917    * @param  {expressio n} ngMouse over {@lin k guide/ex pression E xpression}  to evalua te upon
  22918    * mouseov er. ({@lin k guide/ex pression#- event- Eve nt object  is availab le as `$ev ent`})
  22919    *
  22920    * @exampl e
  22921      <exampl e>
  22922        <file  name="ind ex.html">
  22923         <but ton ng-mou seover="co unt = coun t + 1" ng- init="coun t=0">
  22924           In crement (w hen mouse  is over)
  22925         </bu tton>
  22926         coun t: {{count }}
  22927        </fil e>
  22928      </examp le>
  22929    */
  22930  
  22931  
  22932   /**
  22933    * @ngdoc  directive
  22934    * @name n gMouseente r
  22935    *
  22936    * @descri ption
  22937    * Specify  custom be havior on  mouseenter  event.
  22938    *
  22939    * @elemen t ANY
  22940    * @priori ty 0
  22941    * @param  {expressio n} ngMouse enter {@li nk guide/e xpression  Expression } to evalu ate upon
  22942    * mouseen ter. ({@li nk guide/e xpression# -event- Ev ent object  is availa ble as `$e vent`})
  22943    *
  22944    * @exampl e
  22945      <exampl e>
  22946        <file  name="ind ex.html">
  22947         <but ton ng-mou seenter="c ount = cou nt + 1" ng -init="cou nt=0">
  22948           In crement (w hen mouse  enters)
  22949         </bu tton>
  22950         coun t: {{count }}
  22951        </fil e>
  22952      </examp le>
  22953    */
  22954  
  22955  
  22956   /**
  22957    * @ngdoc  directive
  22958    * @name n gMouseleav e
  22959    *
  22960    * @descri ption
  22961    * Specify  custom be havior on  mouseleave  event.
  22962    *
  22963    * @elemen t ANY
  22964    * @priori ty 0
  22965    * @param  {expressio n} ngMouse leave {@li nk guide/e xpression  Expression } to evalu ate upon
  22966    * mousele ave. ({@li nk guide/e xpression# -event- Ev ent object  is availa ble as `$e vent`})
  22967    *
  22968    * @exampl e
  22969      <exampl e>
  22970        <file  name="ind ex.html">
  22971         <but ton ng-mou seleave="c ount = cou nt + 1" ng -init="cou nt=0">
  22972           In crement (w hen mouse  leaves)
  22973         </bu tton>
  22974         coun t: {{count }}
  22975        </fil e>
  22976      </examp le>
  22977    */
  22978  
  22979  
  22980   /**
  22981    * @ngdoc  directive
  22982    * @name n gMousemove
  22983    *
  22984    * @descri ption
  22985    * Specify  custom be havior on  mousemove  event.
  22986    *
  22987    * @elemen t ANY
  22988    * @priori ty 0
  22989    * @param  {expressio n} ngMouse move {@lin k guide/ex pression E xpression}  to evalua te upon
  22990    * mousemo ve. ({@lin k guide/ex pression#- event- Eve nt object  is availab le as `$ev ent`})
  22991    *
  22992    * @exampl e
  22993      <exampl e>
  22994        <file  name="ind ex.html">
  22995         <but ton ng-mou semove="co unt = coun t + 1" ng- init="coun t=0">
  22996           In crement (w hen mouse  moves)
  22997         </bu tton>
  22998         coun t: {{count }}
  22999        </fil e>
  23000      </examp le>
  23001    */
  23002  
  23003  
  23004   /**
  23005    * @ngdoc  directive
  23006    * @name n gKeydown
  23007    *
  23008    * @descri ption
  23009    * Specify  custom be havior on  keydown ev ent.
  23010    *
  23011    * @elemen t ANY
  23012    * @priori ty 0
  23013    * @param  {expressio n} ngKeydo wn {@link  guide/expr ession Exp ression} t o evaluate  upon
  23014    * keydown . (Event o bject is a vailable a s `$event`  and can b e interrog ated for k eyCode, al tKey, etc. )
  23015    *
  23016    * @exampl e
  23017      <exampl e>
  23018        <file  name="ind ex.html">
  23019         <inp ut ng-keyd own="count  = count +  1" ng-ini t="count=0 ">
  23020         key  down count : {{count} }
  23021        </fil e>
  23022      </examp le>
  23023    */
  23024  
  23025  
  23026   /**
  23027    * @ngdoc  directive
  23028    * @name n gKeyup
  23029    *
  23030    * @descri ption
  23031    * Specify  custom be havior on  keyup even t.
  23032    *
  23033    * @elemen t ANY
  23034    * @priori ty 0
  23035    * @param  {expressio n} ngKeyup  {@link gu ide/expres sion Expre ssion} to  evaluate u pon
  23036    * keyup.  (Event obj ect is ava ilable as  `$event` a nd can be  interrogat ed for key Code, altK ey, etc.)
  23037    *
  23038    * @exampl e
  23039      <exampl e>
  23040        <file  name="ind ex.html">
  23041          <p> Typing in  the input  box below  updates th e key coun t</p>
  23042          <in put ng-key up="count  = count +  1" ng-init ="count=0" > key up c ount: {{co unt}}
  23043  
  23044          <p> Typing in  the input  box below  updates th e keycode< /p>
  23045          <in put ng-key up="event= $event">
  23046          <p> event keyC ode: {{ ev ent.keyCod e }}</p>
  23047          <p> event altK ey: {{ eve nt.altKey  }}</p>
  23048        </fil e>
  23049      </examp le>
  23050    */
  23051  
  23052  
  23053   /**
  23054    * @ngdoc  directive
  23055    * @name n gKeypress
  23056    *
  23057    * @descri ption
  23058    * Specify  custom be havior on  keypress e vent.
  23059    *
  23060    * @elemen t ANY
  23061    * @param  {expressio n} ngKeypr ess {@link  guide/exp ression Ex pression}  to evaluat e upon
  23062    * keypres s. ({@link  guide/exp ression#-e vent- Even t object i s availabl e as `$eve nt`}
  23063    * and can  be interr ogated for  keyCode,  altKey, et c.)
  23064    *
  23065    * @exampl e
  23066      <exampl e>
  23067        <file  name="ind ex.html">
  23068         <inp ut ng-keyp ress="coun t = count  + 1" ng-in it="count= 0">
  23069         key  press coun t: {{count }}
  23070        </fil e>
  23071      </examp le>
  23072    */
  23073  
  23074  
  23075   /**
  23076    * @ngdoc  directive
  23077    * @name n gSubmit
  23078    *
  23079    * @descri ption
  23080    * Enables  binding a ngular exp ressions t o onsubmit  events.
  23081    *
  23082    * Additio nally it p revents th e default  action (wh ich for fo rm means s ending the  request t o the
  23083    * server  and reload ing the cu rrent page ), but onl y if the f orm does n ot contain  `action`,
  23084    * `data-a ction`, or  `x-action ` attribut es.
  23085    *
  23086    * <div cl ass="alert  alert-war ning">
  23087    * **Warni ng:** Be c areful not  to cause  "double-su bmission"  by using b oth the `n gClick` an d
  23088    * `ngSubm it` handle rs togethe r. See the
  23089    * {@link  form#submi tting-a-fo rm-and-pre venting-th e-default- action `fo rm` direct ive docume ntation}
  23090    * for a d etailed di scussion o f when `ng Submit` ma y be trigg ered.
  23091    * </div>
  23092    *
  23093    * @elemen t form
  23094    * @priori ty 0
  23095    * @param  {expressio n} ngSubmi t {@link g uide/expre ssion Expr ession} to  eval.
  23096    * ({@link  guide/exp ression#-e vent- Even t object i s availabl e as `$eve nt`})
  23097    *
  23098    * @exampl e
  23099      <exampl e module=" submitExam ple">
  23100        <file  name="ind ex.html">
  23101         <scr ipt>
  23102           an gular.modu le('submit Example',  [])
  23103              .controlle r('Example Controller ', ['$scop e', functi on($scope)  {
  23104                $scope.l ist = [];
  23105                $scope.t ext = 'hel lo';
  23106                $scope.s ubmit = fu nction() {
  23107                  if ($s cope.text)  {
  23108                    $sco pe.list.pu sh(this.te xt);
  23109                    $sco pe.text =  '';
  23110                  }
  23111                };
  23112              }]);
  23113         </sc ript>
  23114         <for m ng-submi t="submit( )" ng-cont roller="Ex ampleContr oller">
  23115           En ter text a nd hit ent er:
  23116           <i nput type= "text" ng- model="tex t" name="t ext" />
  23117           <i nput type= "submit" i d="submit"  value="Su bmit" />
  23118           <p re>list={{ list}}</pr e>
  23119         </fo rm>
  23120        </fil e>
  23121        <file  name="pro tractor.js " type="pr otractor">
  23122          it( 'should ch eck ng-sub mit', func tion() {
  23123            e xpect(elem ent(by.bin ding('list ')).getTex t()).toBe( 'list=[]') ;
  23124            e lement(by. css('#subm it')).clic k();
  23125            e xpect(elem ent(by.bin ding('list ')).getTex t()).toCon tain('hell o');
  23126            e xpect(elem ent(by.mod el('text') ).getAttri bute('valu e')).toBe( '');
  23127          });
  23128          it( 'should ig nore empty  strings',  function( ) {
  23129            e xpect(elem ent(by.bin ding('list ')).getTex t()).toBe( 'list=[]') ;
  23130            e lement(by. css('#subm it')).clic k();
  23131            e lement(by. css('#subm it')).clic k();
  23132            e xpect(elem ent(by.bin ding('list ')).getTex t()).toCon tain('hell o');
  23133           }) ;
  23134        </fil e>
  23135      </examp le>
  23136    */
  23137  
  23138   /**
  23139    * @ngdoc  directive
  23140    * @name n gFocus
  23141    *
  23142    * @descri ption
  23143    * Specify  custom be havior on  focus even t.
  23144    *
  23145    * Note: A s the `foc us` event  is execute d synchron ously when  calling ` input.focu s()`
  23146    * Angular JS execute s the expr ession usi ng `scope. $e DNS    ync` if th e event is  fired
  23147    * during  an `$apply ` to ensur e a consis tent state .
  23148    *
  23149    * @elemen t window,  input, sel ect, texta rea, a
  23150    * @priori ty 0
  23151    * @param  {expressio n} ngFocus  {@link gu ide/expres sion Expre ssion} to  evaluate u pon
  23152    * focus.  ({@link gu ide/expres sion#-even t- Event o bject is a vailable a s `$event` })
  23153    *
  23154    * @exampl e
  23155    * See {@l ink ng.dir ective:ngC lick ngCli ck}
  23156    */
  23157  
  23158   /**
  23159    * @ngdoc  directive
  23160    * @name n gBlur
  23161    *
  23162    * @descri ption
  23163    * Specify  custom be havior on  blur event .
  23164    *
  23165    * A [blur  event](ht tps://deve loper.mozi lla.org/en -US/docs/W eb/Events/ blur) fire s when
  23166    * an elem ent has lo st focus.
  23167    *
  23168    * Note: A s the `blu r` event i s executed  synchrono usly also  during DOM  manipulat ions
  23169    * (e.g. r emoving a  focussed i nput),
  23170    * Angular JS execute s the expr ession usi ng `scope. $e DNS    ync` if th e event is  fired
  23171    * during  an `$apply ` to ensur e a consis tent state .
  23172    *
  23173    * @elemen t window,  input, sel ect, texta rea, a
  23174    * @priori ty 0
  23175    * @param  {expressio n} ngBlur  {@link gui de/express ion Expres sion} to e valuate up on
  23176    * blur. ( {@link gui de/express ion#-event - Event ob ject is av ailable as  `$event`} )
  23177    *
  23178    * @exampl e
  23179    * See {@l ink ng.dir ective:ngC lick ngCli ck}
  23180    */
  23181  
  23182   /**
  23183    * @ngdoc  directive
  23184    * @name n gCopy
  23185    *
  23186    * @descri ption
  23187    * Specify  custom be havior on  copy event .
  23188    *
  23189    * @elemen t window,  input, sel ect, texta rea, a
  23190    * @priori ty 0
  23191    * @param  {expressio n} ngCopy  {@link gui de/express ion Expres sion} to e valuate up on
  23192    * copy. ( {@link gui de/express ion#-event - Event ob ject is av ailable as  `$event`} )
  23193    *
  23194    * @exampl e
  23195      <exampl e>
  23196        <file  name="ind ex.html">
  23197         <inp ut ng-copy ="copied=t rue" ng-in it="copied =false; va lue='copy  me'" ng-mo del="value ">
  23198         copi ed: {{copi ed}}
  23199        </fil e>
  23200      </examp le>
  23201    */
  23202  
  23203   /**
  23204    * @ngdoc  directive
  23205    * @name n gCut
  23206    *
  23207    * @descri ption
  23208    * Specify  custom be havior on  cut event.
  23209    *
  23210    * @elemen t window,  input, sel ect, texta rea, a
  23211    * @priori ty 0
  23212    * @param  {expressio n} ngCut { @link guid e/expressi on Express ion} to ev aluate upo n
  23213    * cut. ({ @link guid e/expressi on#-event-  Event obj ect is ava ilable as  `$event`})
  23214    *
  23215    * @exampl e
  23216      <exampl e>
  23217        <file  name="ind ex.html">
  23218         <inp ut ng-cut= "cut=true"  ng-init=" cut=false;  value='cu t me'" ng- model="val ue">
  23219         cut:  {{cut}}
  23220        </fil e>
  23221      </examp le>
  23222    */
  23223  
  23224   /**
  23225    * @ngdoc  directive
  23226    * @name n gPaste
  23227    *
  23228    * @descri ption
  23229    * Specify  custom be havior on  paste even t.
  23230    *
  23231    * @elemen t window,  input, sel ect, texta rea, a
  23232    * @priori ty 0
  23233    * @param  {expressio n} ngPaste  {@link gu ide/expres sion Expre ssion} to  evaluate u pon
  23234    * paste.  ({@link gu ide/expres sion#-even t- Event o bject is a vailable a s `$event` })
  23235    *
  23236    * @exampl e
  23237      <exampl e>
  23238        <file  name="ind ex.html">
  23239         <inp ut ng-past e="paste=t rue" ng-in it="paste= false" pla ceholder=' paste here '>
  23240         past ed: {{past e}}
  23241        </fil e>
  23242      </examp le>
  23243    */
  23244  
  23245   /**
  23246    * @ngdoc  directive
  23247    * @name n gIf
  23248    * @restri ct A
  23249    *
  23250    * @descri ption
  23251    * The `ng If` direct ive remove s or recre ates a por tion of th e DOM tree  based on  an
  23252    * {expres sion}. If  the expres sion assig ned to `ng If` evalua tes to a f alse
  23253    * value t hen the el ement is r emoved fro m the DOM,  otherwise  a clone o f the
  23254    * element  is reinse rted into  the DOM.
  23255    *
  23256    * `ngIf`  differs fr om `ngShow ` and `ngH ide` in th at `ngIf`  completely  removes a nd recreat es the
  23257    * element  in the DO M rather t han changi ng its vis ibility vi a the `dis play` css  property.   A common
  23258    * case wh en this di fference i s signific ant is whe n using cs s selector s that rel y on an el ement's
  23259    * positio n within t he DOM, su ch as the  `:first-ch ild` or `: last-child ` pseudo-c lasses.
  23260    *
  23261    * Note th at when an  element i s removed  using `ngI f` its sco pe is dest royed and  a new scop e
  23262    * is crea ted when t he element  is restor ed.  The s cope creat ed within  `ngIf` inh erits from
  23263    * its par ent scope  using
  23264    * [protot ypal inher itance](ht tps://gith ub.com/ang ular/angul ar.js/wiki /Understan ding-Scope s#javascri pt-prototy pal-inheri tance).
  23265    * An impo rtant impl ication of  this is i f `ngModel ` is used  within `ng If` to bin d to
  23266    * a javas cript prim itive defi ned in the  parent sc ope. In th is case an y modifica tions made  to the
  23267    * variabl e within t he child s cope will  override ( hide) the  value in t he parent  scope.
  23268    *
  23269    * Also, ` ngIf` recr eates elem ents using  their com piled stat e. An exam ple of thi s behavior
  23270    * is if a n element' s class at tribute is  directly  modified a fter it's  compiled,  using some thing like
  23271    * jQuery' s `.addCla ss()` meth od, and th e element  is later r emoved. Wh en `ngIf`  recreates  the elemen t
  23272    * the add ed class w ill be los t because  the origin al compile d state is  used to r egenerate  the elemen t.
  23273    *
  23274    * Additio nally, you  can provi de animati ons via th e `ngAnima te` module  to animat e the `ent er`
  23275    * and `le ave` effec ts.
  23276    *
  23277    * @animat ions
  23278    * enter -  happens j ust after  the `ngIf`  contents  change and  a new DOM  element i s created  and inject ed into th e `ngIf` c ontainer
  23279    * leave -  happens j ust before  the `ngIf ` contents  are remov ed from th e DOM
  23280    *
  23281    * @elemen t ANY
  23282    * @scope
  23283    * @priori ty 600
  23284    * @param  {expressio n} ngIf If  the {@lin k guide/ex pression e xpression}  is falsy  then
  23285    *     the  element i s removed  from the D OM tree. I f it is tr uthy a cop y of the c ompiled
  23286    *     ele ment is ad ded to the  DOM tree.
  23287    *
  23288    * @exampl e
  23289     <example  module="n gAnimate"  deps="angu lar-animat e.js" anim ations="tr ue">
  23290       <file  name="inde x.html">
  23291         Clic k me: <inp ut type="c heckbox" n g-model="c hecked" ng -init="che cked=true"  /><br/>
  23292         Show  when chec ked:
  23293         <spa n ng-if="c hecked" cl ass="anima te-if">
  23294           Th is is remo ved when t he checkbo x is unche cked.
  23295         </sp an>
  23296       </file >
  23297       <file  name="anim ations.css ">
  23298         .ani mate-if {
  23299           ba ckground:w hite;
  23300           bo rder:1px s olid black ;
  23301           pa dding:10px ;
  23302         }
  23303  
  23304         .ani mate-if.ng -enter, .a nimate-if. ng-leave {
  23305           -w ebkit-tran sition:all  cubic-bez ier(0.250,  0.460, 0. 450, 0.940 ) 0.5s;
  23306           tr ansition:a ll cubic-b ezier(0.25 0, 0.460,  0.450, 0.9 40) 0.5s;
  23307         }
  23308  
  23309         .ani mate-if.ng -enter,
  23310         .ani mate-if.ng -leave.ng- leave-acti ve {
  23311           op acity:0;
  23312         }
  23313  
  23314         .ani mate-if.ng -leave,
  23315         .ani mate-if.ng -enter.ng- enter-acti ve {
  23316           op acity:1;
  23317         }
  23318       </file >
  23319     </exampl e>
  23320    */
  23321   var ngIfDi rective =  ['$animate ', functio n($animate ) {
  23322     return {
  23323       multiE lement: tr ue,
  23324       transc lude: 'ele ment',
  23325       priori ty: 600,
  23326       termin al: true,
  23327       restri ct: 'A',
  23328       $$tlb:  true,
  23329       link:  function($ scope, $el ement, $at tr, ctrl,  $transclud e) {
  23330           va r block, c hildScope,  previousE lements;
  23331           $s cope.$watc h($attr.ng If, functi on ngIfWat chAction(v alue) {
  23332  
  23333              if (value)  {
  23334                if (!chi ldScope) {
  23335                  $trans clude(func tion(clone , newScope ) {
  23336                    chil dScope = n ewScope;
  23337                    clon e[clone.le ngth++] =  document.c reateComme nt(' end n gIf: ' + $ attr.ngIf  + ' ');
  23338                    // N ote: We on ly need th e first/la st node of  the clone d nodes.
  23339                    // H owever, we  need to k eep the re ference to  the jqlit e wrapper  as it migh t be chang ed later
  23340                    // b y a direct ive with t emplateUrl  when its  template a rrives.
  23341                    bloc k = {
  23342                      cl one: clone
  23343                    };
  23344                    $ani mate.enter (clone, $e lement.par ent(), $el ement);
  23345                  });
  23346                }
  23347              } else {
  23348                if (prev iousElemen ts) {
  23349                  previo usElements .remove();
  23350                  previo usElements  = null;
  23351                }
  23352                if (chil dScope) {
  23353                  childS cope.$dest roy();
  23354                  childS cope = nul l;
  23355                }
  23356                if (bloc k) {
  23357                  previo usElements  = getBloc kNodes(blo ck.clone);
  23358                  $anima te.leave(p reviousEle ments).the n(function () {
  23359                    prev iousElemen ts = null;
  23360                  });
  23361                  block  = null;
  23362                }
  23363              }
  23364           }) ;
  23365       }
  23366     };
  23367   }];
  23368  
  23369   /**
  23370    * @ngdoc  directive
  23371    * @name n gInclude
  23372    * @restri ct ECA
  23373    *
  23374    * @descri ption
  23375    * Fetches , compiles  and inclu des an ext ernal HTML  fragment.
  23376    *
  23377    * By defa ult, the t emplate UR L is restr icted to t he same do main and p rotocol as  the
  23378    * applica tion docum ent. This  is done by  calling { @link $sce #getTruste dResourceU rl
  23379    * $sce.ge tTrustedRe sourceUrl}  on it. To  load temp lates from  other dom ains or pr otocols
  23380    * you may  either {@ link ng.$s ceDelegate Provider#r esourceUrl Whitelist  whitelist  them} or
  23381    * {@link  $sce#trust AsResource Url wrap t hem} as tr usted valu es. Refer  to Angular 's {@link
  23382    * ng.$sce  Strict Co ntextual E scaping}.
  23383    *
  23384    * In addi tion, the  browser's
  23385    * [Same O rigin Poli cy](https: //code.goo gle.com/p/ browsersec /wiki/Part 2#Same-ori gin_policy _for_XMLHt tpRequest)
  23386    * and [Cr oss-Origin  Resource  Sharing (C ORS)](http ://www.w3. org/TR/cor s/)
  23387    * policy  may furthe r restrict  whether t he templat e is succe ssfully lo aded.
  23388    * For exa mple, `ngI nclude` wo n't work f or cross-d omain requ ests on al l browsers  and for ` file://`
  23389    * access  on some br owsers.
  23390    *
  23391    * @animat ions
  23392    * enter -  animation  is used t o bring ne w content  into the b rowser.
  23393    * leave -  animation  is used t o animate  existing c ontent awa y.
  23394    *
  23395    * The ent er and lea ve animati on occur c oncurrentl y.
  23396    *
  23397    * @scope
  23398    * @priori ty 400
  23399    *
  23400    * @param  {string} n gInclude|s rc angular  expressio n evaluati ng to URL.  If the so urce is a  string con stant,
  23401    *                  m ake sure y ou wrap it  in **sing le** quote s, e.g. `s rc="'myPar tialTempla te.html'"` .
  23402    * @param  {string=}  onload Exp ression to  evaluate  when a new  partial i s loaded.
  23403    *
  23404    * @param  {string=}  autoscroll  Whether ` ngInclude`  should ca ll {@link  ng.$anchor Scroll
  23405    *                    $anchorScr oll} to sc roll the v iewport af ter the co ntent is l oaded.
  23406    *
  23407    *                    - If the a ttribute i s not set,  disable s crolling.
  23408    *                    - If the a ttribute i s set with out value,  enable sc rolling.
  23409    *                    - Otherwis e enable s crolling o nly if the  expressio n evaluate s to truth y value.
  23410    *
  23411    * @exampl e
  23412     <example  module="i ncludeExam ple" deps= "angular-a nimate.js"  animation s="true">
  23413       <file  name="inde x.html">
  23414        <div  ng-control ler="Examp leControll er">
  23415          <se lect ng-mo del="templ ate" ng-op tions="t.n ame for t  in templat es">
  23416           <o ption valu e="">(blan k)</option >
  23417          </s elect>
  23418          url  of the te mplate: <t t>{{templa te.url}}</ tt>
  23419          <hr />
  23420          <di v class="s lide-anima te-contain er">
  23421            < div class= "slide-ani mate" ng-i nclude="te mplate.url "></div>
  23422          </d iv>
  23423        </div >
  23424       </file >
  23425       <file  name="scri pt.js">
  23426         angu lar.module ('includeE xample', [ 'ngAnimate '])
  23427           .c ontroller( 'ExampleCo ntroller',  ['$scope' , function ($scope) {
  23428              $scope.tem plates =
  23429                [ { name : 'templat e1.html',  url: 'temp late1.html '},
  23430                  { name : 'templat e2.html',  url: 'temp late2.html '} ];
  23431              $scope.tem plate = $s cope.templ ates[0];
  23432           }] );
  23433        </fil e>
  23434       <file  name="temp late1.html ">
  23435         Cont ent of tem plate1.htm l
  23436       </file >
  23437       <file  name="temp late2.html ">
  23438         Cont ent of tem plate2.htm l
  23439       </file >
  23440       <file  name="anim ations.css ">
  23441         .sli de-animate -container  {
  23442           po sition:rel ative;
  23443           ba ckground:w hite;
  23444           bo rder:1px s olid black ;
  23445           he ight:40px;
  23446           ov erflow:hid den;
  23447         }
  23448  
  23449         .sli de-animate  {
  23450           pa dding:10px ;
  23451         }
  23452  
  23453         .sli de-animate .ng-enter,  .slide-an imate.ng-l eave {
  23454           -w ebkit-tran sition:all  cubic-bez ier(0.250,  0.460, 0. 450, 0.940 ) 0.5s;
  23455           tr ansition:a ll cubic-b ezier(0.25 0, 0.460,  0.450, 0.9 40) 0.5s;
  23456  
  23457           po sition:abs olute;
  23458           to p:0;
  23459           le ft:0;
  23460           ri ght:0;
  23461           bo ttom:0;
  23462           di splay:bloc k;
  23463           pa dding:10px ;
  23464         }
  23465  
  23466         .sli de-animate .ng-enter  {
  23467           to p:-50px;
  23468         }
  23469         .sli de-animate .ng-enter. ng-enter-a ctive {
  23470           to p:0;
  23471         }
  23472  
  23473         .sli de-animate .ng-leave  {
  23474           to p:0;
  23475         }
  23476         .sli de-animate .ng-leave. ng-leave-a ctive {
  23477           to p:50px;
  23478         }
  23479       </file >
  23480       <file  name="prot ractor.js"  type="pro tractor">
  23481         var  templateSe lect = ele ment(by.mo del('templ ate'));
  23482         var  includeEle m = elemen t(by.css(' [ng-includ e]'));
  23483  
  23484         it(' should loa d template 1.html', f unction()  {
  23485           ex pect(inclu deElem.get Text()).to Match(/Con tent of te mplate1.ht ml/);
  23486         });
  23487  
  23488         it(' should loa d template 2.html', f unction()  {
  23489           if  (browser. params.bro wser == 'f irefox') {
  23490              // Firefox  can't han dle using  selects
  23491              // See htt ps://githu b.com/angu lar/protra ctor/issue s/480
  23492              return;
  23493           }
  23494           te mplateSele ct.click() ;
  23495           te mplateSele ct.all(by. css('optio n')).get(2 ).click();
  23496           ex pect(inclu deElem.get Text()).to Match(/Con tent of te mplate2.ht ml/);
  23497         });
  23498  
  23499         it(' should cha nge to bla nk', funct ion() {
  23500           if  (browser. params.bro wser == 'f irefox') {
  23501              // Firefox  can't han dle using  selects
  23502              return;
  23503           }
  23504           te mplateSele ct.click() ;
  23505           te mplateSele ct.all(by. css('optio n')).get(0 ).click();
  23506           ex pect(inclu deElem.isP resent()). toBe(false );
  23507         });
  23508       </file >
  23509     </exampl e>
  23510    */
  23511  
  23512  
  23513   /**
  23514    * @ngdoc  event
  23515    * @name n gInclude#$ includeCon tentReques ted
  23516    * @eventT ype emit o n the scop e ngInclud e was decl ared in
  23517    * @descri ption
  23518    * Emitted  every tim e the ngIn clude cont ent is req uested.
  23519    *
  23520    * @param  {Object} a ngularEven t Syntheti c event ob ject.
  23521    * @param  {String} s rc URL of  content to  load.
  23522    */
  23523  
  23524  
  23525   /**
  23526    * @ngdoc  event
  23527    * @name n gInclude#$ includeCon tentLoaded
  23528    * @eventT ype emit o n the curr ent ngIncl ude scope
  23529    * @descri ption
  23530    * Emitted  every tim e the ngIn clude cont ent is rel oaded.
  23531    *
  23532    * @param  {Object} a ngularEven t Syntheti c event ob ject.
  23533    * @param  {String} s rc URL of  content to  load.
  23534    */
  23535  
  23536  
  23537   /**
  23538    * @ngdoc  event
  23539    * @name n gInclude#$ includeCon tentError
  23540    * @eventT ype emit o n the scop e ngInclud e was decl ared in
  23541    * @descri ption
  23542    * Emitted  when a te mplate HTT P request  yields an  erronous r esponse (s tatus < 20 0 || statu s > 299)
  23543    *
  23544    * @param  {Object} a ngularEven t Syntheti c event ob ject.
  23545    * @param  {String} s rc URL of  content to  load.
  23546    */
  23547   var ngIncl udeDirecti ve = ['$te mplateRequ est', '$an chorScroll ', '$anima te', '$sce ',
  23548                      fu nction($te mplateRequ est,   $an chorScroll ,   $anima te,   $sce ) {
  23549     return {
  23550       restri ct: 'ECA',
  23551       priori ty: 400,
  23552       termin al: true,
  23553       transc lude: 'ele ment',
  23554       contro ller: angu lar.noop,
  23555       compil e: functio n(element,  attr) {
  23556         var  srcExp = a ttr.ngIncl ude || att r.src,
  23557              onloadExp  = attr.onl oad || '',
  23558              autoScroll Exp = attr .autoscrol l;
  23559  
  23560         retu rn functio n(scope, $ element, $ attr, ctrl , $transcl ude) {
  23561           va r changeCo unter = 0,
  23562                currentS cope,
  23563                previous Element,
  23564                currentE lement;
  23565  
  23566           va r cleanupL astInclude Content =  function()  {
  23567              if (previo usElement)  {
  23568                previous Element.re move();
  23569                previous Element =  null;
  23570              }
  23571              if (curren tScope) {
  23572                currentS cope.$dest roy();
  23573                currentS cope = nul l;
  23574              }
  23575              if (curren tElement)  {
  23576                $animate .leave(cur rentElemen t).then(fu nction() {
  23577                  previo usElement  = null;
  23578                });
  23579                previous Element =  currentEle ment;
  23580                currentE lement = n ull;
  23581              }
  23582           };
  23583  
  23584           sc ope.$watch ($sce.pars eAsResourc eUrl(srcEx p), functi on ngInclu deWatchAct ion(src) {
  23585              var afterA nimation =  function( ) {
  23586                if (isDe fined(auto ScrollExp)  && (!auto ScrollExp  || scope.$ eval(autoS crollExp)) ) {
  23587                  $ancho rScroll();
  23588                }
  23589              };
  23590              var thisCh angeId = + +changeCou nter;
  23591  
  23592              if (src) {
  23593                //set th e 2nd para m to true  to ignore  the templa te request  error so  that the i nner
  23594                //conten ts and sco pe can be  cleaned up .
  23595                $templat eRequest(s rc, true). then(funct ion(respon se) {
  23596                  if (th isChangeId  !== chang eCounter)  return;
  23597                  var ne wScope = s cope.$new( );
  23598                  ctrl.t emplate =  response;
  23599  
  23600                  // Not e: This wi ll also li nk all chi ldren of n g-include  that were  contained  in the ori ginal
  23601                  // htm l. If that  content c ontains co ntrollers,  ... they  could poll ute/change  the scope .
  23602                  // How ever, usin g ng-inclu de on an e lement wit h addition al content  does not  make sense ...
  23603                  // Not e: We can' t remove t hem in the  cloneAttc hFn of $tr ansclude a s that
  23604                  // fun ction is c alled befo re linking  the conte nt, which  would appl y child
  23605                  // dir ectives to  non exist ing elemen ts.
  23606                  var cl one = $tra nsclude(ne wScope, fu nction(clo ne) {
  23607                    clea nupLastInc ludeConten t();
  23608                    $ani mate.enter (clone, nu ll, $eleme nt).then(a fterAnimat ion);
  23609                  });
  23610  
  23611                  curren tScope = n ewScope;
  23612                  curren tElement =  clone;
  23613  
  23614                  curren tScope.$em it('$inclu deContentL oaded', sr c);
  23615                  scope. $eval(onlo adExp);
  23616                }, funct ion() {
  23617                  if (th isChangeId  === chang eCounter)  {
  23618                    clea nupLastInc ludeConten t();
  23619                    scop e.$emit('$ includeCon tentError' , src);
  23620                  }
  23621                });
  23622                scope.$e mit('$incl udeContent Requested' , src);
  23623              } else {
  23624                cleanupL astInclude Content();
  23625                ctrl.tem plate = nu ll;
  23626              }
  23627           }) ;
  23628         };
  23629       }
  23630     };
  23631   }];
  23632  
  23633   // This di rective is  called du ring the $ transclude  call of t he first ` ngInclude`  directive .
  23634   // It will  replace a nd compile  the conte nt of the  element wi th the loa ded templa te.
  23635   // We need  this dire ctive so t hat the el ement cont ent is alr eady fille d when
  23636   // the lin k function  of anothe r directiv e on the s ame elemen t as ngInc lude
  23637   // is call ed.
  23638   var ngIncl udeFillCon tentDirect ive = ['$c ompile',
  23639     function ($compile)  {
  23640       return  {
  23641         rest rict: 'ECA ',
  23642         prio rity: -400 ,
  23643         requ ire: 'ngIn clude',
  23644         link : function (scope, $e lement, $a ttr, ctrl)  {
  23645           if  (/SVG/.te st($elemen t[0].toStr ing())) {
  23646              // WebKit:  https://b ugs.webkit .org/show_ bug.cgi?id =135698 -- - SVG elem ents do no t
  23647              // support  innerHTML , so detec t this her e and try  to generat e the cont ents
  23648              // special ly.
  23649              $element.e mpty();
  23650              $compile(j qLiteBuild Fragment(c trl.templa te, docume nt).childN odes)(scop e,
  23651                  functi on namespa ceAdaptedC lone(clone ) {
  23652                $element .append(cl one);
  23653              }, {future ParentElem ent: $elem ent});
  23654              return;
  23655           }
  23656  
  23657           $e lement.htm l(ctrl.tem plate);
  23658           $c ompile($el ement.cont ents())(sc ope);
  23659         }
  23660       };
  23661     }];
  23662  
  23663   /**
  23664    * @ngdoc  directive
  23665    * @name n gInit
  23666    * @restri ct AC
  23667    *
  23668    * @descri ption
  23669    * The `ng Init` dire ctive allo ws you to  evaluate a n expressi on in the
  23670    * current  scope.
  23671    *
  23672    * <div cl ass="alert  alert-err or">
  23673    * The onl y appropri ate use of  `ngInit`  is for ali asing spec ial proper ties of
  23674    * {@link  ng.directi ve:ngRepea t `ngRepea t`}, as se en in the  demo below . Besides  this case,  you
  23675    * should  use {@link  guide/con troller co ntrollers}  rather th an `ngInit `
  23676    * to init ialize val ues on a s cope.
  23677    * </div>
  23678    * <div cl ass="alert  alert-war ning">
  23679    * **Note* *: If you  have assig nment in ` ngInit` al ong with { @link ng.$ filter `$f ilter`}, m ake
  23680    * sure yo u have par enthesis f or correct  precedenc e:
  23681    * <pre cl ass="prett yprint">
  23682    *   <div  ng-init="t est1 = (da ta | order By:'name') "></div>
  23683    * </pre>
  23684    * </div>
  23685    *
  23686    * @priori ty 450
  23687    *
  23688    * @elemen t ANY
  23689    * @param  {expressio n} ngInit  {@link gui de/express ion Expres sion} to e val.
  23690    *
  23691    * @exampl e
  23692      <exampl e module=" initExampl e">
  23693        <file  name="ind ex.html">
  23694      <script >
  23695        angul ar.module( 'initExamp le', [])
  23696          .co ntroller(' ExampleCon troller',  ['$scope',  function( $scope) {
  23697            $ scope.list  = [['a',  'b'], ['c' , 'd']];
  23698          }]) ;
  23699      </scrip t>
  23700      <div ng -controlle r="Example Controller ">
  23701        <div  ng-repeat= "innerList  in list"  ng-init="o uterIndex  = $index">
  23702          <di v ng-repea t="value i n innerLis t" ng-init ="innerInd ex = $inde x">
  23703              <span clas s="example -init">lis t[ {{outer Index}} ][  {{innerIn dex}} ] =  {{value}}; </span>
  23704          </d iv>
  23705        </div >
  23706      </div>
  23707        </fil e>
  23708        <file  name="pro tractor.js " type="pr otractor">
  23709          it( 'should al ias index  positions' , function () {
  23710            v ar element s = elemen t.all(by.c ss('.examp le-init')) ;
  23711            e xpect(elem ents.get(0 ).getText( )).toBe('l ist[ 0 ][  0 ] = a;') ;
  23712            e xpect(elem ents.get(1 ).getText( )).toBe('l ist[ 0 ][  1 ] = b;') ;
  23713            e xpect(elem ents.get(2 ).getText( )).toBe('l ist[ 1 ][  0 ] = c;') ;
  23714            e xpect(elem ents.get(3 ).getText( )).toBe('l ist[ 1 ][  1 ] = d;') ;
  23715          });
  23716        </fil e>
  23717      </examp le>
  23718    */
  23719   var ngInit Directive  = ngDirect ive({
  23720     priority : 450,
  23721     compile:  function( ) {
  23722       return  {
  23723         pre:  function( scope, ele ment, attr s) {
  23724           sc ope.$eval( attrs.ngIn it);
  23725         }
  23726       };
  23727     }
  23728   });
  23729  
  23730   /**
  23731    * @ngdoc  directive
  23732    * @name n gNonBindab le
  23733    * @restri ct AC
  23734    * @priori ty 1000
  23735    *
  23736    * @descri ption
  23737    * The `ng NonBindabl e` directi ve tells A ngular not  to compil e or bind  the conten ts of the  current
  23738    * DOM ele ment. This  is useful  if the el ement cont ains what  appears to  be Angula r directiv es and
  23739    * binding s but whic h should b e ignored  by Angular . This cou ld be the  case if yo u have a s ite that
  23740    * display s snippets  of code,  for instan ce.
  23741    *
  23742    * @elemen t ANY
  23743    *
  23744    * @exampl e
  23745    * In this  example t here are t wo locatio ns where a  simple in terpolatio n binding  (`{{}}`) i s present,
  23746    * but the  one wrapp ed in `ngN onBindable ` is left  alone.
  23747    *
  23748    * @exampl e
  23749       <examp le>
  23750         <fil e name="in dex.html">
  23751           <d iv>Normal:  {{1 + 2}} </div>
  23752           <d iv ng-non- bindable>I gnored: {{ 1 + 2}}</d iv>
  23753         </fi le>
  23754         <fil e name="pr otractor.j s" type="p rotractor" >
  23755          it( 'should ch eck ng-non -bindable' , function () {
  23756            e xpect(elem ent(by.bin ding('1 +  2')).getTe xt()).toCo ntain('3') ;
  23757            e xpect(elem ent.all(by .css('div' )).last(). getText()) .toMatch(/ 1 \+ 2/);
  23758          });
  23759         </fi le>
  23760       </exam ple>
  23761    */
  23762   var ngNonB indableDir ective = n gDirective ({ termina l: true, p riority: 1 000 });
  23763  
  23764   /**
  23765    * @ngdoc  directive
  23766    * @name n gPluralize
  23767    * @restri ct EA
  23768    *
  23769    * @descri ption
  23770    * `ngPlur alize` is  a directiv e that dis plays mess ages accor ding to en -US locali zation rul es.
  23771    * These r ules are b undled wit h angular. js, but ca n be overr idden
  23772    * (see {@ link guide /i18n Angu lar i18n}  dev guide) . You conf igure ngPl uralize di rective
  23773    * by spec ifying the  mappings  between
  23774    * [plural  categorie s](http:// unicode.or g/repos/cl dr-tmp/tru nk/diff/su pplemental /language_ plural_rul es.html)
  23775    * and the  strings t o be displ ayed.
  23776    *
  23777    * # Plura l categori es and exp licit numb er rules
  23778    * There a re two
  23779    * [plural  categorie s](http:// unicode.or g/repos/cl dr-tmp/tru nk/diff/su pplemental /language_ plural_rul es.html)
  23780    * in Angu lar's defa ult en-US  locale: "o ne" and "o ther".
  23781    *
  23782    * While a  plural ca tegory may  match man y numbers  (for examp le, in en- US locale,  "other" c an match
  23783    * any num ber that i s not 1),  an explici t number r ule can on ly match o ne number.  For examp le, the
  23784    * explici t number r ule for "3 " matches  the number  3. There  are exampl es of plur al categor ies
  23785    * and exp licit numb er rules t hroughout  the rest o f this doc umentation .
  23786    *
  23787    * # Confi guring ngP luralize
  23788    * You con figure ngP luralize b y providin g 2 attrib utes: `cou nt` and `w hen`.
  23789    * You can  also prov ide an opt ional attr ibute, `of fset`.
  23790    *
  23791    * The val ue of the  `count` at tribute ca n be eithe r a string  or an {@l ink guide/ expression
  23792    * Angular  expressio n}; these  are evalua ted on the  current s cope for i ts bound v alue.
  23793    *
  23794    * The `wh en` attrib ute specif ies the ma ppings bet ween plura l categori es and the  actual
  23795    * string  to be disp layed. The  value of  the attrib ute should  be a JSON  object.
  23796    *
  23797    * The fol lowing exa mple shows  how to co nfigure ng Pluralize:
  23798    *
  23799    * ```html
  23800    * <ng-plu ralize cou nt="person Count"
  23801                     whe n="{'0': ' Nobody is  viewing.',
  23802    *                        'one':  '1 person  is viewin g.',
  23803    *                        'other ': '{} peo ple are vi ewing.'}">
  23804    * </ng-pl uralize>
  23805    *```
  23806    *
  23807    * In the  example, ` "0: Nobody  is viewin g."` is an  explicit  number rul e. If you  did not
  23808    * specify  this rule , 0 would  be matched  to the "o ther" cate gory and " 0 people a re viewing "
  23809    * would b e shown in stead of " Nobody is  viewing".  You can sp ecify an e xplicit nu mber rule  for
  23810    * other n umbers, fo r example  12, so tha t instead  of showing  "12 peopl e are view ing", you  can
  23811    * show "a  dozen peo ple are vi ewing".
  23812    *
  23813    * You can  use a set  of closed  braces (` {}`) as a  placeholde r for the  number tha t you want  substitut ed
  23814    * into pl uralized s trings. In  the previ ous exampl e, Angular  will repl ace `{}` w ith
  23815    * <span n g-non-bind able>`{{pe rsonCount} }`</span>.  The close d braces ` {}` is a p laceholder
  23816    * for <sp an ng-non- bindable>{ {numberExp ression}}< /span>.
  23817    *
  23818    * # Confi guring ngP luralize w ith offset
  23819    * The `of fset` attr ibute allo ws further  customiza tion of pl uralized t ext, which  can resul t in
  23820    * a bette r user exp erience. F or example , instead  of the mes sage "4 pe ople are v iewing thi s document ",
  23821    * you mig ht display  "John, Ka te and 2 o thers are  viewing th is documen t".
  23822    * The off set attrib ute allows  you to of fset a num ber by any  desired v alue.
  23823    * Let's t ake a look  at an exa mple:
  23824    *
  23825    * ```html
  23826    * <ng-plu ralize cou nt="person Count" off set=2
  23827    *                whe n="{'0': ' Nobody is  viewing.',
  23828    *                        '1': ' {{person1} } is viewi ng.',
  23829    *                        '2': ' {{person1} } and {{pe rson2}} ar e viewing. ',
  23830    *                        'one':  '{{person 1}}, {{per son2}} and  one other  person ar e viewing. ',
  23831    *                        'other ': '{{pers on1}}, {{p erson2}} a nd {} othe r people a re viewing .'}">
  23832    * </ng-pl uralize>
  23833    * ```
  23834    *
  23835    * Notice  that we ar e still us ing two pl ural categ ories(one,  other), b ut we adde d
  23836    * three e xplicit nu mber rules  0, 1 and  2.
  23837    * When on e person,  perhaps Jo hn, views  the docume nt, "John  is viewing " will be  shown.
  23838    * When th ree people  view the  document,  no explici t number r ule is fou nd, so
  23839    * an offs et of 2 is  taken off  3, and An gular uses  1 to deci de the plu ral catego ry.
  23840    * In this  case, plu ral catego ry 'one' i s matched  and "John,  Mary and  one other  person are  viewing"
  23841    * is show n.
  23842    *
  23843    * Note th at when yo u specify  offsets, y ou must pr ovide expl icit numbe r rules fo r
  23844    * numbers  from 0 up  to and in cluding th e offset.  If you use  an offset  of 3, for  example,
  23845    * you mus t provide  explicit n umber rule s for 0, 1 , 2 and 3.  You must  also provi de plural  strings fo r
  23846    * plural  categories  "one" and  "other".
  23847    *
  23848    * @param  {string|ex pression}  count The  variable t o be bound  to.
  23849    * @param  {string} w hen The ma pping betw een plural  category  to its cor responding  strings.
  23850    * @param  {number=}  offset Off set to ded uct from t he total n umber.
  23851    *
  23852    * @exampl e
  23853       <examp le module= "pluralize Example">
  23854         <fil e name="in dex.html">
  23855           <s cript>
  23856              angular.mo dule('plur alizeExamp le', [])
  23857                .control ler('Examp leControll er', ['$sc ope', func tion($scop e) {
  23858                  $scope .person1 =  'Igor';
  23859                  $scope .person2 =  'Misko';
  23860                  $scope .personCou nt = 1;
  23861                }]);
  23862           </ script>
  23863           <d iv ng-cont roller="Ex ampleContr oller">
  23864              Person 1:< input type ="text" ng -model="pe rson1" val ue="Igor"  /><br/>
  23865              Person 2:< input type ="text" ng -model="pe rson2" val ue="Misko"  /><br/>
  23866              Number of  People:<in put type=" text" ng-m odel="pers onCount" v alue="1" / ><br/>
  23867  
  23868              <!--- Exam ple with s imple plur alization  rules for  en locale  --->
  23869              Without Of fset:
  23870              <ng-plural ize count= "personCou nt"
  23871                             when=" {'0': 'Nob ody is vie wing.',
  23872                                     'one': '1  person is  viewing.' ,
  23873                                     'other':  '{} people  are viewi ng.'}">
  23874              </ng-plura lize><br>
  23875  
  23876              <!--- Exam ple with o ffset --->
  23877              With Offse t(2):
  23878              <ng-plural ize count= "personCou nt" offset =2
  23879                             when=" {'0': 'Nob ody is vie wing.',
  23880                                     '1': '{{p erson1}} i s viewing. ',
  23881                                     '2': '{{p erson1}} a nd {{perso n2}} are v iewing.',
  23882                                     'one': '{ {person1}} , {{person 2}} and on e other pe rson are v iewing.',
  23883                                     'other':  '{{person1 }}, {{pers on2}} and  {} other p eople are  viewing.'} ">
  23884              </ng-plura lize>
  23885           </ div>
  23886         </fi le>
  23887         <fil e name="pr otractor.j s" type="p rotractor" >
  23888           it ('should s how correc t pluraliz ed string' , function () {
  23889              var withou tOffset =  element.al l(by.css(' ng-plurali ze')).get( 0);
  23890              var withOf fset = ele ment.all(b y.css('ng- pluralize' )).get(1);
  23891              var countI nput = ele ment(by.mo del('perso nCount'));
  23892  
  23893              expect(wit houtOffset .getText() ).toEqual( '1 person  is viewing .');
  23894              expect(wit hOffset.ge tText()).t oEqual('Ig or is view ing.');
  23895  
  23896              countInput .clear();
  23897              countInput .sendKeys( '0');
  23898  
  23899              expect(wit houtOffset .getText() ).toEqual( 'Nobody is  viewing.' );
  23900              expect(wit hOffset.ge tText()).t oEqual('No body is vi ewing.');
  23901  
  23902              countInput .clear();
  23903              countInput .sendKeys( '2');
  23904  
  23905              expect(wit houtOffset .getText() ).toEqual( '2 people  are viewin g.');
  23906              expect(wit hOffset.ge tText()).t oEqual('Ig or and Mis ko are vie wing.');
  23907  
  23908              countInput .clear();
  23909              countInput .sendKeys( '3');
  23910  
  23911              expect(wit houtOffset .getText() ).toEqual( '3 people  are viewin g.');
  23912              expect(wit hOffset.ge tText()).t oEqual('Ig or, Misko  and one ot her person  are viewi ng.');
  23913  
  23914              countInput .clear();
  23915              countInput .sendKeys( '4');
  23916  
  23917              expect(wit houtOffset .getText() ).toEqual( '4 people  are viewin g.');
  23918              expect(wit hOffset.ge tText()).t oEqual('Ig or, Misko  and 2 othe r people a re viewing .');
  23919           }) ;
  23920           it ('should s how data-b ound names ', functio n() {
  23921              var withOf fset = ele ment.all(b y.css('ng- pluralize' )).get(1);
  23922              var person Count = el ement(by.m odel('pers onCount')) ;
  23923              var person 1 = elemen t(by.model ('person1' ));
  23924              var person 2 = elemen t(by.model ('person2' ));
  23925              personCoun t.clear();
  23926              personCoun t.sendKeys ('4');
  23927              person1.cl ear();
  23928              person1.se ndKeys('Di ');
  23929              person2.cl ear();
  23930              person2.se ndKeys('Vo jta');
  23931              expect(wit hOffset.ge tText()).t oEqual('Di , Vojta an d 2 other  people are  viewing.' );
  23932           }) ;
  23933         </fi le>
  23934       </exam ple>
  23935    */
  23936   var ngPlur alizeDirec tive = ['$ locale', ' $interpola te', funct ion($local e, $interp olate) {
  23937     var BRAC E = /{}/g,
  23938         IS_W HEN = /^wh en(Minus)? (.+)$/;
  23939  
  23940     return {
  23941       restri ct: 'EA',
  23942       link:  function(s cope, elem ent, attr)  {
  23943         var  numberExp  = attr.cou nt,
  23944              whenExp =  attr.$attr .when && e lement.att r(attr.$at tr.when),  // we have  {{}} in a ttrs
  23945              offset = a ttr.offset  || 0,
  23946              whens = sc ope.$eval( whenExp) | | {},
  23947              whensExpFn s = {},
  23948              startSymbo l = $inter polate.sta rtSymbol() ,
  23949              endSymbol  = $interpo late.endSy mbol(),
  23950              braceRepla cement = s tartSymbol  + numberE xp + '-' +  offset +  endSymbol,
  23951              watchRemov er = angul ar.noop,
  23952              lastCount;
  23953  
  23954         forE ach(attr,  function(e xpression,  attribute Name) {
  23955           va r tmpMatch  = IS_WHEN .exec(attr ibuteName) ;
  23956           if  (tmpMatch ) {
  23957              var whenKe y = (tmpMa tch[1] ? ' -' : '') +  lowercase (tmpMatch[ 2]);
  23958              whens[when Key] = ele ment.attr( attr.$attr [attribute Name]);
  23959           }
  23960         });
  23961         forE ach(whens,  function( expression , key) {
  23962           wh ensExpFns[ key] = $in terpolate( expression .replace(B RACE, brac eReplaceme nt));
  23963  
  23964         });
  23965  
  23966         scop e.$watch(n umberExp,  function n gPluralize WatchActio n(newVal)  {
  23967           va r count =  parseFloat (newVal);
  23968           va r countIsN aN = isNaN (count);
  23969  
  23970           if  (!countIs NaN && !(c ount in wh ens)) {
  23971              // If an e xplicit nu mber rule  such as 1,  2, 3... i s defined,  just use  it.
  23972              // Otherwi se, check  it against  pluraliza tion rules  in $local e service.
  23973              count = $l ocale.plur alCat(coun t - offset );
  23974           }
  23975  
  23976           //  If both ` count` and  `lastCoun t` are NaN , we don't  need to r e-register  a watch.
  23977           //  In JS `Na N !== NaN` , so we ha ve to exli citly chec k.
  23978           if  ((count ! == lastCou nt) && !(c ountIsNaN  && isNaN(l astCount)) ) {
  23979              watchRemov er();
  23980              watchRemov er = scope .$watch(wh ensExpFns[ count], up dateElemen tText);
  23981              lastCount  = count;
  23982           }
  23983         });
  23984  
  23985         func tion updat eElementTe xt(newText ) {
  23986           el ement.text (newText | | '');
  23987         }
  23988       }
  23989     };
  23990   }];
  23991  
  23992   /**
  23993    * @ngdoc  directive
  23994    * @name n gRepeat
  23995    *
  23996    * @descri ption
  23997    * The `ng Repeat` di rective in stantiates  a templat e once per  item from  a collect ion. Each  template
  23998    * instanc e gets its  own scope , where th e given lo op variabl e is set t o the curr ent collec tion item,
  23999    * and `$i ndex` is s et to the  item index  or key.
  24000    *
  24001    * Special  propertie s are expo sed on the  local sco pe of each  template  instance,  including:
  24002    *
  24003    * | Varia ble  | Typ e             | Detai ls                                                                            |
  24004    * |------ -----|---- ---------- ---|------ ---------- ---------- ---------- ---------- ---------- ---------- ---------- -|
  24005    * | `$ind ex`  | {@t ype number }  | itera tor offset  of the re peated ele ment (0..l ength-1)                          |
  24006    * | `$fir st`  | {@t ype boolea n} | true  if the rep eated elem ent is fir st in the  iterator.                         |
  24007    * | `$mid dle` | {@t ype boolea n} | true  if the rep eated elem ent is bet ween the f irst and l ast in the  iterator.  |
  24008    * | `$las t`   | {@t ype boolea n} | true  if the rep eated elem ent is las t in the i terator.                          |
  24009    * | `$eve n`   | {@t ype boolea n} | true  if the ite rator posi tion `$ind ex` is eve n (otherwi se false).             |
  24010    * | `$odd `    | {@t ype boolea n} | true  if the ite rator posi tion `$ind ex` is odd  (otherwis e false).              |
  24011    *
  24012    * Creatin g aliases  for these  properties  is possib le with {@ link ng.di rective:ng Init `ngIn it`}.
  24013    * This ma y be usefu l when, fo r instance , nesting  ngRepeats.
  24014    *
  24015    * # Speci al repeat  start and  end points
  24016    * To repe at a serie s of eleme nts instea d of just  one parent  element,  ngRepeat ( as well as  other ng  directives ) supports  extending
  24017    * the ran ge of the  repeater b y defining  explicit  start and  end points  by using  **ng-repea t-start**  and **ng-r epeat-end* * respecti vely.
  24018    * The **n g-repeat-s tart** dir ective wor ks the sam e as **ng- repeat**,  but will r epeat all  the HTML c ode (inclu ding the t ag it's de fined on)
  24019    * up to a nd includi ng the end ing HTML t ag where * *ng-repeat -end** is  placed.
  24020    *
  24021    * The exa mple below  makes use  of this f eature:
  24022    * ```html
  24023    *   <head er ng-repe at-start=" item in it ems">
  24024    *     Hea der {{ ite m }}
  24025    *   </hea der>
  24026    *   <div  class="bod y">
  24027    *     Bod y {{ item  }}
  24028    *   </div >
  24029    *   <foot er ng-repe at-end>
  24030    *     Foo ter {{ ite m }}
  24031    *   </foo ter>
  24032    * ```
  24033    *
  24034    * And wit h an input  of {@type  ['A','B'] } for the  items vari able in th e example  above, the  output wi ll evaluat e to:
  24035    * ```html
  24036    *   <head er>
  24037    *     Hea der A
  24038    *   </hea der>
  24039    *   <div  class="bod y">
  24040    *     Bod y A
  24041    *   </div >
  24042    *   <foot er>
  24043    *     Foo ter A
  24044    *   </foo ter>
  24045    *   <head er>
  24046    *     Hea der B
  24047    *   </hea der>
  24048    *   <div  class="bod y">
  24049    *     Bod y B
  24050    *   </div >
  24051    *   <foot er>
  24052    *     Foo ter B
  24053    *   </foo ter>
  24054    * ```
  24055    *
  24056    * The cus tom start  and end po ints for n gRepeat al so support  all other  HTML dire ctive synt ax flavors  provided  in Angular JS (such
  24057    * as **da ta-ng-repe at-start** , **x-ng-r epeat-star t** and ** ng:repeat- start**).
  24058    *
  24059    * @animat ions
  24060    * **.ente r** - when  a new ite m is added  to the li st or when  an item i s revealed  after a f ilter
  24061    *
  24062    * **.leav e** - when  an item i s removed  from the l ist or whe n an item  is filtere d out
  24063    *
  24064    * **.move ** - when  an adjacen t item is  filtered o ut causing  a reorder  or when t he item co ntents are  reordered
  24065    *
  24066    * @elemen t ANY
  24067    * @scope
  24068    * @priori ty 1000
  24069    * @param  {repeat_ex pression}  ngRepeat T he express ion indica ting how t o enumerat e a collec tion. Thes e
  24070    *   forma ts are cur rently sup ported:
  24071    *
  24072    *   * `va riable in  expression ` â€“ wher e variable  is the us er defined  loop vari able and ` expression `
  24073    *     is  a scope ex pression g iving the  collection  to enumer ate.
  24074    *
  24075    *     For  example:  `album in  artist.alb ums`.
  24076    *
  24077    *   * `(k ey, value)  in expres sion` â€“  where `key ` and `val ue` can be  any user  defined id entifiers,
  24078    *     and  `expressi on` is the  scope exp ression gi ving the c ollection  to enumera te.
  24079    *
  24080    *     For  example:  `(name, ag e) in {'ad am':10, 'a malie':12} `.
  24081    *
  24082    *   * `va riable in  expression  track by  tracking_e xpression`  â€“ You c an also pr ovide an o ptional tr acking fun ction
  24083    *     whi ch can be  used to as sociate th e objects  in the col lection wi th the DOM  elements.  If no tra cking func tion
  24084    *     is  specified  the ng-rep eat associ ates eleme nts by ide ntity in t he collect ion. It is  an error  to have
  24085    *     mor e than one  tracking  function t o resolve  to the sam e key. (Th is would m ean that t wo distinc t objects  are
  24086    *     map ped to the  same DOM  element, w hich is no t possible .)  Filter s should b e applied  to the exp ression,
  24087    *     bef ore specif ying a tra cking expr ession.
  24088    *
  24089    *     For  example:  `item in i tems` is e quivalent  to `item i n items tr ack by $id (item)`. T his implie s that the  DOM eleme nts
  24090    *     wil l be assoc iated by i tem identi ty in the  array.
  24091    *
  24092    *     For  example:  `item in i tems track  by $id(it em)`. A bu ilt in `$i d()` funct ion can be  used to a ssign a un ique
  24093    *     `$$ hashKey` p roperty to  each item  in the ar ray. This  property i s then use d as a key  to associ ated DOM e lements
  24094    *     wit h the corr esponding  item in th e array by  identity.  Moving th e same obj ect in arr ay would m ove the DO M
  24095    *     ele ment in th e same way  in the DO M.
  24096    *
  24097    *     For  example:  `item in i tems track  by item.i d` is a ty pical patt ern when t he items c ome from t he databas e. In this
  24098    *     cas e the obje ct identit y does not  matter. T wo objects  are consi dered equi valent as  long as th eir `id`
  24099    *     pro perty is s ame.
  24100    *
  24101    *     For  example:  `item in i tems | fil ter:search Text track  by item.i d` is a pa ttern that  might be  used to ap ply a filt er
  24102    *     to  items in c onjunction  with a tr acking exp ression.
  24103    *
  24104    *   * `va riable in  expression  as alias_ expression ` â€“ You  can also p rovide an  optional a lias expre ssion whic h will the n store th e
  24105    *     int ermediate  results of  the repea ter after  the filter s have bee n applied.  Typically  this is u sed to ren der a spec ial messag e
  24106    *     whe n a filter  is active  on the re peater, bu t the filt ered resul t set is e mpty.
  24107    *
  24108    *     For  example:  `item in i tems | fil ter:x as r esults` wi ll store t he fragmen t of the r epeated it ems as `re sults`, bu t only aft er
  24109    *     the  items hav e been pro cessed thr ough the f ilter.
  24110    *
  24111    * @exampl e
  24112    * This ex ample init ializes th e scope to  a list of  names and
  24113    * then us es `ngRepe at` to dis play every  person:
  24114     <example  module="n gAnimate"  deps="angu lar-animat e.js" anim ations="tr ue">
  24115       <file  name="inde x.html">
  24116         <div  ng-init=" friends =  [
  24117           {n ame:'John' , age:25,  gender:'bo y'},
  24118           {n ame:'Jessi e', age:30 , gender:' girl'},
  24119           {n ame:'Johan na', age:2 8, gender: 'girl'},
  24120           {n ame:'Joy',  age:15, g ender:'gir l'},
  24121           {n ame:'Mary' , age:28,  gender:'gi rl'},
  24122           {n ame:'Peter ', age:95,  gender:'b oy'},
  24123           {n ame:'Sebas tian', age :50, gende r:'boy'},
  24124           {n ame:'Erika ', age:27,  gender:'g irl'},
  24125           {n ame:'Patri ck', age:4 0, gender: 'boy'},
  24126           {n ame:'Saman tha', age: 60, gender :'girl'}
  24127         ]">
  24128           I  have {{fri ends.lengt h}} friend s. They ar e:
  24129           <i nput type= "search" n g-model="q " placehol der="filte r friends. .." />
  24130           <u l class="e xample-ani mate-conta iner">
  24131              <li class= "animate-r epeat" ng- repeat="fr iend in fr iends | fi lter:q as  results">
  24132                [{{$inde x + 1}}] { {friend.na me}} who i s {{friend .age}} yea rs old.
  24133              </li>
  24134              <li class= "animate-r epeat" ng- if="result s.length = = 0">
  24135                <strong> No results  found...< /strong>
  24136              </li>
  24137           </ ul>
  24138         </di v>
  24139       </file >
  24140       <file  name="anim ations.css ">
  24141         .exa mple-anima te-contain er {
  24142           ba ckground:w hite;
  24143           bo rder:1px s olid black ;
  24144           li st-style:n one;
  24145           ma rgin:0;
  24146           pa dding:0 10 px;
  24147         }
  24148  
  24149         .ani mate-repea t {
  24150           li ne-height: 40px;
  24151           li st-style:n one;
  24152           bo x-sizing:b order-box;
  24153         }
  24154  
  24155         .ani mate-repea t.ng-move,
  24156         .ani mate-repea t.ng-enter ,
  24157         .ani mate-repea t.ng-leave  {
  24158           -w ebkit-tran sition:all  linear 0. 5s;
  24159           tr ansition:a ll linear  0.5s;
  24160         }
  24161  
  24162         .ani mate-repea t.ng-leave .ng-leave- active,
  24163         .ani mate-repea t.ng-move,
  24164         .ani mate-repea t.ng-enter  {
  24165           op acity:0;
  24166           ma x-height:0 ;
  24167         }
  24168  
  24169         .ani mate-repea t.ng-leave ,
  24170         .ani mate-repea t.ng-move. ng-move-ac tive,
  24171         .ani mate-repea t.ng-enter .ng-enter- active {
  24172           op acity:1;
  24173           ma x-height:4 0px;
  24174         }
  24175       </file >
  24176       <file  name="prot ractor.js"  type="pro tractor">
  24177         var  friends =  element.al l(by.repea ter('frien d in frien ds'));
  24178  
  24179         it(' should ren der initia l data set ', functio n() {
  24180           ex pect(frien ds.count() ).toBe(10) ;
  24181           ex pect(frien ds.get(0). getText()) .toEqual(' [1] John w ho is 25 y ears old.' );
  24182           ex pect(frien ds.get(1). getText()) .toEqual(' [2] Jessie  who is 30  years old .');
  24183           ex pect(frien ds.last(). getText()) .toEqual(' [10] Saman tha who is  60 years  old.');
  24184           ex pect(eleme nt(by.bind ing('frien ds.length' )).getText ())
  24185                .toMatch ("I have 1 0 friends.  They are: ");
  24186         });
  24187  
  24188          it( 'should up date repea ter when f ilter pred icate chan ges', func tion() {
  24189            e xpect(frie nds.count( )).toBe(10 );
  24190  
  24191            e lement(by. model('q') ).sendKeys ('ma');
  24192  
  24193            e xpect(frie nds.count( )).toBe(2) ;
  24194            e xpect(frie nds.get(0) .getText() ).toEqual( '[1] Mary  who is 28  years old. ');
  24195            e xpect(frie nds.last() .getText() ).toEqual( '[2] Saman tha who is  60 years  old.');
  24196          });
  24197         </fi le>
  24198       </exam ple>
  24199    */
  24200   var ngRepe atDirectiv e = ['$par se', '$ani mate', fun ction($par se, $anima te) {
  24201     var NG_R EMOVED = ' $$NG_REMOV ED';
  24202     var ngRe peatMinErr  = minErr( 'ngRepeat' );
  24203  
  24204     var upda teScope =  function(s cope, inde x, valueId entifier,  value, key Identifier , key, arr ayLength)  {
  24205       // TOD O(perf): g enerate se tters to s have off ~ 40ms or 1- 1.5%
  24206       scope[ valueIdent ifier] = v alue;
  24207       if (ke yIdentifie r) scope[k eyIdentifi er] = key;
  24208       scope. $index = i ndex;
  24209       scope. $first = ( index ===  0);
  24210       scope. $last = (i ndex === ( arrayLengt h - 1));
  24211       scope. $middle =  !(scope.$f irst || sc ope.$last) ;
  24212       // jsh int bitwis e: false
  24213       scope. $odd = !(s cope.$even  = (index& 1) === 0);
  24214       // jsh int bitwis e: true
  24215     };
  24216  
  24217     var getB lockStart  = function (block) {
  24218       return  block.clo ne[0];
  24219     };
  24220  
  24221     var getB lockEnd =  function(b lock) {
  24222       return  block.clo ne[block.c lone.lengt h - 1];
  24223     };
  24224  
  24225  
  24226     return {
  24227       restri ct: 'A',
  24228       multiE lement: tr ue,
  24229       transc lude: 'ele ment',
  24230       priori ty: 1000,
  24231       termin al: true,
  24232       $$tlb:  true,
  24233       compil e: functio n ngRepeat Compile($e lement, $a ttr) {
  24234         var  expression  = $attr.n gRepeat;
  24235         var  ngRepeatEn dComment =  document. createComm ent(' end  ngRepeat:  ' + expres sion + ' ' );
  24236  
  24237         var  match = ex pression.m atch(/^\s* ([\s\S]+?) \s+in\s+([ \s\S]+?)(? :\s+as\s+( [\s\S]+?)) ?(?:\s+tra ck\s+by\s+ ([\s\S]+?) )?\s*$/);
  24238  
  24239         if ( !match) {
  24240           th row ngRepe atMinErr(' iexp', "Ex pected exp ression in  form of ' _item_ in  _collectio n_[ track  by _id_]'  but got '{ 0}'.",
  24241                expressi on);
  24242         }
  24243  
  24244         var  lhs = matc h[1];
  24245         var  rhs = matc h[2];
  24246         var  aliasAs =  match[3];
  24247         var  trackByExp  = match[4 ];
  24248  
  24249         matc h = lhs.ma tch(/^(?:( [\$\w]+)|\ (([\$\w]+) \s*,\s*([\ $\w]+)\))$ /);
  24250  
  24251         if ( !match) {
  24252           th row ngRepe atMinErr(' iidexp', " '_item_' i n '_item_  in _collec tion_' sho uld be an  identifier  or '(_key _, _value_ )' express ion, but g ot '{0}'." ,
  24253                lhs);
  24254         }
  24255         var  valueIdent ifier = ma tch[3] ||  match[1];
  24256         var  keyIdentif ier = matc h[2];
  24257  
  24258         if ( aliasAs &&  (!/^[$a-z A-Z_][$a-z A-Z0-9_]*$ /.test(ali asAs) ||
  24259              /^(null|un defined|th is|\$index |\$first|\ $middle|\$ last|\$eve n|\$odd|\$ parent)$/. test(alias As))) {
  24260           th row ngRepe atMinErr(' badident',  "alias '{ 0}' is inv alid --- m ust be a v alid JS id entifier w hich is no t a reserv ed name.",
  24261              aliasAs);
  24262         }
  24263  
  24264         var  trackByExp Getter, tr ackByIdExp Fn, trackB yIdArrayFn , trackByI dObjFn;
  24265         var  hashFnLoca ls = {$id:  hashKey};
  24266  
  24267         if ( trackByExp ) {
  24268           tr ackByExpGe tter = $pa rse(trackB yExp);
  24269         } el se {
  24270           tr ackByIdArr ayFn = fun ction(key,  value) {
  24271              return has hKey(value );
  24272           };
  24273           tr ackByIdObj Fn = funct ion(key) {
  24274              return key ;
  24275           };
  24276         }
  24277  
  24278         retu rn functio n ngRepeat Link($scop e, $elemen t, $attr,  ctrl, $tra nsclude) {
  24279  
  24280           if  (trackByE xpGetter)  {
  24281              trackByIdE xpFn = fun ction(key,  value, in dex) {
  24282                // assig n key, val ue, and $i ndex to th e locals s o that the y can be u sed in has h function s
  24283                if (keyI dentifier)  hashFnLoc als[keyIde ntifier] =  key;
  24284                hashFnLo cals[value Identifier ] = value;
  24285                hashFnLo cals.$inde x = index;
  24286                return t rackByExpG etter($sco pe, hashFn Locals);
  24287              };
  24288           }
  24289  
  24290           //  Store a l ist of ele ments from  previous  run. This  is a hash  where key  is the ite m from the
  24291           //  iterator,  and the v alue is ob jects with  following  propertie s.
  24292           //    - scope : bound sc ope
  24293           //    - eleme nt: previo us element .
  24294           //    - index : position
  24295           //
  24296           //  We are us ing no-pro to object  so that we  don't nee d to guard  against i nherited p rops via
  24297           //  hasOwnPro perty.
  24298           va r lastBloc kMap = cre ateMap();
  24299  
  24300           // watch prop s
  24301           $s cope.$watc hCollectio n(rhs, fun ction ngRe peatAction (collectio n) {
  24302              var index,  length,
  24303                  previo usNode = $ element[0] ,     // n ode that c loned node s should b e inserted  after
  24304                                                     // i nitialized  to the co mment node  anchor
  24305                  nextNo de,
  24306                  // Sam e as lastB lockMap bu t it has t he current  state. It  will beco me the
  24307                  // las tBlockMap  on the nex t iteratio n.
  24308                  nextBl ockMap = c reateMap() ,
  24309                  collec tionLength ,
  24310                  key, v alue, // k ey/value o f iteratio n
  24311                  trackB yId,
  24312                  trackB yIdFn,
  24313                  collec tionKeys,
  24314                  block,        //  last objec t informat ion {scope , element,  id}
  24315                  nextBl ockOrder,
  24316                  elemen tsToRemove ;
  24317  
  24318              if (aliasA s) {
  24319                $scope[a liasAs] =  collection ;
  24320              }
  24321  
  24322              if (isArra yLike(coll ection)) {
  24323                collecti onKeys = c ollection;
  24324                trackByI dFn = trac kByIdExpFn  || trackB yIdArrayFn ;
  24325              } else {
  24326                trackByI dFn = trac kByIdExpFn  || trackB yIdObjFn;
  24327                // if ob ject, extr act keys,  sort them  and use to  determine  order of  iteration  over obj p rops
  24328                collecti onKeys = [ ];
  24329                for (var  itemKey i n collecti on) {
  24330                  if (co llection.h asOwnPrope rty(itemKe y) && item Key.charAt (0) != '$' ) {
  24331                    coll ectionKeys .push(item Key);
  24332                  }
  24333                }
  24334                collecti onKeys.sor t();
  24335              }
  24336  
  24337              collection Length = c ollectionK eys.length ;
  24338              nextBlockO rder = new  Array(col lectionLen gth);
  24339  
  24340              // locate  existing i tems
  24341              for (index  = 0; inde x < collec tionLength ; index++)  {
  24342                key = (c ollection  === collec tionKeys)  ? index :  collection Keys[index ];
  24343                value =  collection [key];
  24344                trackByI d = trackB yIdFn(key,  value, in dex);
  24345                if (last BlockMap[t rackById])  {
  24346                  // fou nd previou sly seen b lock
  24347                  block  = lastBloc kMap[track ById];
  24348                  delete  lastBlock Map[trackB yId];
  24349                  nextBl ockMap[tra ckById] =  block;
  24350                  nextBl ockOrder[i ndex] = bl ock;
  24351                } else i f (nextBlo ckMap[trac kById]) {
  24352                  // if  collision  detected.  restore la stBlockMap  and throw  an error
  24353                  forEac h(nextBloc kOrder, fu nction(blo ck) {
  24354                    if ( block && b lock.scope ) lastBloc kMap[block .id] = blo ck;
  24355                  });
  24356                  throw  ngRepeatMi nErr('dupe s',
  24357                      "D uplicates  in a repea ter are no t allowed.  Use 'trac k by' expr ession to  specify un ique keys.  Repeater:  {0}, Dupl icate key:  {1}, Dupl icate valu e: {2}",
  24358                      ex pression,  trackById,  value);
  24359                } else {
  24360                  // new  never bef ore seen b lock
  24361                  nextBl ockOrder[i ndex] = {i d: trackBy Id, scope:  undefined , clone: u ndefined};
  24362                  nextBl ockMap[tra ckById] =  true;
  24363                }
  24364              }
  24365  
  24366              // remove  leftover i tems
  24367              for (var b lockKey in  lastBlock Map) {
  24368                block =  lastBlockM ap[blockKe y];
  24369                elements ToRemove =  getBlockN odes(block .clone);
  24370                $animate .leave(ele mentsToRem ove);
  24371                if (elem entsToRemo ve[0].pare ntNode) {
  24372                  // if  the elemen t was not  removed ye t because  of pending  animation , mark it  as deleted
  24373                  // so  that we ca n ignore i t later
  24374                  for (i ndex = 0,  length = e lementsToR emove.leng th; index  < length;  index++) {
  24375                    elem entsToRemo ve[index][ NG_REMOVED ] = true;
  24376                  }
  24377                }
  24378                block.sc ope.$destr oy();
  24379              }
  24380  
  24381              // we are  not using  forEach fo r perf rea sons (tryi ng to avoi d #call)
  24382              for (index  = 0; inde x < collec tionLength ; index++)  {
  24383                key = (c ollection  === collec tionKeys)  ? index :  collection Keys[index ];
  24384                value =  collection [key];
  24385                block =  nextBlockO rder[index ];
  24386  
  24387                if (bloc k.scope) {
  24388                  // if  we have al ready seen  this obje ct, then w e need to  reuse the
  24389                  // ass ociated sc ope/elemen t
  24390  
  24391                  nextNo de = previ ousNode;
  24392  
  24393                  // ski p nodes th at are alr eady pendi ng removal  via leave  animation
  24394                  do {
  24395                    next Node = nex tNode.next Sibling;
  24396                  } whil e (nextNod e && nextN ode[NG_REM OVED]);
  24397  
  24398                  if (ge tBlockStar t(block) ! = nextNode ) {
  24399                    // e xisting it em which g ot moved
  24400                    $ani mate.move( getBlockNo des(block. clone), nu ll, jqLite (previousN ode));
  24401                  }
  24402                  previo usNode = g etBlockEnd (block);
  24403                  update Scope(bloc k.scope, i ndex, valu eIdentifie r, value,  keyIdentif ier, key,  collection Length);
  24404                } else {
  24405                  // new  item whic h we don't  know abou t
  24406                  $trans clude(func tion ngRep eatTranscl ude(clone,  scope) {
  24407                    bloc k.scope =  scope;
  24408                    // h ttp://jspe rf.com/clo ne-vs-crea tecomment
  24409                    var  endNode =  ngRepeatEn dComment.c loneNode(f alse);
  24410                    clon e[clone.le ngth++] =  endNode;
  24411  
  24412                    // T ODO(perf):  support n aked previ ousNode in  `enter` t o avoid cr eation of  jqLite wra pper?
  24413                    $ani mate.enter (clone, nu ll, jqLite (previousN ode));
  24414                    prev iousNode =  endNode;
  24415                    // N ote: We on ly need th e first/la st node of  the clone d nodes.
  24416                    // H owever, we  need to k eep the re ference to  the jqlit e wrapper  as it migh t be chang ed later
  24417                    // b y a direct ive with t emplateUrl  when its  template a rrives.
  24418                    bloc k.clone =  clone;
  24419                    next BlockMap[b lock.id] =  block;
  24420                    upda teScope(bl ock.scope,  index, va lueIdentif ier, value , keyIdent ifier, key , collecti onLength);
  24421                  });
  24422                }
  24423              }
  24424              lastBlockM ap = nextB lockMap;
  24425           }) ;
  24426         };
  24427       }
  24428     };
  24429   }];
  24430  
  24431   var NG_HID E_CLASS =  'ng-hide';
  24432   var NG_HID E_IN_PROGR ESS_CLASS  = 'ng-hide -animate';
  24433   /**
  24434    * @ngdoc  directive
  24435    * @name n gShow
  24436    *
  24437    * @descri ption
  24438    * The `ng Show` dire ctive show s or hides  the given  HTML elem ent based  on the exp ression
  24439    * provide d to the ` ngShow` at tribute. T he element  is shown  or hidden  by removin g or addin g
  24440    * the `.n g-hide` CS S class on to the ele ment. The  `.ng-hide`  CSS class  is predef ined
  24441    * in Angu larJS and  sets the d isplay sty le to none  (using an  !importan t flag).
  24442    * For CSP  mode plea se add `an gular-csp. css` to yo ur html fi le (see {@ link ng.di rective:ng Csp ngCsp} ).
  24443    *
  24444    * ```html
  24445    * <!-- wh en $scope. myValue is  truthy (e lement is  visible) - ->
  24446    * <div ng -show="myV alue"></di v>
  24447    *
  24448    * <!-- wh en $scope. myValue is  falsy (el ement is h idden) -->
  24449    * <div ng -show="myV alue" clas s="ng-hide "></div>
  24450    * ```
  24451    *
  24452    * When th e `ngShow`  expressio n evaluate s to a fal sy value t hen the `. ng-hide` C SS class i s added to  the class
  24453    * attribu te on the  element ca using it t o become h idden. Whe n truthy,  the `.ng-h ide` CSS c lass is re moved
  24454    * from th e element  causing th e element  not to app ear hidden .
  24455    *
  24456    * ## Why  is !import ant used?
  24457    *
  24458    * You may  be wonder ing why !i mportant i s used for  the `.ng- hide` CSS  class. Thi s is becau se the `.n g-hide` se lector
  24459    * can be  easily ove rridden by  heavier s electors.  For exampl e, somethi ng as simp le
  24460    * as chan ging the d isplay sty le on a HT ML list it em would m ake hidden  elements  appear vis ible.
  24461    * This al so becomes  a bigger  issue when  dealing w ith CSS fr ameworks.
  24462    *
  24463    * By usin g !importa nt, the sh ow and hid e behavior  will work  as expect ed despite  any clash  between C SS selecto r
  24464    * specifi city (when  !importan t isn't us ed with an y conflict ing styles ). If a de veloper ch ooses to o verride th e
  24465    * styling  to change  how to hi de an elem ent then i t is just  a matter o f using !i mportant i n their ow n CSS code .
  24466    *
  24467    * ### Ove rriding `. ng-hide`
  24468    *
  24469    * By defa ult, the ` .ng-hide`  class will  style the  element w ith `displ ay: none!i mportant`.  If you wi sh to chan ge
  24470    * the hid e behavior  with ngSh ow/ngHide  then this  can be ach ieved by r estating t he styles  for the `. ng-hide`
  24471    * class i n CSS:
  24472    *
  24473    * ```css
  24474    * .ng-hid e {
  24475    *   /&#42 ; this is  just anoth er form of  hiding an  element & #42;/
  24476    *   displ ay: block! important;
  24477    *   posit ion: absol ute;
  24478    *   top:  -9999px;
  24479    *   left:  -9999px;
  24480    * }
  24481    * ```
  24482    *
  24483    * By defa ult you do n't need t o override  in CSS an ything and  the anima tions will  work arou nd the dis play style .
  24484    *
  24485    * ## A no te about a nimations  with `ngSh ow`
  24486    *
  24487    * Animati ons in ngS how/ngHide  work with  the show  and hide e vents that  are trigg ered when  the direct ive expres sion
  24488    * is true  and false . This sys tem works  like the a nimation s ystem pres ent with n gClass exc ept that
  24489    * you mus t also inc lude the ! important  flag to ov erride the  display p roperty
  24490    * so that  you can p erform an  animation  when the e lement is  hidden dur ing the ti me of the  animation.
  24491    *
  24492    * ```css
  24493    * //
  24494    * //a wor king examp le can be  found at t he bottom  of this pa ge
  24495    * //
  24496    * .my-ele ment.ng-hi de-add, .m y-element. ng-hide-re move {
  24497    *   /&#42 ; this is  required a s of 1.3x  to properl y
  24498    *      ap ply all st yling in a  show/hide  animation  &#42;/
  24499    *   trans ition: 0s  linear all ;
  24500    * }
  24501    *
  24502    * .my-ele ment.ng-hi de-add-act ive,
  24503    * .my-ele ment.ng-hi de-remove- active {
  24504    *   /&#42 ; the tran sition is  defined in  the activ e class &# 42;/
  24505    *   trans ition: 1s  linear all ;
  24506    * }
  24507    *
  24508    * .my-ele ment.ng-hi de-add { . .. }
  24509    * .my-ele ment.ng-hi de-add.ng- hide-add-a ctive { .. . }
  24510    * .my-ele ment.ng-hi de-remove  { ... }
  24511    * .my-ele ment.ng-hi de-remove. ng-hide-re move-activ e { ... }
  24512    * ```
  24513    *
  24514    * Keep in  mind that , as of An gularJS ve rsion 1.3. 0-beta.11,  there is  no need to  change th e display
  24515    * propert y to block  during an imation st ates--ngAn imate will  handle th e style to ggling aut omatically  for you.
  24516    *
  24517    * @animat ions
  24518    * addClas s: `.ng-hi de` - happ ens after  the `ngSho w` express ion evalua tes to a t ruthy valu e and the  just befor e contents  are set t o visible
  24519    * removeC lass: `.ng -hide` - h appens aft er the `ng Show` expr ession eva luates to  a non trut hy value a nd just be fore the c ontents ar e set to h idden
  24520    *
  24521    * @elemen t ANY
  24522    * @param  {expressio n} ngShow  If the {@l ink guide/ expression  expressio n} is trut hy
  24523    *     the n the elem ent is sho wn or hidd en respect ively.
  24524    *
  24525    * @exampl e
  24526     <example  module="n gAnimate"  deps="angu lar-animat e.js" anim ations="tr ue">
  24527       <file  name="inde x.html">
  24528         Clic k me: <inp ut type="c heckbox" n g-model="c hecked"><b r/>
  24529         <div >
  24530           Sh ow:
  24531           <d iv class=" check-elem ent animat e-show" ng -show="che cked">
  24532              <span clas s="glyphic on glyphic on-thumbs- up"></span > I show u p when you r checkbox  is checke d.
  24533           </ div>
  24534         </di v>
  24535         <div >
  24536           Hi de:
  24537           <d iv class=" check-elem ent animat e-show" ng -hide="che cked">
  24538              <span clas s="glyphic on glyphic on-thumbs- down"></sp an> I hide  when your  checkbox  is checked .
  24539           </ div>
  24540         </di v>
  24541       </file >
  24542       <file  name="glyp hicons.css ">
  24543         @imp ort url(.. /../compon ents/boots trap-3.1.1 /css/boots trap.css);
  24544       </file >
  24545       <file  name="anim ations.css ">
  24546         .ani mate-show  {
  24547           li ne-height:  20px;
  24548           op acity: 1;
  24549           pa dding: 10p x;
  24550           bo rder: 1px  solid blac k;
  24551           ba ckground:  white;
  24552         }
  24553  
  24554         .ani mate-show. ng-hide-ad d.ng-hide- add-active ,
  24555         .ani mate-show. ng-hide-re move.ng-hi de-remove- active {
  24556           -w ebkit-tran sition: al l linear 0 .5s;
  24557           tr ansition:  all linear  0.5s;
  24558         }
  24559  
  24560         .ani mate-show. ng-hide {
  24561           li ne-height:  0;
  24562           op acity: 0;
  24563           pa dding: 0 1 0px;
  24564         }
  24565  
  24566         .che ck-element  {
  24567           pa dding: 10p x;
  24568           bo rder: 1px  solid blac k;
  24569           ba ckground:  white;
  24570         }
  24571       </file >
  24572       <file  name="prot ractor.js"  type="pro tractor">
  24573         var  thumbsUp =  element(b y.css('spa n.glyphico n-thumbs-u p'));
  24574         var  thumbsDown  = element (by.css('s pan.glyphi con-thumbs -down'));
  24575  
  24576         it(' should che ck ng-show  / ng-hide ', functio n() {
  24577           ex pect(thumb sUp.isDisp layed()).t oBeFalsy() ;
  24578           ex pect(thumb sDown.isDi splayed()) .toBeTruth y();
  24579  
  24580           el ement(by.m odel('chec ked')).cli ck();
  24581  
  24582           ex pect(thumb sUp.isDisp layed()).t oBeTruthy( );
  24583           ex pect(thumb sDown.isDi splayed()) .toBeFalsy ();
  24584         });
  24585       </file >
  24586     </exampl e>
  24587    */
  24588   var ngShow Directive  = ['$anima te', funct ion($anima te) {
  24589     return {
  24590       restri ct: 'A',
  24591       multiE lement: tr ue,
  24592       link:  function(s cope, elem ent, attr)  {
  24593         scop e.$watch(a ttr.ngShow , function  ngShowWat chAction(v alue) {
  24594           //  we're add ing a temp orary, ani mation-spe cific clas s for ng-h ide since  this way
  24595           //  we can co ntrol when  the eleme nt is actu ally displ ayed on sc reen witho ut having
  24596           //  to have a  global/gr eedy CSS s elector th at breaks  when other  animation s are run.
  24597           //  Read: htt ps://githu b.com/angu lar/angula r.js/issue s/9103#iss uecomment- 58335845
  24598           $a nimate[val ue ? 'remo veClass' :  'addClass '](element , NG_HIDE_ CLASS, {
  24599              tempClasse s: NG_HIDE _IN_PROGRE SS_CLASS
  24600           }) ;
  24601         });
  24602       }
  24603     };
  24604   }];
  24605  
  24606  
  24607   /**
  24608    * @ngdoc  directive
  24609    * @name n gHide
  24610    *
  24611    * @descri ption
  24612    * The `ng Hide` dire ctive show s or hides  the given  HTML elem ent based  on the exp ression
  24613    * provide d to the ` ngHide` at tribute. T he element  is shown  or hidden  by removin g or addin g
  24614    * the `ng -hide` CSS  class ont o the elem ent. The ` .ng-hide`  CSS class  is predefi ned
  24615    * in Angu larJS and  sets the d isplay sty le to none  (using an  !importan t flag).
  24616    * For CSP  mode plea se add `an gular-csp. css` to yo ur html fi le (see {@ link ng.di rective:ng Csp ngCsp} ).
  24617    *
  24618    * ```html
  24619    * <!-- wh en $scope. myValue is  truthy (e lement is  hidden) -- >
  24620    * <div ng -hide="myV alue" clas s="ng-hide "></div>
  24621    *
  24622    * <!-- wh en $scope. myValue is  falsy (el ement is v isible) -- >
  24623    * <div ng -hide="myV alue"></di v>
  24624    * ```
  24625    *
  24626    * When th e `ngHide`  expressio n evaluate s to a tru thy value  then the ` .ng-hide`  CSS class  is added t o the clas s
  24627    * attribu te on the  element ca using it t o become h idden. Whe n falsy, t he `.ng-hi de` CSS cl ass is rem oved
  24628    * from th e element  causing th e element  not to app ear hidden .
  24629    *
  24630    * ## Why  is !import ant used?
  24631    *
  24632    * You may  be wonder ing why !i mportant i s used for  the `.ng- hide` CSS  class. Thi s is becau se the `.n g-hide` se lector
  24633    * can be  easily ove rridden by  heavier s electors.  For exampl e, somethi ng as simp le
  24634    * as chan ging the d isplay sty le on a HT ML list it em would m ake hidden  elements  appear vis ible.
  24635    * This al so becomes  a bigger  issue when  dealing w ith CSS fr ameworks.
  24636    *
  24637    * By usin g !importa nt, the sh ow and hid e behavior  will work  as expect ed despite  any clash  between C SS selecto r
  24638    * specifi city (when  !importan t isn't us ed with an y conflict ing styles ). If a de veloper ch ooses to o verride th e
  24639    * styling  to change  how to hi de an elem ent then i t is just  a matter o f using !i mportant i n their ow n CSS code .
  24640    *
  24641    * ### Ove rriding `. ng-hide`
  24642    *
  24643    * By defa ult, the ` .ng-hide`  class will  style the  element w ith `displ ay: none!i mportant`.  If you wi sh to chan ge
  24644    * the hid e behavior  with ngSh ow/ngHide  then this  can be ach ieved by r estating t he styles  for the `. ng-hide`
  24645    * class i n CSS:
  24646    *
  24647    * ```css
  24648    * .ng-hid e {
  24649    *   /&#42 ; this is  just anoth er form of  hiding an  element & #42;/
  24650    *   displ ay: block! important;
  24651    *   posit ion: absol ute;
  24652    *   top:  -9999px;
  24653    *   left:  -9999px;
  24654    * }
  24655    * ```
  24656    *
  24657    * By defa ult you do n't need t o override  in CSS an ything and  the anima tions will  work arou nd the dis play style .
  24658    *
  24659    * ## A no te about a nimations  with `ngHi de`
  24660    *
  24661    * Animati ons in ngS how/ngHide  work with  the show  and hide e vents that  are trigg ered when  the direct ive expres sion
  24662    * is true  and false . This sys tem works  like the a nimation s ystem pres ent with n gClass, ex cept that  the `.ng-h ide`
  24663    * CSS cla ss is adde d and remo ved for yo u instead  of your ow n CSS clas s.
  24664    *
  24665    * ```css
  24666    * //
  24667    * //a wor king examp le can be  found at t he bottom  of this pa ge
  24668    * //
  24669    * .my-ele ment.ng-hi de-add, .m y-element. ng-hide-re move {
  24670    *   trans ition: 0.5 s linear a ll;
  24671    * }
  24672    *
  24673    * .my-ele ment.ng-hi de-add { . .. }
  24674    * .my-ele ment.ng-hi de-add.ng- hide-add-a ctive { .. . }
  24675    * .my-ele ment.ng-hi de-remove  { ... }
  24676    * .my-ele ment.ng-hi de-remove. ng-hide-re move-activ e { ... }
  24677    * ```
  24678    *
  24679    * Keep in  mind that , as of An gularJS ve rsion 1.3. 0-beta.11,  there is  no need to  change th e display
  24680    * propert y to block  during an imation st ates--ngAn imate will  handle th e style to ggling aut omatically  for you.
  24681    *
  24682    * @animat ions
  24683    * removeC lass: `.ng -hide` - h appens aft er the `ng Hide` expr ession eva luates to  a truthy v alue and j ust before  the conte nts are se t to hidde n
  24684    * addClas s: `.ng-hi de` - happ ens after  the `ngHid e` express ion evalua tes to a n on truthy  value and  just befor e the cont ents are s et to visi ble
  24685    *
  24686    * @elemen t ANY
  24687    * @param  {expressio n} ngHide  If the {@l ink guide/ expression  expressio n} is trut hy then
  24688    *     the  element i s shown or  hidden re spectively .
  24689    *
  24690    * @exampl e
  24691     <example  module="n gAnimate"  deps="angu lar-animat e.js" anim ations="tr ue">
  24692       <file  name="inde x.html">
  24693         Clic k me: <inp ut type="c heckbox" n g-model="c hecked"><b r/>
  24694         <div >
  24695           Sh ow:
  24696           <d iv class=" check-elem ent animat e-hide" ng -show="che cked">
  24697              <span clas s="glyphic on glyphic on-thumbs- up"></span > I show u p when you r checkbox  is checke d.
  24698           </ div>
  24699         </di v>
  24700         <div >
  24701           Hi de:
  24702           <d iv class=" check-elem ent animat e-hide" ng -hide="che cked">
  24703              <span clas s="glyphic on glyphic on-thumbs- down"></sp an> I hide  when your  checkbox  is checked .
  24704           </ div>
  24705         </di v>
  24706       </file >
  24707       <file  name="glyp hicons.css ">
  24708         @imp ort url(.. /../compon ents/boots trap-3.1.1 /css/boots trap.css);
  24709       </file >
  24710       <file  name="anim ations.css ">
  24711         .ani mate-hide  {
  24712           -w ebkit-tran sition: al l linear 0 .5s;
  24713           tr ansition:  all linear  0.5s;
  24714           li ne-height:  20px;
  24715           op acity: 1;
  24716           pa dding: 10p x;
  24717           bo rder: 1px  solid blac k;
  24718           ba ckground:  white;
  24719         }
  24720  
  24721         .ani mate-hide. ng-hide {
  24722           li ne-height:  0;
  24723           op acity: 0;
  24724           pa dding: 0 1 0px;
  24725         }
  24726  
  24727         .che ck-element  {
  24728           pa dding: 10p x;
  24729           bo rder: 1px  solid blac k;
  24730           ba ckground:  white;
  24731         }
  24732       </file >
  24733       <file  name="prot ractor.js"  type="pro tractor">
  24734         var  thumbsUp =  element(b y.css('spa n.glyphico n-thumbs-u p'));
  24735         var  thumbsDown  = element (by.css('s pan.glyphi con-thumbs -down'));
  24736  
  24737         it(' should che ck ng-show  / ng-hide ', functio n() {
  24738           ex pect(thumb sUp.isDisp layed()).t oBeFalsy() ;
  24739           ex pect(thumb sDown.isDi splayed()) .toBeTruth y();
  24740  
  24741           el ement(by.m odel('chec ked')).cli ck();
  24742  
  24743           ex pect(thumb sUp.isDisp layed()).t oBeTruthy( );
  24744           ex pect(thumb sDown.isDi splayed()) .toBeFalsy ();
  24745         });
  24746       </file >
  24747     </exampl e>
  24748    */
  24749   var ngHide Directive  = ['$anima te', funct ion($anima te) {
  24750     return {
  24751       restri ct: 'A',
  24752       multiE lement: tr ue,
  24753       link:  function(s cope, elem ent, attr)  {
  24754         scop e.$watch(a ttr.ngHide , function  ngHideWat chAction(v alue) {
  24755           //  The comme nt inside  of the ngS howDirecti ve explain s why we a dd and
  24756           //  remove a  temporary  class for  the show/h ide animat ion
  24757           $a nimate[val ue ? 'addC lass' : 'r emoveClass '](element ,NG_HIDE_C LASS, {
  24758              tempClasse s: NG_HIDE _IN_PROGRE SS_CLASS
  24759           }) ;
  24760         });
  24761       }
  24762     };
  24763   }];
  24764  
  24765   /**
  24766    * @ngdoc  directive
  24767    * @name n gStyle
  24768    * @restri ct AC
  24769    *
  24770    * @descri ption
  24771    * The `ng Style` dir ective all ows you to  set CSS s tyle on an  HTML elem ent condit ionally.
  24772    *
  24773    * @elemen t ANY
  24774    * @param  {expressio n} ngStyle
  24775    *
  24776    * {@link  guide/expr ession Exp ression} w hich evals  to an
  24777    * object  whose keys  are CSS s tyle names  and value s are corr esponding  values for  those CSS
  24778    * keys.
  24779    *
  24780    * Since s ome CSS st yle names  are not va lid keys f or an obje ct, they m ust be quo ted.
  24781    * See the  'backgrou nd-color'  style in t he example  below.
  24782    *
  24783    * @exampl e
  24784      <exampl e>
  24785        <file  name="ind ex.html">
  24786           <i nput type= "button" v alue="set  color" ng- click="myS tyle={colo r:'red'}">
  24787           <i nput type= "button" v alue="set  background " ng-click ="myStyle= {'backgrou nd-color': 'blue'}">
  24788           <i nput type= "button" v alue="clea r" ng-clic k="myStyle ={}">
  24789           <b r/>
  24790           <s pan ng-sty le="myStyl e">Sample  Text</span >
  24791           <p re>myStyle ={{myStyle }}</pre>
  24792        </fil e>
  24793        <file  name="sty le.css">
  24794          spa n {
  24795            c olor: blac k;
  24796          }
  24797        </fil e>
  24798        <file  name="pro tractor.js " type="pr otractor">
  24799          var  colorSpan  = element (by.css('s pan'));
  24800  
  24801          it( 'should ch eck ng-sty le', funct ion() {
  24802            e xpect(colo rSpan.getC ssValue('c olor')).to Be('rgba(0 , 0, 0, 1) ');
  24803            e lement(by. css('input [value=\'s et color\' ]')).click ();
  24804            e xpect(colo rSpan.getC ssValue('c olor')).to Be('rgba(2 55, 0, 0,  1)');
  24805            e lement(by. css('input [value=cle ar]')).cli ck();
  24806            e xpect(colo rSpan.getC ssValue('c olor')).to Be('rgba(0 , 0, 0, 1) ');
  24807          });
  24808        </fil e>
  24809      </examp le>
  24810    */
  24811   var ngStyl eDirective  = ngDirec tive(funct ion(scope,  element,  attr) {
  24812     scope.$w atch(attr. ngStyle, f unction ng StyleWatch Action(new Styles, ol dStyles) {
  24813       if (ol dStyles &&  (newStyle s !== oldS tyles)) {
  24814         forE ach(oldSty les, funct ion(val, s tyle) { el ement.css( style, '') ;});
  24815       }
  24816       if (ne wStyles) e lement.css (newStyles );
  24817     }, true) ;
  24818   });
  24819  
  24820   /**
  24821    * @ngdoc  directive
  24822    * @name n gSwitch
  24823    * @restri ct EA
  24824    *
  24825    * @descri ption
  24826    * The `ng Switch` di rective is  used to c onditional ly swap DO M structur e on your  template b ased on a  scope expr ession.
  24827    * Element s within ` ngSwitch`  but withou t `ngSwitc hWhen` or  `ngSwitchD efault` di rectives w ill be pre served at  the locati on
  24828    * as spec ified in t he templat e.
  24829    *
  24830    * The dir ective its elf works  similar to  ngInclude , however,  instead o f download ing templa te code (o r loading  it
  24831    * from th e template  cache), ` ngSwitch`  simply cho oses one o f the nest ed element s and make s it visib le based o n which el ement
  24832    * matches  the value  obtained  from the e valuated e xpression.  In other  words, you  define a  container  element
  24833    * (where  you place  the direct ive), plac e an expre ssion on t he **`on=" ..."` attr ibute**
  24834    * (or the  **`ng-swi tch="..."`  attribute **), defin e any inne r elements  inside of  the direc tive and p lace
  24835    * a when  attribute  per elemen t. The whe n attribut e is used  to inform  ngSwitch w hich eleme nt to disp lay when t he on
  24836    * express ion is eva luated. If  a matchin g expressi on is not  found via  a when att ribute the n an eleme nt with th e default
  24837    * attribu te is disp layed.
  24838    *
  24839    * <div cl ass="alert  alert-inf o">
  24840    * Be awar e that the  attribute  values to  match aga inst canno t be expre ssions. Th ey are int erpreted
  24841    * as lite ral string  values to  match aga inst.
  24842    * For exa mple, **`n g-switch-w hen="someV al"`** wil l match ag ainst the  string `"s omeVal"` n ot against  the
  24843    * value o f the expr ession `$s cope.someV al`.
  24844    * </div>
  24845  
  24846    * @animat ions
  24847    * enter -  happens a fter the n gSwitch co ntents cha nge and th e matched  child elem ent is pla ced inside  the conta iner
  24848    * leave -  happens j ust after  the ngSwit ch content s change a nd just be fore the f ormer cont ents are r emoved fro m the DOM
  24849    *
  24850    * @usage
  24851    *
  24852    * ```
  24853    * <ANY ng -switch="e xpression" >
  24854    *   <ANY  ng-switch- when="matc hValue1">. ..</ANY>
  24855    *   <ANY  ng-switch- when="matc hValue2">. ..</ANY>
  24856    *   <ANY  ng-switch- default>.. .</ANY>
  24857    * </ANY>
  24858    * ```
  24859    *
  24860    *
  24861    * @scope
  24862    * @priori ty 1200
  24863    * @param  {*} ngSwit ch|on expr ession to  match agai nst <tt>ng -switch-wh en</tt>.
  24864    * On chil d elements  add:
  24865    *
  24866    * * `ngSw itchWhen`:  the case  statement  to match a gainst. If  match the n this
  24867    *   case  will be di splayed. I f the same  match app ears multi ple times,  all the
  24868    *   eleme nts will b e displaye d.
  24869    * * `ngSw itchDefaul t`: the de fault case  when no o ther case  match. If  there
  24870    *   are m ultiple de fault case s, all of  them will  be display ed when no  other
  24871    *   case  match.
  24872    *
  24873    *
  24874    * @exampl e
  24875     <example  module="s witchExamp le" deps=" angular-an imate.js"  animations ="true">
  24876       <file  name="inde x.html">
  24877         <div  ng-contro ller="Exam pleControl ler">
  24878           <s elect ng-m odel="sele ction" ng- options="i tem for it em in item s">
  24879           </ select>
  24880           <t t>selectio n={{select ion}}</tt>
  24881           <h r/>
  24882           <d iv class=" animate-sw itch-conta iner"
  24883              ng-switch  on="select ion">
  24884                <div cla ss="animat e-switch"  ng-switch- when="sett ings">Sett ings Div</ div>
  24885                <div cla ss="animat e-switch"  ng-switch- when="home ">Home Spa n</div>
  24886                <div cla ss="animat e-switch"  ng-switch- default>de fault</div >
  24887           </ div>
  24888         </di v>
  24889       </file >
  24890       <file  name="scri pt.js">
  24891         angu lar.module ('switchEx ample', [' ngAnimate' ])
  24892           .c ontroller( 'ExampleCo ntroller',  ['$scope' , function ($scope) {
  24893              $scope.ite ms = ['set tings', 'h ome', 'oth er'];
  24894              $scope.sel ection = $ scope.item s[0];
  24895           }] );
  24896       </file >
  24897       <file  name="anim ations.css ">
  24898         .ani mate-switc h-containe r {
  24899           po sition:rel ative;
  24900           ba ckground:w hite;
  24901           bo rder:1px s olid black ;
  24902           he ight:40px;
  24903           ov erflow:hid den;
  24904         }
  24905  
  24906         .ani mate-switc h {
  24907           pa dding:10px ;
  24908         }
  24909  
  24910         .ani mate-switc h.ng-anima te {
  24911           -w ebkit-tran sition:all  cubic-bez ier(0.250,  0.460, 0. 450, 0.940 ) 0.5s;
  24912           tr ansition:a ll cubic-b ezier(0.25 0, 0.460,  0.450, 0.9 40) 0.5s;
  24913  
  24914           po sition:abs olute;
  24915           to p:0;
  24916           le ft:0;
  24917           ri ght:0;
  24918           bo ttom:0;
  24919         }
  24920  
  24921         .ani mate-switc h.ng-leave .ng-leave- active,
  24922         .ani mate-switc h.ng-enter  {
  24923           to p:-50px;
  24924         }
  24925         .ani mate-switc h.ng-leave ,
  24926         .ani mate-switc h.ng-enter .ng-enter- active {
  24927           to p:0;
  24928         }
  24929       </file >
  24930       <file  name="prot ractor.js"  type="pro tractor">
  24931         var  switchElem  = element (by.css('[ ng-switch] '));
  24932         var  select = e lement(by. model('sel ection'));
  24933  
  24934         it(' should sta rt in sett ings', fun ction() {
  24935           ex pect(switc hElem.getT ext()).toM atch(/Sett ings Div/) ;
  24936         });
  24937         it(' should cha nge to hom e', functi on() {
  24938           se lect.all(b y.css('opt ion')).get (1).click( );
  24939           ex pect(switc hElem.getT ext()).toM atch(/Home  Span/);
  24940         });
  24941         it(' should sel ect defaul t', functi on() {
  24942           se lect.all(b y.css('opt ion')).get (2).click( );
  24943           ex pect(switc hElem.getT ext()).toM atch(/defa ult/);
  24944         });
  24945       </file >
  24946     </exampl e>
  24947    */
  24948   var ngSwit chDirectiv e = ['$ani mate', fun ction($ani mate) {
  24949     return {
  24950       restri ct: 'EA',
  24951       requir e: 'ngSwit ch',
  24952  
  24953       // ask s for $sco pe to fool  the BC co ntroller m odule
  24954       contro ller: ['$s cope', fun ction ngSw itchContro ller() {
  24955        this. cases = {} ;
  24956       }],
  24957       link:  function(s cope, elem ent, attr,  ngSwitchC ontroller)  {
  24958         var  watchExpr  = attr.ngS witch || a ttr.on,
  24959              selectedTr anscludes  = [],
  24960              selectedEl ements = [ ],
  24961              previousLe aveAnimati ons = [],
  24962              selectedSc opes = [];
  24963  
  24964         var  spliceFact ory = func tion(array , index) {
  24965              return fun ction() {  array.spli ce(index,  1); };
  24966         };
  24967  
  24968         scop e.$watch(w atchExpr,  function n gSwitchWat chAction(v alue) {
  24969           va r i, ii;
  24970           fo r (i = 0,  ii = previ ousLeaveAn imations.l ength; i <  ii; ++i)  {
  24971              $animate.c ancel(prev iousLeaveA nimations[ i]);
  24972           }
  24973           pr eviousLeav eAnimation s.length =  0;
  24974  
  24975           fo r (i = 0,  ii = selec tedScopes. length; i  < ii; ++i)  {
  24976              var select ed = getBl ockNodes(s electedEle ments[i].c lone);
  24977              selectedSc opes[i].$d estroy();
  24978              var promis e = previo usLeaveAni mations[i]  = $animat e.leave(se lected);
  24979              promise.th en(spliceF actory(pre viousLeave Animations , i));
  24980           }
  24981  
  24982           se lectedElem ents.lengt h = 0;
  24983           se lectedScop es.length  = 0;
  24984  
  24985           if  ((selecte dTransclud es = ngSwi tchControl ler.cases[ '!' + valu e] || ngSw itchContro ller.cases ['?'])) {
  24986              forEach(se lectedTran scludes, f unction(se lectedTran sclude) {
  24987                selected Transclude .transclud e(function (caseEleme nt, select edScope) {
  24988                  select edScopes.p ush(select edScope);
  24989                  var an chor = sel ectedTrans clude.elem ent;
  24990                  caseEl ement[case Element.le ngth++] =  document.c reateComme nt(' end n gSwitchWhe n: ');
  24991                  var bl ock = { cl one: caseE lement };
  24992  
  24993                  select edElements .push(bloc k);
  24994                  $anima te.enter(c aseElement , anchor.p arent(), a nchor);
  24995                });
  24996              });
  24997           }
  24998         });
  24999       }
  25000     };
  25001   }];
  25002  
  25003   var ngSwit chWhenDire ctive = ng Directive( {
  25004     transclu de: 'eleme nt',
  25005     priority : 1200,
  25006     require:  '^ngSwitc h',
  25007     multiEle ment: true ,
  25008     link: fu nction(sco pe, elemen t, attrs,  ctrl, $tra nsclude) {
  25009       ctrl.c ases['!' +  attrs.ngS witchWhen]  = (ctrl.c ases['!' +  attrs.ngS witchWhen]  || []);
  25010       ctrl.c ases['!' +  attrs.ngS witchWhen] .push({ tr ansclude:  $transclud e, element : element  });
  25011     }
  25012   });
  25013  
  25014   var ngSwit chDefaultD irective =  ngDirecti ve({
  25015     transclu de: 'eleme nt',
  25016     priority : 1200,
  25017     require:  '^ngSwitc h',
  25018     multiEle ment: true ,
  25019     link: fu nction(sco pe, elemen t, attr, c trl, $tran sclude) {
  25020       ctrl.c ases['?']  = (ctrl.ca ses['?'] | | []);
  25021       ctrl.c ases['?']. push({ tra nsclude: $ transclude , element:  element } );
  25022      }
  25023   });
  25024  
  25025   /**
  25026    * @ngdoc  directive
  25027    * @name n gTransclud e
  25028    * @restri ct EAC
  25029    *
  25030    * @descri ption
  25031    * Directi ve that ma rks the in sertion po int for th e transclu ded DOM of  the neare st parent  directive  that uses  transclusi on.
  25032    *
  25033    * Any exi sting cont ent of the  element t hat this d irective i s placed o n will be  removed be fore the t ranscluded  content i s inserted .
  25034    *
  25035    * @elemen t ANY
  25036    *
  25037    * @exampl e
  25038      <exampl e module=" transclude Example">
  25039        <file  name="ind ex.html">
  25040          <sc ript>
  25041            a ngular.mod ule('trans cludeExamp le', [])
  25042              .directive ('pane', f unction(){
  25043                 return  {
  25044                   restr ict: 'E',
  25045                   trans clude: tru e,
  25046                   scope : { title: '@' },
  25047                   templ ate: '<div  style="bo rder: 1px  solid blac k;">' +
  25048                                '<d iv style=" background -color: gr ay">{{titl e}}</div>'  +
  25049                                '<n g-transclu de></ng-tr ansclude>'  +
  25050                              '</di v>'
  25051                 };
  25052            } )
  25053            . controller ('ExampleC ontroller' , ['$scope ', functio n($scope)  {
  25054               $scope.ti tle = 'Lor em Ipsum';
  25055               $scope.te xt = 'Nequ e porro qu isquam est  qui dolor em ipsum q uia dolor. ..';
  25056            } ]);
  25057          </s cript>
  25058          <di v ng-contr oller="Exa mpleContro ller">
  25059            < input ng-m odel="titl e"><br>
  25060            < textarea n g-model="t ext"></tex tarea> <br />
  25061            < pane title ="{{title} }">{{text} }</pane>
  25062          </d iv>
  25063        </fil e>
  25064        <file  name="pro tractor.js " type="pr otractor">
  25065           it ('should h ave transc luded', fu nction() {
  25066              var titleE lement = e lement(by. model('tit le'));
  25067              titleEleme nt.clear() ;
  25068              titleEleme nt.sendKey s('TITLE') ;
  25069              var textEl ement = el ement(by.m odel('text '));
  25070              textElemen t.clear();
  25071              textElemen t.sendKeys ('TEXT');
  25072              expect(ele ment(by.bi nding('tit le')).getT ext()).toE qual('TITL E');
  25073              expect(ele ment(by.bi nding('tex t')).getTe xt()).toEq ual('TEXT' );
  25074           }) ;
  25075        </fil e>
  25076      </examp le>
  25077    *
  25078    */
  25079   var ngTran scludeDire ctive = ng Directive( {
  25080     restrict : 'EAC',
  25081     link: fu nction($sc ope, $elem ent, $attr s, control ler, $tran sclude) {
  25082       if (!$ transclude ) {
  25083         thro w minErr(' ngTransclu de')('orph an',
  25084          'Il legal use  of ngTrans clude dire ctive in t he templat e! ' +
  25085          'No  parent di rective th at require s a transc lusion fou nd. ' +
  25086          'El ement: {0} ',
  25087          sta rtingTag($ element));
  25088       }
  25089  
  25090       $trans clude(func tion(clone ) {
  25091         $ele ment.empty ();
  25092         $ele ment.appen d(clone);
  25093       });
  25094     }
  25095   });
  25096  
  25097   /**
  25098    * @ngdoc  directive
  25099    * @name s cript
  25100    * @restri ct E
  25101    *
  25102    * @descri ption
  25103    * Load th e content  of a `<scr ipt>` elem ent into { @link ng.$ templateCa che `$temp lateCache` }, so that  the
  25104    * templat e can be u sed by {@l ink ng.dir ective:ngI nclude `ng Include`},
  25105    * {@link  ngRoute.di rective:ng View `ngVi ew`}, or { @link guid e/directiv e directiv es}. The t ype of the
  25106    * `<scrip t>` elemen t must be  specified  as `text/n g-template `, and a c ache name  for the te mplate mus t be
  25107    * assigne d through  the elemen t's `id`,  which can  then be us ed as a di rective's  `templateU rl`.
  25108    *
  25109    * @param  {string} t ype Must b e set to ` 'text/ng-t emplate'`.
  25110    * @param  {string} i d Cache na me of the  template.
  25111    *
  25112    * @exampl e
  25113     <example >
  25114       <file  name="inde x.html">
  25115         <scr ipt type=" text/ng-te mplate" id ="/tpl.htm l">
  25116           Co ntent of t he templat e.
  25117         </sc ript>
  25118  
  25119         <a n g-click="c urrentTpl= '/tpl.html '" id="tpl -link">Loa d inlined  template</ a>
  25120         <div  id="tpl-c ontent" ng -include s rc="curren tTpl"></di v>
  25121       </file >
  25122       <file  name="prot ractor.js"  type="pro tractor">
  25123         it(' should loa d template  defined i nside scri pt tag', f unction()  {
  25124           el ement(by.c ss('#tpl-l ink')).cli ck();
  25125           ex pect(eleme nt(by.css( '#tpl-cont ent')).get Text()).to Match(/Con tent of th e template /);
  25126         });
  25127       </file >
  25128     </exampl e>
  25129    */
  25130   var script Directive  = ['$templ ateCache',  function( $templateC ache) {
  25131     return {
  25132       restri ct: 'E',
  25133       termin al: true,
  25134       compil e: functio n(element,  attr) {
  25135         if ( attr.type  == 'text/n g-template ') {
  25136           va r template Url = attr .id,
  25137                text = e lement[0]. text;
  25138  
  25139           $t emplateCac he.put(tem plateUrl,  text);
  25140         }
  25141       }
  25142     };
  25143   }];
  25144  
  25145   var ngOpti onsMinErr  = minErr(' ngOptions' );
  25146   /**
  25147    * @ngdoc  directive
  25148    * @name s elect
  25149    * @restri ct E
  25150    *
  25151    * @descri ption
  25152    * HTML `S ELECT` ele ment with  angular da ta-binding .
  25153    *
  25154    * # `ngOp tions`
  25155    *
  25156    * The `ng Options` a ttribute c an be used  to dynami cally gene rate a lis t of `<opt ion>`
  25157    * element s for the  `<select>`  element u sing the a rray or ob ject obtai ned by eva luating th e
  25158    * `ngOpti ons` compr ehension_e xpression.
  25159    *
  25160    * In many  cases, `n gRepeat` c an be used  on `<opti on>` eleme nts instea d of `ngOp tions` to  achieve a
  25161    * similar  result. H owever, th e `ngOptio ns` provid es some be nefits suc h as reduc ing memory  and
  25162    * increas ing speed  by not cre ating a ne w scope fo r each rep eated inst ance, as w ell as pro viding
  25163    * more fl exibility  in how the  `select`' s model is  assigned  via `selec t as`. `ng Options` s hould be
  25164    * used wh en the `se lect` mode l needs to  be bound  to a non-s tring valu e. This is  because a n option
  25165    * element  can only  be bound t o string v alues at p resent.
  25166    *
  25167    * When an  item in t he `<selec t>` menu i s selected , the arra y element  or object  property
  25168    * represe nted by th e selected  option wi ll be boun d to the m odel ident ified by t he `ngMode l`
  25169    * directi ve.
  25170    *
  25171    * Optiona lly, a sin gle hard-c oded `<opt ion>` elem ent, with  the value  set to an  empty stri ng, can
  25172    * be nest ed into th e `<select >` element . This ele ment will  then repre sent the ` null` or " not select ed"
  25173    * option.  See examp le below f or demonst ration.
  25174    *
  25175    * <div cl ass="alert  alert-war ning">
  25176    * **Note: ** `ngMode l` compare s by refer ence, not  value. Thi s is impor tant when  binding to  an
  25177    * array o f objects.  See an ex ample [in  this jsfid dle](http: //jsfiddle .net/qWzTb /).
  25178    * </div>
  25179    *
  25180    * ## `sel ect as`
  25181    *
  25182    * Using ` select as`  will bind  the resul t of the ` select as`  expressio n to the m odel, but
  25183    * the val ue of the  `<select>`  and `<opt ion>` html  elements  will be ei ther the i ndex (for  array data  sources)
  25184    * or prop erty name  (for objec t data sou rces) of t he value w ithin the  collection . If a `tr ack by` ex pression
  25185    * is used , the resu lt of that  expressio n will be  set as the  value of  the `optio n` and `se lect` elem ents.
  25186    *
  25187    * ### `se lect as` w ith `track expr`
  25188    *
  25189    * Using ` select as`  together  with `trac kexpr` is  not recomm ended. Rea soning:
  25190    *
  25191    * - Examp le: &lt;se lect ng-op tions="ite m.subItem  as item.la bel for it em in valu es track b y item.id"  ng-model= "selected" &gt;
  25192    *   value s: [{id: 1 , label: ' aLabel', s ubItem: {n ame: 'aSub Item'}}, { id: 2, lab el: 'bLabe l', subIte m: {name:  'bSubItem' }}],
  25193    *   $scop e.selected  = {name:  'aSubItem' };
  25194    * - track  by is alw ays applie d to `valu e`, with t he purpose  of preser ving the s election,
  25195    *   (to ` item` in t his case)
  25196    * - to ca lculate wh ether an i tem is sel ected we d o the foll owing:
  25197    *   1. ap ply `track  by` to th e values i n the arra y, e.g.
  25198    *      In  the examp le: [1,2]
  25199    *   2. ap ply `track  by` to th e already  selected v alue in `n gModel`:
  25200    *      In  the examp le: this i s not poss ible, as ` track by`  refers to  `item.id`,  but the s elected
  25201    *      va lue from ` ngModel` i s `{name:  aSubItem}` .
  25202    *
  25203    * @param  {string} n gModel Ass ignable an gular expr ession to  data-bind  to.
  25204    * @param  {string=}  name Prope rty name o f the form  under whi ch the con trol is pu blished.
  25205    * @param  {string=}  required T he control  is consid ered valid  only if v alue is en tered.
  25206    * @param  {string=}  ngRequired  Adds `req uired` att ribute and  `required ` validati on constra int to
  25207    *    the  element wh en the ngR equired ex pression e valuates t o true. Us e `ngRequi red` inste ad of
  25208    *    `req uired` whe n you want  to data-b ind to the  `required ` attribut e.
  25209    * @param  {comprehen sion_expre ssion=} ng Options in  one of th e followin g forms:
  25210    *
  25211    *   * for  array dat a sources:
  25212    *     * ` label` **` for`** `va lue` **`in `** `array `
  25213    *     * ` select` ** `as`** `la bel` **`fo r`** `valu e` **`in`* * `array`
  25214    *     * ` label`  ** `group by` ** `group`  **`for`**  `value` * *`in`** `a rray`
  25215    *     * ` select` ** `as`** `la bel` **`gr oup by`**  `group` ** `for`** `v alue` **`i n`** `arra y` **`trac k by`** `t rackexpr`
  25216    *   * for  object da ta sources :
  25217    *     * ` label` **` for (`**`k ey` **`,`* * `value`* *`) in`**  `object`
  25218    *     * ` select` ** `as`** `la bel` **`fo r (`**`key ` **`,`**  `value`**` ) in`** `o bject`
  25219    *     * ` label` **` group by`* * `group`  **`for (`* *`key`**`, `** `value `**`) in`* * `object`
  25220    *     * ` select` ** `as`** `la bel` **`gr oup by`**  `group`
  25221    *          **`for` ` (`**`key`* *`,`** `va lue`**`) i n`** `obje ct`
  25222    *
  25223    * Where:
  25224    *
  25225    *   * `ar ray` / `ob ject`: an  expression  which eva luates to  an array /  object to  iterate o ver.
  25226    *   * `va lue`: loca l variable  which wil l refer to  each item  in the `a rray` or e ach proper ty value
  25227    *      of  `object`  during ite ration.
  25228    *   * `ke y`: local  variable w hich will  refer to a  property  name in `o bject` dur ing iterat ion.
  25229    *   * `la bel`: The  result of  this expre ssion will  be the la bel for `< option>` e lement. Th e
  25230    *     `ex pression`  will most  likely ref er to the  `value` va riable (e. g. `value. propertyNa me`).
  25231    *   * `se lect`: The  result of  this expr ession wil l be bound  to the mo del of the  parent `< select>`
  25232    *      el ement. If  not specif ied, `sele ct` expres sion will  default to  `value`.
  25233    *   * `gr oup`: The  result of  this expre ssion will  be used t o group op tions usin g the `<op tgroup>`
  25234    *      DO M element.
  25235    *   * `tr ackexpr`:  Used when  working wi th an arra y of objec ts. The re sult of th is express ion will b e
  25236    *      us ed to iden tify the o bjects in  the array.  The `trac kexpr` wil l most lik ely refer  to the
  25237    *     `va lue` varia ble (e.g.  `value.pro pertyName` ). With th is the sel ection is  preserved
  25238    *      ev en when th e options  are recrea ted (e.g.  reloaded f rom the se rver).
  25239    *
  25240    * @exampl e
  25241       <examp le module= "selectExa mple">
  25242         <fil e name="in dex.html">
  25243           <s cript>
  25244           an gular.modu le('select Example',  [])
  25245              .controlle r('Example Controller ', ['$scop e', functi on($scope)  {
  25246                $scope.c olors = [
  25247                  {name: 'black', s hade:'dark '},
  25248                  {name: 'white', s hade:'ligh t'},
  25249                  {name: 'red', sha de:'dark'} ,
  25250                  {name: 'blue', sh ade:'dark' },
  25251                  {name: 'yellow',  shade:'lig ht'}
  25252                ];
  25253                $scope.m yColor = $ scope.colo rs[2]; //  red
  25254              }]);
  25255           </ script>
  25256           <d iv ng-cont roller="Ex ampleContr oller">
  25257              <ul>
  25258                <li ng-r epeat="col or in colo rs">
  25259                  Name:  <input ng- model="col or.name">
  25260                  [<a hr ef ng-clic k="colors. splice($in dex, 1)">X </a>]
  25261                </li>
  25262                <li>
  25263                  [<a hr ef ng-clic k="colors. push({})"> add</a>]
  25264                </li>
  25265              </ul>
  25266              <hr/>
  25267              Color (nul l not allo wed):
  25268              <select ng -model="my Color" ng- options="c olor.name  for color  in colors" ></select> <br>
  25269  
  25270              Color (nul l allowed) :
  25271              <span  cla ss="nullab le">
  25272                <select  ng-model=" myColor" n g-options= "color.nam e for colo r in color s">
  25273                  <optio n value="" >-- choose  color --< /option>
  25274                </select >
  25275              </span><br />
  25276  
  25277              Color grou ped by sha de:
  25278              <select ng -model="my Color" ng- options="c olor.name  group by c olor.shade  for color  in colors ">
  25279              </select>< br/>
  25280  
  25281  
  25282              Select <a  href ng-cl ick="myCol or = { nam e:'not in  list', sha de: 'other ' }">bogus </a>.<br>
  25283              <hr/>
  25284              Currently  selected:  {{ {select ed_color:m yColor} }}
  25285              <div style ="border:s olid 1px b lack; heig ht:20px"
  25286                   ng-st yle="{'bac kground-co lor':myCol or.name}">
  25287              </div>
  25288           </ div>
  25289         </fi le>
  25290         <fil e name="pr otractor.j s" type="p rotractor" >
  25291            i t('should  check ng-o ptions', f unction()  {
  25292               expect(el ement(by.b inding('{s elected_co lor:myColo r}')).getT ext()).toM atch('red' );
  25293               element.a ll(by.mode l('myColor ')).first( ).click();
  25294               element.a ll(by.css( 'select[ng -model="my Color"] op tion')).fi rst().clic k();
  25295               expect(el ement(by.b inding('{s elected_co lor:myColo r}')).getT ext()).toM atch('blac k');
  25296               element(b y.css('.nu llable sel ect[ng-mod el="myColo r"]')).cli ck();
  25297               element.a ll(by.css( '.nullable  select[ng -model="my Color"] op tion')).fi rst().clic k();
  25298               expect(el ement(by.b inding('{s elected_co lor:myColo r}')).getT ext()).toM atch('null ');
  25299            } );
  25300         </fi le>
  25301       </exam ple>
  25302    */
  25303  
  25304   var ngOpti onsDirecti ve = value Fn({
  25305     restrict : 'A',
  25306     terminal : true
  25307   });
  25308  
  25309   // jshint  maxlen: fa lse
  25310   var select Directive  = ['$compi le', '$par se', funct ion($compi le,   $par se) {
  25311                              //000 0111111111 1000000000 0022222222 2200000000 0000000000 0003333333 3330000000 0000000444 4444444444 4400000000 0555555555 5555550000 0006666666 6666666600 0000000000 0007777777 7770000000 0000000000 0088888888 88
  25312     var NG_O PTIONS_REG EXP = /^\s *([\s\S]+? )(?:\s+as\ s+([\s\S]+ ?))?(?:\s+ group\s+by \s+([\s\S] +?))?\s+fo r\s+(?:([\ $\w][\$\w] *)|(?:\(\s *([\$\w][\ $\w]*)\s*, \s*([\$\w] [\$\w]*)\s *\)))\s+in \s+([\s\S] +?)(?:\s+t rack\s+by\ s+([\s\S]+ ?))?$/,
  25313         null ModelCtrl  = {$setVie wValue: no op};
  25314   // jshint  maxlen: 10 0
  25315  
  25316     return {
  25317       restri ct: 'E',
  25318       requir e: ['selec t', '?ngMo del'],
  25319       contro ller: ['$e lement', ' $scope', ' $attrs', f unction($e lement, $s cope, $att rs) {
  25320         var  self = thi s,
  25321              optionsMap  = {},
  25322              ngModelCtr l = nullMo delCtrl,
  25323              nullOption ,
  25324              unknownOpt ion;
  25325  
  25326  
  25327         self .databound  = $attrs. ngModel;
  25328  
  25329  
  25330         self .init = fu nction(ngM odelCtrl_,  nullOptio n_, unknow nOption_)  {
  25331           ng ModelCtrl  = ngModelC trl_;
  25332           nu llOption =  nullOptio n_;
  25333           un knownOptio n = unknow nOption_;
  25334         };
  25335  
  25336  
  25337         self .addOption  = functio n(value, e lement) {
  25338           as sertNotHas OwnPropert y(value, ' "option va lue"');
  25339           op tionsMap[v alue] = tr ue;
  25340  
  25341           if  (ngModelC trl.$viewV alue == va lue) {
  25342              $element.v al(value);
  25343              if (unknow nOption.pa rent()) un knownOptio n.remove() ;
  25344           }
  25345           //  Workaroun d for http s://code.g oogle.com/ p/chromium /issues/de tail?id=38 1459
  25346           //  Adding an  <option s elected="s elected">  element to  a <select  required= "required" > should
  25347           //  automatic ally selec t the new  element
  25348           if  (element  && element [0].hasAtt ribute('se lected'))  {
  25349              element[0] .selected  = true;
  25350           }
  25351         };
  25352  
  25353  
  25354         self .removeOpt ion = func tion(value ) {
  25355           if  (this.has Option(val ue)) {
  25356              delete opt ionsMap[va lue];
  25357              if (ngMode lCtrl.$vie wValue ===  value) {
  25358                this.ren derUnknown Option(val ue);
  25359              }
  25360           }
  25361         };
  25362  
  25363  
  25364         self .renderUnk nownOption  = functio n(val) {
  25365           va r unknownV al = '? '  + hashKey( val) + ' ? ';
  25366           un knownOptio n.val(unkn ownVal);
  25367           $e lement.pre pend(unkno wnOption);
  25368           $e lement.val (unknownVa l);
  25369           un knownOptio n.prop('se lected', t rue); // n eeded for  IE
  25370         };
  25371  
  25372  
  25373         self .hasOption  = functio n(value) {
  25374           re turn optio nsMap.hasO wnProperty (value);
  25375         };
  25376  
  25377         $sco pe.$on('$d estroy', f unction()  {
  25378           //  disable u nknown opt ion so tha t we don't  do work w hen the wh ole select  is being  destroyed
  25379           se lf.renderU nknownOpti on = noop;
  25380         });
  25381       }],
  25382  
  25383       link:  function(s cope, elem ent, attr,  ctrls) {
  25384         // i f ngModel  is not def ined, we d on't need  to do anyt hing
  25385         if ( !ctrls[1])  return;
  25386  
  25387         var  selectCtrl  = ctrls[0 ],
  25388              ngModelCtr l = ctrls[ 1],
  25389              multiple =  attr.mult iple,
  25390              optionsExp  = attr.ng Options,
  25391              nullOption  = false,  // if fals e, user wi ll not be  able to se lect it (u sed by ngO ptions)
  25392              emptyOptio n,
  25393              renderSche duled = fa lse,
  25394              // we can' t just jqL ite('<opti on>') sinc e jqLite i s not smar t enough
  25395              // to crea te it in < select> an d IE barfs  otherwise .
  25396              optionTemp late = jqL ite(docume nt.createE lement('op tion')),
  25397              optGroupTe mplate =jq Lite(docum ent.create Element('o ptgroup')) ,
  25398              unknownOpt ion = opti onTemplate .clone();
  25399  
  25400         // f ind "null"  option
  25401         for  (var i = 0 , children  = element .children( ), ii = ch ildren.len gth; i < i i; i++) {
  25402           if  (children [i].value  === '') {
  25403              emptyOptio n = nullOp tion = chi ldren.eq(i );
  25404              break;
  25405           }
  25406         }
  25407  
  25408         sele ctCtrl.ini t(ngModelC trl, nullO ption, unk nownOption );
  25409  
  25410         // r equired va lidator
  25411         if ( multiple)  {
  25412           ng ModelCtrl. $isEmpty =  function( value) {
  25413              return !va lue || val ue.length  === 0;
  25414           };
  25415         }
  25416  
  25417         if ( optionsExp ) setupAsO ptions(sco pe, elemen t, ngModel Ctrl);
  25418         else  if (multi ple) setup AsMultiple (scope, el ement, ngM odelCtrl);
  25419         else  setupAsSi ngle(scope , element,  ngModelCt rl, select Ctrl);
  25420  
  25421  
  25422         //// ////////// ////////// ////
  25423  
  25424  
  25425  
  25426         func tion setup AsSingle(s cope, sele ctElement,  ngModelCt rl, select Ctrl) {
  25427           ng ModelCtrl. $render =  function()  {
  25428              var viewVa lue = ngMo delCtrl.$v iewValue;
  25429  
  25430              if (select Ctrl.hasOp tion(viewV alue)) {
  25431                if (unkn ownOption. parent())  unknownOpt ion.remove ();
  25432                selectEl ement.val( viewValue) ;
  25433                if (view Value ===  '') emptyO ption.prop ('selected ', true);  // to make  IE9 happy
  25434              } else {
  25435                if (isUn defined(vi ewValue) & & emptyOpt ion) {
  25436                  select Element.va l('');
  25437                } else {
  25438                  select Ctrl.rende rUnknownOp tion(viewV alue);
  25439                }
  25440              }
  25441           };
  25442  
  25443           se lectElemen t.on('chan ge', funct ion() {
  25444              scope.$app ly(functio n() {
  25445                if (unkn ownOption. parent())  unknownOpt ion.remove ();
  25446                ngModelC trl.$setVi ewValue(se lectElemen t.val());
  25447              });
  25448           }) ;
  25449         }
  25450  
  25451         func tion setup AsMultiple (scope, se lectElemen t, ctrl) {
  25452           va r lastView ;
  25453           ct rl.$render  = functio n() {
  25454              var items  = new Hash Map(ctrl.$ viewValue) ;
  25455              forEach(se lectElemen t.find('op tion'), fu nction(opt ion) {
  25456                option.s elected =  isDefined( items.get( option.val ue));
  25457              });
  25458           };
  25459  
  25460           //  we have t o do it on  each watc h since ng Model watc hes refere nce, but
  25461           //  we need t o work of  an array,  so we need  to see if  anything  was insert ed/removed
  25462           sc ope.$watch (function  selectMult ipleWatch( ) {
  25463              if (!equal s(lastView , ctrl.$vi ewValue))  {
  25464                lastView  = shallow Copy(ctrl. $viewValue );
  25465                ctrl.$re nder();
  25466              }
  25467           }) ;
  25468  
  25469           se lectElemen t.on('chan ge', funct ion() {
  25470              scope.$app ly(functio n() {
  25471                var arra y = [];
  25472                forEach( selectElem ent.find(' option'),  function(o ption) {
  25473                  if (op tion.selec ted) {
  25474                    arra y.push(opt ion.value) ;
  25475                  }
  25476                });
  25477                ctrl.$se tViewValue (array);
  25478              });
  25479           }) ;
  25480         }
  25481  
  25482         func tion setup AsOptions( scope, sel ectElement , ctrl) {
  25483           va r match;
  25484  
  25485           if  (!(match  = optionsE xp.match(N G_OPTIONS_ REGEXP)))  {
  25486              throw ngOp tionsMinEr r('iexp',
  25487                "Expecte d expressi on in form  of " +
  25488                "'_selec t_ (as _la bel_)? for  (_key_,)? _value_ in  _collecti on_'" +
  25489                " but go t '{0}'. E lement: {1 }",
  25490                optionsE xp, starti ngTag(sele ctElement) );
  25491           }
  25492  
  25493           va r displayF n = $parse (match[2]  || match[1 ]),
  25494                valueNam e = match[ 4] || matc h[6],
  25495                selectAs  = / as /. test(match [0]) && ma tch[1],
  25496                selectAs Fn = selec tAs ? $par se(selectA s) : null,
  25497                keyName  = match[5] ,
  25498                groupByF n = $parse (match[3]  || ''),
  25499                valueFn  = $parse(m atch[2] ?  match[1] :  valueName ),
  25500                valuesFn  = $parse( match[7]),
  25501                track =  match[8],
  25502                trackFn  = track ?  $parse(mat ch[8]) : n ull,
  25503                trackKey sCache = { },
  25504                // This  is an arra y of array  of existi ng option  groups in  DOM.
  25505                // We tr y to reuse  these if  possible
  25506                // - opt ionGroupsC ache[0] is  the optio ns with no  option gr oup
  25507                // - opt ionGroupsC ache[?][0]  is the pa rent: eith er the SEL ECT or OPT GROUP elem ent
  25508                optionGr oupsCache  = [[{eleme nt: select Element, l abel:''}]] ,
  25509                //re-usa ble object  to repres ent option 's locals
  25510                locals =  {};
  25511  
  25512           if  (nullOpti on) {
  25513              // compile  the eleme nt since t here might  be bindin gs in it
  25514              $compile(n ullOption) (scope);
  25515  
  25516              // remove  the class,  which is  added auto matically  because we  recompile  the eleme nt and it
  25517              // becomes  the compi lation roo t
  25518              nullOption .removeCla ss('ng-sco pe');
  25519  
  25520              // we need  to remove  it before  calling s electEleme nt.empty()  because o therwise I E will
  25521              // remove  the label  from the e lement. wt f?
  25522              nullOption .remove();
  25523           }
  25524  
  25525           //  clear con tents, we' ll add wha t's needed  based on  the model
  25526           se lectElemen t.empty();
  25527  
  25528           se lectElemen t.on('chan ge', selec tionChange d);
  25529  
  25530           ct rl.$render  = render;
  25531  
  25532           sc ope.$watch Collection (valuesFn,  scheduleR endering);
  25533           sc ope.$watch Collection (getLabels , schedule Rendering) ;
  25534  
  25535           if  (multiple ) {
  25536              scope.$wat chCollecti on(functio n() { retu rn ctrl.$m odelValue;  }, schedu leRenderin g);
  25537           }
  25538  
  25539           //  --------- ---------- ---------- ---------- ---------- ---------- ------- //
  25540  
  25541           fu nction cal lExpressio n(exprFn,  key, value ) {
  25542              locals[val ueName] =  value;
  25543              if (keyNam e) locals[ keyName] =  key;
  25544              return exp rFn(scope,  locals);
  25545           }
  25546  
  25547           fu nction sel ectionChan ged() {
  25548              scope.$app ly(functio n() {
  25549                var coll ection = v aluesFn(sc ope) || [] ;
  25550                var view Value;
  25551                if (mult iple) {
  25552                  viewVa lue = [];
  25553                  forEac h(selectEl ement.val( ), functio n(selected Key) {
  25554                      se lectedKey  = trackFn  ? trackKey sCache[sel ectedKey]  : selected Key;
  25555                    view Value.push (getViewVa lue(select edKey, col lection[se lectedKey] ));
  25556                  });
  25557                } else {
  25558                  var se lectedKey  = trackFn  ? trackKey sCache[sel ectElement .val()] :  selectElem ent.val();
  25559                  viewVa lue = getV iewValue(s electedKey , collecti on[selecte dKey]);
  25560                }
  25561                ctrl.$se tViewValue (viewValue );
  25562                render() ;
  25563              });
  25564           }
  25565  
  25566           fu nction get ViewValue( key, value ) {
  25567              if (key == = '?') {
  25568                return u ndefined;
  25569              } else if  (key === ' ') {
  25570                return n ull;
  25571              } else {
  25572                var view ValueFn =  selectAsFn  ? selectA sFn : valu eFn;
  25573                return c allExpress ion(viewVa lueFn, key , value);
  25574              }
  25575           }
  25576  
  25577           fu nction get Labels() {
  25578              var values  = valuesF n(scope);
  25579              var toDisp lay;
  25580              if (values  && isArra y(values))  {
  25581                toDispla y = new Ar ray(values .length);
  25582                for (var  i = 0, ii  = values. length; i  < ii; i++)  {
  25583                  toDisp lay[i] = c allExpress ion(displa yFn, i, va lues[i]);
  25584                }
  25585                return t oDisplay;
  25586              } else if  (values) {
  25587                // TODO:  Add a tes t for this  case
  25588                toDispla y = {};
  25589                for (var  prop in v alues) {
  25590                  if (va lues.hasOw nProperty( prop)) {
  25591                    toDi splay[prop ] = callEx pression(d isplayFn,  prop, valu es[prop]);
  25592                  }
  25593                }
  25594              }
  25595              return toD isplay;
  25596           }
  25597  
  25598           fu nction cre ateIsSelec tedFn(view Value) {
  25599              var select edSet;
  25600              if (multip le) {
  25601                if (trac kFn && isA rray(viewV alue)) {
  25602  
  25603                  select edSet = ne w HashMap( []);
  25604                  for (v ar trackIn dex = 0; t rackIndex  < viewValu e.length;  trackIndex ++) {
  25605                    // t racking by  key
  25606                    sele ctedSet.pu t(callExpr ession(tra ckFn, null , viewValu e[trackInd ex]), true );
  25607                  }
  25608                } else {
  25609                  select edSet = ne w HashMap( viewValue) ;
  25610                }
  25611              } else if  (trackFn)  {
  25612                viewValu e = callEx pression(t rackFn, nu ll, viewVa lue);
  25613              }
  25614  
  25615              return fun ction isSe lected(key , value) {
  25616                var comp areValueFn ;
  25617                if (trac kFn) {
  25618                  compar eValueFn =  trackFn;
  25619                } else i f (selectA sFn) {
  25620                  compar eValueFn =  selectAsF n;
  25621                } else {
  25622                  compar eValueFn =  valueFn;
  25623                }
  25624  
  25625                if (mult iple) {
  25626                  return  isDefined (selectedS et.remove( callExpres sion(compa reValueFn,  key, valu e)));
  25627                } else {
  25628                  return  viewValue  === callE xpression( compareVal ueFn, key,  value);
  25629                }
  25630              };
  25631           }
  25632  
  25633           fu nction sch eduleRende ring() {
  25634              if (!rende rScheduled ) {
  25635                scope.$$ postDigest (render);
  25636                renderSc heduled =  true;
  25637              }
  25638           }
  25639  
  25640           /* *
  25641            *  A new lab elMap is c reated wit h each ren der.
  25642            *  This func tion is ca lled for e ach existi ng option  with added =false,
  25643            *  and each  new option  with adde d=true.
  25644            *  - Labels  that are p assed to t his method  twice,
  25645            *  (once wit h added=tr ue and onc e with add ed=false)  will end u p with a v alue of 0,  and
  25646            *  will caus e no chang e to happe n to the c orrespondi ng option.
  25647            *  - Labels  that are p assed to t his method  only once  with adde d=false wi ll end up  with a
  25648            *  value of  -1 and wil l eventual ly be pass ed to sele ctCtrl.rem oveOption( )
  25649            *  - Labels  that are p assed to t his method  only once  with adde d=true wil l end up w ith a
  25650            *  value of  1 and will  eventuall y be passe d to selec tCtrl.addO ption()
  25651           */
  25652           fu nction upd ateLabelMa p(labelMap , label, a dded) {
  25653              labelMap[l abel] = la belMap[lab el] || 0;
  25654              labelMap[l abel] += ( added ? 1  : -1);
  25655           }
  25656  
  25657           fu nction ren der() {
  25658              renderSche duled = fa lse;
  25659  
  25660              // Tempora ry locatio n for the  option gro ups before  we render  them
  25661              var option Groups = { '':[]},
  25662                  option GroupNames  = [''],
  25663                  option GroupName,
  25664                  option Group,
  25665                  option ,
  25666                  existi ngParent,  existingOp tions, exi stingOptio n,
  25667                  viewVa lue = ctrl .$viewValu e,
  25668                  values  = valuesF n(scope) | | [],
  25669                  keys =  keyName ?  sortedKey s(values)  : values,
  25670                  key,
  25671                  value,
  25672                  groupL ength, len gth,
  25673                  groupI ndex, inde x,
  25674                  labelM ap = {},
  25675                  select ed,
  25676                  isSele cted = cre ateIsSelec tedFn(view Value),
  25677                  anySel ected = fa lse,
  25678                  lastEl ement,
  25679                  elemen t,
  25680                  label,
  25681                  option Id;
  25682  
  25683              trackKeysC ache = {};
  25684  
  25685              // We now  build up t he list of  options w e need (we  merge lat er)
  25686              for (index  = 0; leng th = keys. length, in dex < leng th; index+ +) {
  25687                key = in dex;
  25688                if (keyN ame) {
  25689                  key =  keys[index ];
  25690                  if (ke y.charAt(0 ) === '$')  continue;
  25691                }
  25692                value =  values[key ];
  25693  
  25694                optionGr oupName =  callExpres sion(group ByFn, key,  value) ||  '';
  25695                if (!(op tionGroup  = optionGr oups[optio nGroupName ])) {
  25696                  option Group = op tionGroups [optionGro upName] =  [];
  25697                  option GroupNames .push(opti onGroupNam e);
  25698                }
  25699  
  25700                selected  = isSelec ted(key, v alue);
  25701                anySelec ted = anyS elected ||  selected;
  25702  
  25703                label =  callExpres sion(displ ayFn, key,  value); / / what wil l be seen  by the use r
  25704  
  25705                // doing  displayFn (scope, lo cals) || ' ' overwrit es zero va lues
  25706                label =  isDefined( label) ? l abel : '';
  25707                optionId  = trackFn  ? trackFn (scope, lo cals) : (k eyName ? k eys[index]  : index);
  25708                if (trac kFn) {
  25709                  trackK eysCache[o ptionId] =  key;
  25710                }
  25711  
  25712                optionGr oup.push({
  25713                  // eit her the in dex into a rray or ke y from obj ect
  25714                  id: op tionId,
  25715                  label:  label,
  25716                  select ed: select ed                     // determ ine if we  should be  selected
  25717                });
  25718              }
  25719              if (!multi ple) {
  25720                if (null Option ||  viewValue  === null)  {
  25721                  // ins ert null o ption if w e have a p laceholder , or the m odel is nu ll
  25722                  option Groups[''] .unshift({ id:'', lab el:'', sel ected:!any Selected}) ;
  25723                } else i f (!anySel ected) {
  25724                  // opt ion could  not be fou nd, we hav e to inser t the unde fined item
  25725                  option Groups[''] .unshift({ id:'?', la bel:'', se lected:tru e});
  25726                }
  25727              }
  25728  
  25729              // Now we  need to up date the l ist of DOM  nodes to  match the  optionGrou ps we comp uted above
  25730              for (group Index = 0,  groupLeng th = optio nGroupName s.length;
  25731                   group Index < gr oupLength;
  25732                   group Index++) {
  25733                // curre nt option  group name  or '' if  no group
  25734                optionGr oupName =  optionGrou pNames[gro upIndex];
  25735  
  25736                // list  of options  for that  group. (fi rst item h as the par ent)
  25737                optionGr oup = opti onGroups[o ptionGroup Name];
  25738  
  25739                if (opti onGroupsCa che.length  <= groupI ndex) {
  25740                  // we  need to gr ow the opt ionGroups
  25741                  existi ngParent =  {
  25742                    elem ent: optGr oupTemplat e.clone(). attr('labe l', option GroupName) ,
  25743                    labe l: optionG roup.label
  25744                  };
  25745                  existi ngOptions  = [existin gParent];
  25746                  option GroupsCach e.push(exi stingOptio ns);
  25747                  select Element.ap pend(exist ingParent. element);
  25748                } else {
  25749                  existi ngOptions  = optionGr oupsCache[ groupIndex ];
  25750                  existi ngParent =  existingO ptions[0];   // eithe r SELECT ( no group)  or OPTGROU P element
  25751  
  25752                  // upd ate the OP TGROUP lab el if not  the same.
  25753                  if (ex istingPare nt.label ! = optionGr oupName) {
  25754                    exis tingParent .element.a ttr('label ', existin gParent.la bel = opti onGroupNam e);
  25755                  }
  25756                }
  25757  
  25758                lastElem ent = null ;  // star t at the b eginning
  25759                for (ind ex = 0, le ngth = opt ionGroup.l ength; ind ex < lengt h; index++ ) {
  25760                  option  = optionG roup[index ];
  25761                  if ((e xistingOpt ion = exis tingOption s[index +  1])) {
  25762                    // r euse eleme nts
  25763                    last Element =  existingOp tion.eleme nt;
  25764                    if ( existingOp tion.label  !== optio n.label) {
  25765                      up dateLabelM ap(labelMa p, existin gOption.la bel, false );
  25766                      up dateLabelM ap(labelMa p, option. label, tru e);
  25767                      la stElement. text(exist ingOption. label = op tion.label );
  25768                      la stElement. prop('labe l', existi ngOption.l abel);
  25769                    }
  25770                    if ( existingOp tion.id != = option.i d) {
  25771                      la stElement. val(existi ngOption.i d = option .id);
  25772                    }
  25773                    // l astElement .prop('sel ected') pr ovided by  jQuery has  side-effe cts
  25774                    if ( lastElemen t[0].selec ted !== op tion.selec ted) {
  25775                      la stElement. prop('sele cted', (ex istingOpti on.selecte d = option .selected) );
  25776                      if  (msie) {
  25777                         // See #76 92
  25778                         // The sel ected item  wouldn't  visually u pdate on I E without  this.
  25779                         // Tested  on Win7: I E9, IE10 a nd IE11. F uture IEs  should be  tested as  well
  25780                         lastElemen t.prop('se lected', e xistingOpt ion.select ed);
  25781                      }
  25782                    }
  25783                  } else  {
  25784                    // g row elemen ts
  25785  
  25786                    // i f it's a n ull option
  25787                    if ( option.id  === '' &&  nullOption ) {
  25788                      //  put back  the pre-co mpiled ele ment
  25789                      el ement = nu llOption;
  25790                    } el se {
  25791                      //  jQuery(v1 .4.2) Bug:  We should  be able t o chain th e method c alls, but
  25792                      //  in this v ersion of  jQuery on  some brows er the .te xt() retur ns a strin g
  25793                      //  rather th en the ele ment.
  25794                      (e lement = o ptionTempl ate.clone( ))
  25795                           .val(opt ion.id)
  25796                           .prop('s elected',  option.sel ected)
  25797                           .attr('s elected',  option.sel ected)
  25798                           .prop('l abel', opt ion.label)
  25799                           .text(op tion.label );
  25800                    }
  25801  
  25802                    exis tingOption s.push(exi stingOptio n = {
  25803                         element: e lement,
  25804                         label: opt ion.label,
  25805                         id: option .id,
  25806                         selected:  option.sel ected
  25807                    });
  25808                    upda teLabelMap (labelMap,  option.la bel, true) ;
  25809                    if ( lastElemen t) {
  25810                      la stElement. after(elem ent);
  25811                    } el se {
  25812                      ex istingPare nt.element .append(el ement);
  25813                    }
  25814                    last Element =  element;
  25815                  }
  25816                }
  25817                // remov e any exce ssive OPTI ONs in a g roup
  25818                index++;  // increm ent since  the existi ngOptions[ 0] is pare nt element  not OPTIO N
  25819                while (e xistingOpt ions.lengt h > index)  {
  25820                  option  = existin gOptions.p op();
  25821                  update LabelMap(l abelMap, o ption.labe l, false);
  25822                  option .element.r emove();
  25823                }
  25824              }
  25825              // remove  any excess ive OPTGRO UPs from s elect
  25826              while (opt ionGroupsC ache.lengt h > groupI ndex) {
  25827                // remov e all the  labels in  the option  group
  25828                optionGr oup = opti onGroupsCa che.pop();
  25829                for (ind ex = 1; in dex < opti onGroup.le ngth; ++in dex) {
  25830                  update LabelMap(l abelMap, o ptionGroup [index].la bel, false );
  25831                }
  25832                optionGr oup[0].ele ment.remov e();
  25833              }
  25834              forEach(la belMap, fu nction(cou nt, label)  {
  25835                if (coun t > 0) {
  25836                  select Ctrl.addOp tion(label );
  25837                } else i f (count <  0) {
  25838                  select Ctrl.remov eOption(la bel);
  25839                }
  25840              });
  25841           }
  25842         }
  25843       }
  25844     };
  25845   }];
  25846  
  25847   var option Directive  = ['$inter polate', f unction($i nterpolate ) {
  25848     var null SelectCtrl  = {
  25849       addOpt ion: noop,
  25850       remove Option: no op
  25851     };
  25852  
  25853     return {
  25854       restri ct: 'E',
  25855       priori ty: 100,
  25856       compil e: functio n(element,  attr) {
  25857         if ( isUndefine d(attr.val ue)) {
  25858           va r interpol ateFn = $i nterpolate (element.t ext(), tru e);
  25859           if  (!interpo lateFn) {
  25860              attr.$set( 'value', e lement.tex t());
  25861           }
  25862         }
  25863  
  25864         retu rn functio n(scope, e lement, at tr) {
  25865           va r selectCt rlName = ' $selectCon troller',
  25866                parent =  element.p arent(),
  25867                selectCt rl = paren t.data(sel ectCtrlNam e) ||
  25868                  parent .parent(). data(selec tCtrlName) ; // in ca se we are  in optgrou p
  25869  
  25870           if  (!selectC trl || !se lectCtrl.d atabound)  {
  25871              selectCtrl  = nullSel ectCtrl;
  25872           }
  25873  
  25874           if  (interpol ateFn) {
  25875              scope.$wat ch(interpo lateFn, fu nction int erpolateWa tchAction( newVal, ol dVal) {
  25876                attr.$se t('value',  newVal);
  25877                if (oldV al !== new Val) {
  25878                  select Ctrl.remov eOption(ol dVal);
  25879                }
  25880                selectCt rl.addOpti on(newVal,  element);
  25881              });
  25882           }  else {
  25883              selectCtrl .addOption (attr.valu e, element );
  25884           }
  25885  
  25886           el ement.on(' $destroy',  function( ) {
  25887              selectCtrl .removeOpt ion(attr.v alue);
  25888           }) ;
  25889         };
  25890       }
  25891     };
  25892   }];
  25893  
  25894   var styleD irective =  valueFn({
  25895     restrict : 'E',
  25896     terminal : false
  25897   });
  25898  
  25899     if (wind ow.angular .bootstrap ) {
  25900       //Angu larJS is a lready loa ded, so we  can retur n here...
  25901       consol e.log('WAR NING: Trie d to load  angular mo re than on ce.');
  25902       return ;
  25903     }
  25904  
  25905     //try to  bind to j query now  so that on e can writ e jqLite(d ocument).r eady()
  25906     //but we  will rebi nd on boot strap agai n.
  25907     bindJQue ry();
  25908  
  25909     publishE xternalAPI (angular);
  25910  
  25911     jqLite(d ocument).r eady(funct ion() {
  25912       angula rInit(docu ment, boot strap);
  25913     });
  25914  
  25915   })(window,  document) ;
  25916  
  25917   !window.an gular.$$cs p() && win dow.angula r.element( document). find('head ').prepend ('<style t ype="text/ css">@char set "UTF-8 ";[ng\\:cl oak],[ng-c loak],[dat a-ng-cloak ],[x-ng-cl oak],.ng-c loak,.x-ng -cloak,.ng -hide:not( .ng-hide-a nimate){di splay:none  !importan t;}ng\\:fo rm{display :block;}</ style>');