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.
| # | 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 |
| Description | Between Files 1 and 2 |
|
|---|---|---|
| Text Blocks | Lines | |
| Unchanged | 50 | 51730 |
| Changed | 49 | 104 |
| Inserted | 0 | 0 |
| Removed | 0 | 0 |
| 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 |
No regular expressions were active.
| 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(/</,'< ;').replac e(/>/,'> ;')); | |
| 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
|
|
| 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)) | |
| 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
|
|
| 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
|
|
| 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 (<, & gt;) with &lt; a nd &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="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= "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= " " 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; &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 | * /* ; 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 | * /* ; this is required a s of 1.3x to properl y | |
| 24498 | * ap ply all st yling in a show/hide animation */ | |
| 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 | * /* ; 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 | * /* ; 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: <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" > | |
| 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>'); |
Araxis Merge (but not the data content of this report) is Copyright © 1993-2016 Araxis Ltd (www.araxis.com). All rights reserved.