Compare commits
736 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f031127160 | |||
| 00b44d8e12 | |||
| ca865d29a3 | |||
| 3ccec13aa7 | |||
| 43d49013d1 | |||
| 116fac0562 | |||
| c3024254b6 | |||
| 770353df19 | |||
| 85b7d24357 | |||
| 8469779a8e | |||
| 3374e35953 | |||
| 90ff8a98d8 | |||
| a4dc21ebf5 | |||
| ec93f94cc9 | |||
| 7665497a53 | |||
| 2acadc4216 | |||
| c7658d9457 | |||
| b92c650e05 | |||
| f7a0f9d841 | |||
| b17d40b4a5 | |||
| d745df7e5f | |||
| 53b444419c | |||
| 9a21050b43 | |||
| 8473b9d558 | |||
| 679d418a50 | |||
| 16d247b386 | |||
| 4767d34ae8 | |||
| 5efc2ed5ac | |||
| f9bf194439 | |||
| 3c4460b513 | |||
| a98931de0e | |||
| 7e5154e755 | |||
| ec6b1cfaba | |||
| 8d8801f1ae | |||
| 301647bf1b | |||
| 1c03a1b9c0 | |||
| fd797cdb7e | |||
| ed1dbf2554 | |||
| 022cb3dc4e | |||
| 4f107acfcf | |||
| f363bcb437 | |||
| 7b2259f32c | |||
| 9e88fa18b9 | |||
| 094580c3da | |||
| cc4d08c5f0 | |||
| d0ae241afd | |||
| e1f103a8e4 | |||
| d17aa84be1 | |||
| e87c88914f | |||
| b5d48ee1f0 | |||
| 1c010b33aa | |||
| 16c7ab1ba0 | |||
| 9ef5d8f318 | |||
| 6a634e309b | |||
| 13f58447e2 | |||
| bc72211e7b | |||
| 230e124ddb | |||
| 10016ab3fd | |||
| 69dc003a0b | |||
| ae2fd55575 | |||
| f102fb75b6 | |||
| 8a7240ddfd | |||
| ac70ec0340 | |||
| dbd90a4d78 | |||
| 5b1f9b3c2b | |||
| 08a07f2d30 | |||
| b1143c9481 | |||
| 73e1d0054c | |||
| 33ab261817 | |||
| 230ff0576a | |||
| e3371d7c53 | |||
| 9b2b93d9bd | |||
| d7fb721b4d | |||
| e7cfa5c2bf | |||
| 2a3212a0a3 | |||
| 7a08a76875 | |||
| 22a09dddc6 | |||
| 8c72549cc2 | |||
| bba5214930 | |||
| fb194b9488 | |||
| 56817e9faa | |||
| e87fb8a8e1 | |||
| 5be0fc40ed | |||
| a98337b359 | |||
| 143d016899 | |||
| 3d70e55d72 | |||
| dbcc44dc80 | |||
| db87fd52ca | |||
| 792509e987 | |||
| 166e0d63d0 | |||
| 0d7f19bb62 | |||
| 607045d592 | |||
| 51d32243fe | |||
| 1c1a1bc9ed | |||
| 553fdb318f | |||
| 607ed4ee46 | |||
| ec1cece270 | |||
| 4656e386fb | |||
| f29f2f99b1 | |||
| cc27f08588 | |||
| 99fe398b59 | |||
| cb89e02432 | |||
| ac69392cd7 | |||
| a5fb372e1e | |||
| da720712f3 | |||
| 0cb3dc8782 | |||
| dfd95f0115 | |||
| 7636670a77 | |||
| fe6247a7f8 | |||
| 2b90ef1694 | |||
| 099138fb9a | |||
| cbe31d8dfd | |||
| 06b0930b6a | |||
| 7b7be341b6 | |||
| 751c77f87b | |||
| 634ac03c5e | |||
| 8cab53c64d | |||
| edef295b11 | |||
| 64e447354e | |||
| da1f7c762d | |||
| 89366bdbf9 | |||
| 78efa0e36c | |||
| 3a8b3db174 | |||
| 1a01e80b9c | |||
| d59027c40e | |||
| c197c2aa27 | |||
| 01cd34957e | |||
| 864517e5a2 | |||
| 1dd5d2ec1f | |||
| 6da835f4bc | |||
| 5cca077e4a | |||
| e290aa8c13 | |||
| 9c51d50318 | |||
| 1c3a46adda | |||
| 4407e81c61 | |||
| ad76e77fce | |||
| ac5b9055f6 | |||
| c18074a310 | |||
| ed703d8e2c | |||
| 9c53d0769e | |||
| 90532f5e3c | |||
| 2bc04d23fb | |||
| 7f6da764e1 | |||
| 6926ef8f67 | |||
| bba2b7cfce | |||
| dc1e55ce1a | |||
| 408e868237 | |||
| 97abb12473 | |||
| d26bffbc3f | |||
| 2f3bd9dae7 | |||
| 256e5dff55 | |||
| acb6b75fe9 | |||
| 683fd713c4 | |||
| 3591ae0103 | |||
| 5fedfd79a5 | |||
| bdde40e755 | |||
| 88c4963328 | |||
| 67a81eff42 | |||
| add43e91dc | |||
| b3c7a6d566 | |||
| 424bd49ede | |||
| 6a58404507 | |||
| d4ce8362b1 | |||
| caa12dbc57 | |||
| 1122b3c14d | |||
| a357649da5 | |||
| 332a3c7984 | |||
| fcd761b9d7 | |||
| b0d5f062e3 | |||
| 2c0753225a | |||
| 3b898664ee | |||
| 61fb5863df | |||
| a4ec297925 | |||
| 93d7e60d43 | |||
| 338264b5f6 | |||
| 19b51caa2c | |||
| 8c08b4373c | |||
| 0b38882a91 | |||
| 3364d69a3b | |||
| e6c9bfa4a9 | |||
| 7a3e182e9c | |||
| 2471f6b01c | |||
| 1fefafd09f | |||
| 8a63dc3151 | |||
| 403008816c | |||
| 62d552ffe2 | |||
| bcaa4217bc | |||
| 0823f6dfab | |||
| 87bb554aec | |||
| 36447cb2b5 | |||
| 3b2c6f09cb | |||
| 63414b9653 | |||
| 5f24bb0267 | |||
| 52519d45b9 | |||
| 78728df099 | |||
| 732db27cd6 | |||
| 3cad63fbd8 | |||
| d2be5939dc | |||
| 9a77d03047 | |||
| 8efcec67cc | |||
| 4fbd4bbd8d | |||
| 2fae296cbc | |||
| cef8466419 | |||
| 083159ebbe | |||
| 32e440cffc | |||
| 89c8c93b9a | |||
| 296074f548 | |||
| 2ccfaffa74 | |||
| 192672a162 | |||
| 7f4e658d3d | |||
| ff57695855 | |||
| ae8deb1246 | |||
| b9dcb35e9b | |||
| 25d9f5a804 | |||
| 1b234cb7af | |||
| d219442945 | |||
| 2b33be47cb | |||
| 499baced12 | |||
| 7aa9fecab8 | |||
| 9b6c82d804 | |||
| c3117b7544 | |||
| 67744384e8 | |||
| 17c401d09a | |||
| 488aea15f4 | |||
| 43df853ee3 | |||
| 28d5dcb578 | |||
| 7eb15c46a2 | |||
| 1fac36e2cb | |||
| 4b6c87b6e7 | |||
| ce6c2b2072 | |||
| 3e94a2c54d | |||
| b1e488f5d7 | |||
| 03d867160f | |||
| 9870e65c5f | |||
| aa839b9ff0 | |||
| fdb66aa237 | |||
| e0ca5fdd51 | |||
| 681c1c53e4 | |||
| 631c4863d8 | |||
| 944bda12c7 | |||
| bc36c4dea4 | |||
| 722766958b | |||
| 73fd3ca2eb | |||
| efe8ad51ed | |||
| d5b62465f0 | |||
| bc76e7255b | |||
| 8dd23ad2f2 | |||
| bce75d7c68 | |||
| 815053e403 | |||
| 6173abe20b | |||
| 6fcf0afa35 | |||
| 05521e276f | |||
| 38ffbbd7dd | |||
| 47e1878e4c | |||
| dc6f149973 | |||
| 420f6bfccb | |||
| ae33e11694 | |||
| 4d8b0282b4 | |||
| 00845fca88 | |||
| 84fe86c7fd | |||
| 5e1ed9d5d2 | |||
| 2ba668732a | |||
| 2cb73b71d1 | |||
| 16a2ce2b13 | |||
| 18e87a7544 | |||
| f81431dd72 | |||
| 04bdb9f813 | |||
| 1cfe281a76 | |||
| 6165bd7d1e | |||
| 0135564ad9 | |||
| 6847cbeff8 | |||
| 84daf33c03 | |||
| 86cbdb893a | |||
| 11ee680d38 | |||
| 4c5b382b69 | |||
| 39f4a776d6 | |||
| a250116694 | |||
| 9a73d71f47 | |||
| 73aaca05f8 | |||
| a993112098 | |||
| 9145d5ec3e | |||
| efc863844c | |||
| cc260e7864 | |||
| 42ce8f7f55 | |||
| 661390aef3 | |||
| ed4a70e765 | |||
| 1866968310 | |||
| 5fbf98ec23 | |||
| 5d2bb2c1b9 | |||
| 9039ddbb56 | |||
| 8f8510fc22 | |||
| 1e99ea6a51 | |||
| 016e1e675e | |||
| 1240641f76 | |||
| f1a34f0908 | |||
| 01bda54e05 | |||
| bc04afe183 | |||
| ac086ae616 | |||
| f75a2b093f | |||
| 4dba7b0203 | |||
| d3cd3c0a9b | |||
| e351874a0a | |||
| dcdf4fc78b | |||
| cf38d8c55b | |||
| b0233a33a1 | |||
| c3235db9ee | |||
| 738113bac8 | |||
| 6613ee40e6 | |||
| ce6035d953 | |||
| 2bc4793ee8 | |||
| 9c6e34bfc1 | |||
| 4e65ff31a8 | |||
| 15461c7883 | |||
| de5352cfcf | |||
| ae26ed994e | |||
| 94745f6274 | |||
| dbfa0d88bb | |||
| cf3b5cb2fc | |||
| 192a225854 | |||
| 3508f76719 | |||
| a7d081fac0 | |||
| ee774f6e5b | |||
| 80f34598f8 | |||
| 7e168c8ad2 | |||
| 3ebc2c2442 | |||
| 631d86f723 | |||
| 3ac97f2b3d | |||
| ed55346be7 | |||
| e31ec1f7ed | |||
| 70e4fd2865 | |||
| 7898490779 | |||
| 0893e83c92 | |||
| ef334d0070 | |||
| 9f08d03978 | |||
| 3ca6c4bfb9 | |||
| cfea2095ca | |||
| 171bec3b0e | |||
| 93891ad2e9 | |||
| eece726651 | |||
| dc6665caed | |||
| 5b592cbaf4 | |||
| 348138d7cd | |||
| 6a34a4ebeb | |||
| 5ca247c749 | |||
| b16bffbf76 | |||
| b2aec3706d | |||
| d577c5def1 | |||
| a4dd14952e | |||
| 8879b3733e | |||
| 35b02226ca | |||
| 814feaa2ab | |||
| aa2e66dcaf | |||
| 7b7b12e477 | |||
| 187cd0a058 | |||
| 0c690af2fe | |||
| 40ecd2d8e5 | |||
| 484286d536 | |||
| d56b62dcda | |||
| b94125ac14 | |||
| 3f34319398 | |||
| ba076a29b9 | |||
| 13000c7350 | |||
| fd2649fc65 | |||
| 437b09c155 | |||
| b2b015a53b | |||
| 5bea4c5692 | |||
| 1b527b7acf | |||
| 4b8629b6b8 | |||
| ed81d19ce9 | |||
| 3497bf2d82 | |||
| afcf03fd2c | |||
| 582612b000 | |||
| 7bf32ccadb | |||
| f5c18861b6 | |||
| 4acd75b904 | |||
| cd6dd22b19 | |||
| 139c532019 | |||
| e5b57bf01c | |||
| 5ecd6d4e0a | |||
| 03bbe9aab1 | |||
| 0ef9d54ccd | |||
| 6ade77efa2 | |||
| 91fa865bf2 | |||
| 10ae76673c | |||
| 9497757842 | |||
| bb5abe0e9c | |||
| 76c0ddfc0b | |||
| 36b888e781 | |||
| a476972e2e | |||
| 866d3fb573 | |||
| 70cf0a389f | |||
| 7d4ccea579 | |||
| 654dd1d5e8 | |||
| bf114f6ee3 | |||
| 5727eaf767 | |||
| 346e98330c | |||
| 2b1f10266a | |||
| fc7970fdf0 | |||
| 65957e99ba | |||
| 7f9a94f8bc | |||
| cb560e2441 | |||
| 55856565c2 | |||
| 13968343d4 | |||
| 4c428121b9 | |||
| 4816f7ee5c | |||
| ce53fbde50 | |||
| 1516a69cd2 | |||
| 7a77fdae4f | |||
| b13da18e11 | |||
| f98f8a3892 | |||
| 77c4a7fd66 | |||
| e281413919 | |||
| 2007ddd3f8 | |||
| d8922fe3e9 | |||
| 6c611df8f0 | |||
| 6be24df5bc | |||
| 4759aacba9 | |||
| 802bfc259c | |||
| 64db8d166e | |||
| d2a769e196 | |||
| 68a8c8907d | |||
| 701d61080a | |||
| a8cc449706 | |||
| 2aa212b19c | |||
| 1f23cfe9c7 | |||
| 0fa8e47fb5 | |||
| 8043784fd7 | |||
| 526a6b31e5 | |||
| 14fd064a62 | |||
| 3178afbf0c | |||
| ce3b616432 | |||
| 54a761905d | |||
| aa531d7bd1 | |||
| d7e9ae1215 | |||
| 6cf9ede88e | |||
| 6092291bd7 | |||
| 3d0f11212f | |||
| 6194e002e2 | |||
| 75545d4d1c | |||
| d67eb2f2db | |||
| 6b8153ff0f | |||
| fb132732f1 | |||
| 336b157497 | |||
| d16975a9de | |||
| 87f6b36bab | |||
| 43fccf5617 | |||
| a5b3bcf41c | |||
| 8801d9c286 | |||
| a8e114f351 | |||
| 9a3a9b46e5 | |||
| 934204ec18 | |||
| 7cb8f8fb44 | |||
| 8d34bf2fea | |||
| 8801e69dba | |||
| f4afa398a1 | |||
| 32063278bd | |||
| 92208d2f85 | |||
| ab7c74b4b9 | |||
| e283abe171 | |||
| d7620f68bb | |||
| 971d97e2ec | |||
| 559d5efc04 | |||
| 85042820fb | |||
| 24a2eec815 | |||
| d987a79ab1 | |||
| eba09353e6 | |||
| 297660c9a3 | |||
| 8343c05fd8 | |||
| 7c3d064786 | |||
| c2ccc1cbdf | |||
| 04e080660a | |||
| f3cca88384 | |||
| 978bbd2d49 | |||
| 652feebd86 | |||
| 16ccbc4f61 | |||
| 072d45fd01 | |||
| 4439e39319 | |||
| b49c3a1a1e | |||
| c7addd4886 | |||
| 6df60aff52 | |||
| e7a080d6e6 | |||
| 661a728764 | |||
| 89303fd2dc | |||
| 1f8be1ca66 | |||
| cbc2024092 | |||
| f0ff7023c3 | |||
| 6e8728a364 | |||
| f179a63dd4 | |||
| 3a71c1e595 | |||
| ef7a61a67e | |||
| a6b2ee785b | |||
| d5a1336e6b | |||
| d4312b731a | |||
| 66f051386e | |||
| 8b3f9684e0 | |||
| 331f32deac | |||
| bb80c96754 | |||
| 0d8e19c26f | |||
| ed2fd2d0ca | |||
| 7c60151cb8 | |||
| 965308a32c | |||
| 92c612a9de | |||
| a7b53abcad | |||
| d575e1f613 | |||
| 2ba458387d | |||
| 98489a1d0c | |||
| 51d501aab2 | |||
| 841bdf1c07 | |||
| 86cac55c7c | |||
| c0995399d4 | |||
| de6cc287e5 | |||
| afd6771163 | |||
| 4cda028609 | |||
| 8ecce7642b | |||
| d1d5761232 | |||
| 759cba1a8d | |||
| 23cd40a8ec | |||
| f3188c1d09 | |||
| 2f4967f100 | |||
| 4fe4e7457c | |||
| d4e7274d4b | |||
| cffa015554 | |||
| 1104c7d75b | |||
| 4c6b4447db | |||
| 741a37b338 | |||
| 1157c5d341 | |||
| e48adebfb7 | |||
| 0a61dcb486 | |||
| 4b51eaadf8 | |||
| e2457ca16d | |||
| bd62790080 | |||
| 53fdcafa44 | |||
| af6f2483be | |||
| d8522aa349 | |||
| bae3121683 | |||
| 54c0d464b0 | |||
| cf89e8653c | |||
| 0c3500f532 | |||
| c12f525df4 | |||
| e7ba830691 | |||
| 4eb0716711 | |||
| ed90f3b7ea | |||
| 14b19ecf5e | |||
| 644432a14c | |||
| a03e370a09 | |||
| 23677d3ddb | |||
| fc781560a3 | |||
| c9199ee663 | |||
| 6f18adedef | |||
| 6ad894cd58 | |||
| cde2f1a868 | |||
| 6a831495de | |||
| 6e2c38f54d | |||
| 00e7e31418 | |||
| ff4b3e20c1 | |||
| 269fb43b36 | |||
| 7530654328 | |||
| c7bd464384 | |||
| ef1874d1f3 | |||
| c6d8205fdd | |||
| 55150a669a | |||
| 1eb9e22d45 | |||
| c0de8fb737 | |||
| 557e3894d7 | |||
| 38a9695413 | |||
| 293e0336b0 | |||
| 1f5bc0a1cd | |||
| 1fe666192b | |||
| 29541e735d | |||
| f5b567d44b | |||
| 5ee3bbee90 | |||
| 80927c5811 | |||
| ca8b344e20 | |||
| 3dab93874d | |||
| 7550f90a57 | |||
| d78fea87d1 | |||
| 27cee7db0a | |||
| 60acba3840 | |||
| 51bed36370 | |||
| 6d940213ac | |||
| 494b527fa7 | |||
| 8ce84cb2ea | |||
| d981c2a3ec | |||
| 537e20065a | |||
| 97578b4dae | |||
| fa12564607 | |||
| 54bcb9ae25 | |||
| ad7ce0d402 | |||
| 085e0ea8ef | |||
| bb52c4e8d3 | |||
| 295af335c1 | |||
| 2c2e18c37a | |||
| adfb75e3c6 | |||
| 9bff5c60df | |||
| 3ba008d4b2 | |||
| 4e45a2f8e2 | |||
| 4dbd8452eb | |||
| 45a8db9c08 | |||
| d930a410fb | |||
| 66505ffc40 | |||
| 045de959b9 | |||
| 3ca11d5235 | |||
| d5d8ac01e3 | |||
| ace81c053c | |||
| 1e95c419b8 | |||
| 49ed63d26a | |||
| 6ff2685668 | |||
| c4573c04aa | |||
| d57abdb3f7 | |||
| 4050e89446 | |||
| b6620c737f | |||
| 0c8e908841 | |||
| 5595e196a8 | |||
| f92e4146d1 | |||
| 8b7108e3c9 | |||
| caf702cc88 | |||
| cf2c49ed7f | |||
| ccd52abf5d | |||
| 74c574015d | |||
| 1f1a6fb6d2 | |||
| 8632e893b0 | |||
| c2b6e127fa | |||
| 06eceeb09f | |||
| 8133d468b9 | |||
| 074a354fa9 | |||
| e191582a02 | |||
| 6fbe926cda | |||
| ebbc224e09 | |||
| 2c6aa4c300 | |||
| f7a8f17fc7 | |||
| 191efbb558 | |||
| bf873d6f02 | |||
| e741107c55 | |||
| 82f4b99d99 | |||
| 7210b7ae1d | |||
| afed23c001 | |||
| 1f69cc2989 | |||
| 3401833c83 | |||
| 06606e2816 | |||
| eba64e1f31 | |||
| 81dd1df1b1 | |||
| dbafbb0de5 | |||
| 1d0aa7b7c6 | |||
| afd02ca48c | |||
| 67db7616ad | |||
| 3d7c752e27 | |||
| f02833d634 | |||
| 0eb373e0e6 | |||
| fd3071843c | |||
| a631ceb223 | |||
| a713928210 | |||
| 05fa20df81 | |||
| 125573602f | |||
| ed5dfbcd66 | |||
| d2e52b2376 | |||
| a56aaa9877 | |||
| 79bb7b1f0b | |||
| b936e52874 | |||
| 0d52ff0f10 | |||
| baf52e902d | |||
| dffea9e2b7 | |||
| 4a411b8f82 | |||
| 278bfc4bb2 | |||
| 18731173f9 | |||
| d43fb404d7 | |||
| da984ad187 | |||
| 4015357ce5 | |||
| dc3d11ad19 | |||
| 0e1545eb04 | |||
| ec7cabf5c9 | |||
| 3051beba2f | |||
| 92304323b1 | |||
| c28123a872 | |||
| d798423813 | |||
| 2583e77cc7 | |||
| f66836fee4 | |||
| 0ccc445d53 | |||
| b7d5fa1cbe | |||
| 8bb3942453 | |||
| 51a79cebcb | |||
| 36bcf64008 | |||
| 5c6630605b | |||
| 125827406c | |||
| 62c21422a6 | |||
| 98d489712e | |||
| 2cab2d8ef1 | |||
| 8fa2bb72bc | |||
| d151f94937 | |||
| 5b74b7185b | |||
| 4f0be2ae4e | |||
| bb9badeb2a | |||
| c287c8361d | |||
| ade7127c79 | |||
| d341483f1f | |||
| b36acbc857 | |||
| a4fea38b94 | |||
| 300c5c0c99 | |||
| 152537c4e9 | |||
| 8b46bf6bc9 | |||
| aef861eb41 | |||
| f61d36861d | |||
| 2af0348cea | |||
| 78c5743494 | |||
| 2cb9fbd043 | |||
| e9dad5dbf4 | |||
| 54895fc2a1 | |||
| 60a12b4161 | |||
| cd7e58ba41 | |||
| 9391475dc3 | |||
| 7840803add | |||
| 7d77de2834 | |||
| ab044cada6 | |||
| d010e0cc7d | |||
| 40f728b1aa | |||
| 23abb26405 | |||
| fd55bc8e1d | |||
| 541aaa4e08 | |||
| f22c422547 | |||
| 0e461f0c07 | |||
| 5074448443 | |||
| 8d66af11e6 | |||
| 169948bb47 | |||
| 58d9469574 | |||
| 8d858a2360 | |||
| 5540748890 | |||
| f8a52be817 | |||
| 3b5f1105f6 | |||
| 663ccc5449 | |||
| 263f47819f | |||
| 6b75475ce3 | |||
| 07c354a8c0 | |||
| 1391579599 | |||
| 5d2bd1d84c | |||
| bf77e212af | |||
| eef2f9c31e | |||
| 438627c2c3 |
+4
-7
@@ -1,4 +1,6 @@
|
||||
/build/
|
||||
build/
|
||||
angularjs.netrc
|
||||
jstd.log
|
||||
.DS_Store
|
||||
gen_docs.disable
|
||||
test.disable
|
||||
@@ -6,14 +8,9 @@ regression/temp*.html
|
||||
performance/temp*.html
|
||||
.idea/workspace.xml
|
||||
*~
|
||||
*.swp
|
||||
angular.js.tmproj
|
||||
/node_modules/
|
||||
/components/
|
||||
/bower_components/
|
||||
node_modules
|
||||
angular.xcodeproj
|
||||
.idea
|
||||
.agignore
|
||||
libpeerconnection.log
|
||||
npm-debug.log
|
||||
/tmp/
|
||||
|
||||
+3
-10
@@ -7,20 +7,13 @@ env:
|
||||
- SAUCE_USERNAME=angular-ci
|
||||
- SAUCE_ACCESS_KEY=9b988f434ff8-fbca-8aa4-4ae3-35442987
|
||||
- SAUCE_CONNECT_READY_FILE=/tmp/sauce-connect-ready
|
||||
- LOGS_DIR=/tmp/angular-build/logs
|
||||
|
||||
before_script:
|
||||
- mkdir -p $LOGS_DIR
|
||||
- export SAUCE_ACCESS_KEY=`echo $SAUCE_ACCESS_KEY | rev`
|
||||
- ./lib/sauce/sauce_connect_setup.sh
|
||||
- npm install -g grunt-cli
|
||||
- grunt bower
|
||||
- grunt bower
|
||||
- grunt package-without-bower
|
||||
- grunt ci-checks
|
||||
- grunt ci-checks package
|
||||
- ./lib/sauce/sauce_connect_block.sh
|
||||
|
||||
script:
|
||||
- ./travis_build.sh
|
||||
|
||||
after_script:
|
||||
- ./travis_print_logs.sh
|
||||
- grunt parallel:travis --reporters dots --browsers SL_Chrome
|
||||
|
||||
+3
-746
@@ -1,740 +1,3 @@
|
||||
<a name="1.2.2"></a>
|
||||
# 1.2.2 consciousness-inertia (2013-11-22)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$animate:**
|
||||
- ensure keyframe animations are blocked around the reflow
|
||||
([6760d7a3](https://github.com/angular/angular.js/commit/6760d7a315d7ea5cbd4f8ab74b200f754a2041f4),
|
||||
[#5018](https://github.com/angular/angular.js/issues/5018))
|
||||
- ensure transition animations are unblocked before the dom operation occurs
|
||||
([062fbed8](https://github.com/angular/angular.js/commit/062fbed8fc3f7bc55433f8c6915c27520e6f63c5),
|
||||
[#5014](https://github.com/angular/angular.js/issues/5014),
|
||||
[#4265](https://github.com/angular/angular.js/issues/4265))
|
||||
- ensure addClass/removeClass animations do not snap during reflow
|
||||
([76e4db6f](https://github.com/angular/angular.js/commit/76e4db6f3d15199ac1fbe85f9cfa6079a1c4fa56),
|
||||
[#4892](https://github.com/angular/angular.js/issues/4892))
|
||||
- ensure the DOM operation isn't run twice
|
||||
([7067a8fb](https://github.com/angular/angular.js/commit/7067a8fb0b18d5b5489006e1960cee721a88b4d2),
|
||||
[#4949](https://github.com/angular/angular.js/issues/4949))
|
||||
- **$compile:**
|
||||
- secure form[action] & iframe[srcdoc]
|
||||
([0421cb42](https://github.com/angular/angular.js/commit/0421cb4200e672818ed10996e92311404c150c3a),
|
||||
[#4927](https://github.com/angular/angular.js/issues/4927),
|
||||
[#4933](https://github.com/angular/angular.js/issues/4933))
|
||||
- ensure CSS classes are added and removed only when necessary
|
||||
([0cd7e8f2](https://github.com/angular/angular.js/commit/0cd7e8f22721f62b62440bb059ae764ebbe7b42a))
|
||||
- **$httpBackend:** only IE8 and below can't use `script.onload` for JSONP
|
||||
([a3172a28](https://github.com/angular/angular.js/commit/a3172a285fd74b5aa6c8d68a4988c767c06f549c),
|
||||
[#4523](https://github.com/angular/angular.js/issues/4523),
|
||||
[#4527](https://github.com/angular/angular.js/issues/4527),
|
||||
[#4922](https://github.com/angular/angular.js/issues/4922))
|
||||
- **$parse:** allow for new lines in expr when promise unwrapping is on
|
||||
([40647b17](https://github.com/angular/angular.js/commit/40647b179c473f3f470bb1b3237d6f006269582f),
|
||||
[#4718](https://github.com/angular/angular.js/issues/4718))
|
||||
- **$resource:** Always return a resource instance when calling class methods on resources.
|
||||
([f6ecf9a3](https://github.com/angular/angular.js/commit/f6ecf9a3c9090593faf5fa50586c99a56b51c776),
|
||||
[#4545](https://github.com/angular/angular.js/issues/4545),
|
||||
[#5061](https://github.com/angular/angular.js/issues/5061))
|
||||
- **httpBackend:** should not read response data when request is aborted
|
||||
([6f1050df](https://github.com/angular/angular.js/commit/6f1050df4fa885bd59ce85adbef7350ea93911a3),
|
||||
[#4913](https://github.com/angular/angular.js/issues/4913),
|
||||
[#4940](https://github.com/angular/angular.js/issues/4940))
|
||||
- **loader:** expose `$$minErr` to modules such as`ngResource`
|
||||
([9e89a31b](https://github.com/angular/angular.js/commit/9e89a31b129e40c805178535c244899ffafb77d8),
|
||||
[#5050](https://github.com/angular/angular.js/issues/5050))
|
||||
- **ngAnimate:**
|
||||
- correctly retain and restore existing styles during and after animation
|
||||
([c42d0a04](https://github.com/angular/angular.js/commit/c42d0a041890b39fc98afd357ec1307a3a36208d),
|
||||
[#4869](https://github.com/angular/angular.js/issues/4869))
|
||||
- use a fallback CSS property that doesn't break existing styles
|
||||
([1d50663b](https://github.com/angular/angular.js/commit/1d50663b38ba042e8d748ffa6d48cfb5e93cfd7e),
|
||||
[#4902](https://github.com/angular/angular.js/issues/4902),
|
||||
[#5030](https://github.com/angular/angular.js/issues/5030))
|
||||
- **ngClass:** ensure that ngClass only adds/removes the changed classes
|
||||
([6b8bbe4d](https://github.com/angular/angular.js/commit/6b8bbe4d90640542eed5607a8c91f6b977b1d6c0),
|
||||
[#4960](https://github.com/angular/angular.js/issues/4960),
|
||||
[#4944](https://github.com/angular/angular.js/issues/4944))
|
||||
- **ngController:** fix issue with ngInclude on the same element
|
||||
([6288cf5c](https://github.com/angular/angular.js/commit/6288cf5ca471b0615a026fdb4db3ba242c9d8f88),
|
||||
[#4431](https://github.com/angular/angular.js/issues/4431))
|
||||
- **ngInclude:**
|
||||
- Don't throw when the ngInclude element contains content with directives.
|
||||
([0a7cbb33](https://github.com/angular/angular.js/commit/0a7cbb33b06778833a4d99b1868cc07690a827a7))
|
||||
- allow ngInclude to load scripts when jQuery is included
|
||||
([c47abd0d](https://github.com/angular/angular.js/commit/c47abd0dd7490576f4b84ee51ebaca385c1036da),
|
||||
[#3756](https://github.com/angular/angular.js/issues/3756))
|
||||
- **ngMock:** fixes httpBackend expectation with body object
|
||||
([4d16472b](https://github.com/angular/angular.js/commit/4d16472b918a3482942d76f1e273a5aa01f65e83),
|
||||
[#4956](https://github.com/angular/angular.js/issues/4956))
|
||||
- **ngView:** Don't throw when the ngView element contains content with directives.
|
||||
([e6521e74](https://github.com/angular/angular.js/commit/e6521e7491242504250b57dd0ee66af49e653c33),
|
||||
[#5069](https://github.com/angular/angular.js/issues/5069))
|
||||
- **tests:** Correct tests for IE11
|
||||
([57924234](https://github.com/angular/angular.js/commit/579242346c4202ea58fc2cae6df232289cbea0bb),
|
||||
[#5046](https://github.com/angular/angular.js/issues/5046))
|
||||
- **input:** hold listener during text composition
|
||||
([a4e6d962](https://github.com/angular/angular.js/commit/a4e6d962d78b26f5112d48c4f88c1e6234d0cae7),
|
||||
[#4684](https://github.com/angular/angular.js/issues/4684))
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="1.2.1"></a>
|
||||
# 1.2.1 underscore-empathy (2013-11-14)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$compile:**
|
||||
- accessing controllers of transcluded directives from children
|
||||
([90f87072](https://github.com/angular/angular.js/commit/90f87072e83234ae366cfeb3c281503c31dad738),
|
||||
[#4935](https://github.com/angular/angular.js/issues/4935))
|
||||
- correctly handle interpolated style in replace templates
|
||||
([e1254b26](https://github.com/angular/angular.js/commit/e1254b266dfa2d4e3756e4317152dbdbcabe44be),
|
||||
[#4882](https://github.com/angular/angular.js/issues/4882))
|
||||
- **$resource:** don't use $parse for @dotted.member
|
||||
([9577702e](https://github.com/angular/angular.js/commit/9577702e8d2519c1a60f5ac4058e63bd7b919815))
|
||||
- **bootstrap:** make IE8 happy
|
||||
([a61b65d0](https://github.com/angular/angular.js/commit/a61b65d01b468502fe53d68818949d3fcc9f20f6))
|
||||
- **loader:** don't rely on internal APIs
|
||||
([8425e9fe](https://github.com/angular/angular.js/commit/8425e9fe383c17f6a5589c778658c5fc0570ae8f),
|
||||
[#4437](https://github.com/angular/angular.js/issues/4437), [#4874](https://github.com/angular/angular.js/issues/4874))
|
||||
- **minErr:** remove references to internal APIs
|
||||
([94764ee0](https://github.com/angular/angular.js/commit/94764ee08910726db1db7a1101c3001500306dea))
|
||||
- **ngIf:** don't create multiple elements when changing from a truthy value to another thruthy value
|
||||
([4612705e](https://github.com/angular/angular.js/commit/4612705ec297bc6ba714cb7a98f1be6aff77c4b8),
|
||||
[#4852](https://github.com/angular/angular.js/issues/4852))
|
||||
- **urlUtils:**
|
||||
- make removal of windows drive from path safer
|
||||
([89f435de](https://github.com/angular/angular.js/commit/89f435de847635e3ec339726e6f83cf3f0ee9091),
|
||||
[#4939](https://github.com/angular/angular.js/issues/4939))
|
||||
- return right path for file:// on windows
|
||||
([f925e8ca](https://github.com/angular/angular.js/commit/f925e8caa6c51a7d45ca9ead30601ec2e9d4464c),
|
||||
[#4680](https://github.com/angular/angular.js/issues/4680))
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- **$parse:** revert hiding "private" properties
|
||||
([4ab16aaa](https://github.com/angular/angular.js/commit/4ab16aaaf762e9038803da1f967ac8cb6650727d),
|
||||
[#4926](https://github.com/angular/angular.js/issues/4926), [#4842](https://github.com/angular/angular.js/issues/4842), [#4865](https://github.com/angular/angular.js/issues/4865), [#4859](https://github.com/angular/angular.js/issues/4859), [#4849](https://github.com/angular/angular.js/issues/4849))
|
||||
|
||||
|
||||
|
||||
<a name="1.2.0"></a>
|
||||
# 1.2.0 timely-delivery (2013-11-08)
|
||||
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
|
||||
- **animations:**
|
||||
- ensure CSS transitions can work with inherited CSS class definitions
|
||||
([9d69a0a7](https://github.com/angular/angular.js/commit/9d69a0a7c75c937c0a49bb705d31252326b052df))
|
||||
- provide support for staggering animations with CSS
|
||||
([74848307](https://github.com/angular/angular.js/commit/74848307443c00ab07552336c56ddfa1e9ef6eff))
|
||||
- **$parse:** secure expressions by hiding "private" properties
|
||||
([3d6a89e8](https://github.com/angular/angular.js/commit/3d6a89e8888b14ae5cb5640464e12b7811853c7e))
|
||||
- **docs:**
|
||||
- provide index pages for each angular module
|
||||
([a7e12b79](https://github.com/angular/angular.js/commit/a7e12b7959212f2fa88fe17d5a045cc9d8b22922))
|
||||
- add forward slash shortcut key for search bar
|
||||
([74912802](https://github.com/angular/angular.js/commit/74912802c644ca929e39a7583cb7a9a05f12e91f))
|
||||
- **jqLite:** expose isolateScope() getter similar to scope()
|
||||
([27e9340b](https://github.com/angular/angular.js/commit/27e9340b3c25b512e45213b39811098d07e12e3b))
|
||||
- **misc:** add externs file for Closure Compiler
|
||||
([9d0a6977](https://github.com/angular/angular.js/commit/9d0a69772c39bfc751ca2000c3b4b3381e51fe93))
|
||||
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$animate:**
|
||||
- don't force animations to be enabled
|
||||
([98adc9e0](https://github.com/angular/angular.js/commit/98adc9e0383dc05efad168f30a0725cb67f5eda8))
|
||||
- only apply the fallback property if any transition animations are detected
|
||||
([94700807](https://github.com/angular/angular.js/commit/9470080762aecca5285d0f5cac4ae01540bbad4c))
|
||||
- avoid hanging animations if the active CSS transition class is missing
|
||||
([b89584db](https://github.com/angular/angular.js/commit/b89584db10b63f346cbfd03f67fb92504e5bf362),
|
||||
[#4732](https://github.com/angular/angular.js/issues/4732), [#4490](https://github.com/angular/angular.js/issues/4490))
|
||||
- ensure staggering animations understand multiple delay values
|
||||
([41a2d5b3](https://github.com/angular/angular.js/commit/41a2d5b30f4feb90651eb577cf44852a6d2be72c))
|
||||
- ensure the active class is not applied if cancelled during reflow
|
||||
([e53ff431](https://github.com/angular/angular.js/commit/e53ff431e1472c0b2d5405d267d4e403ca31087e),
|
||||
[#4699](https://github.com/angular/angular.js/issues/4699))
|
||||
- use direct DOM comparison when checking for $rootElement
|
||||
([d434eabe](https://github.com/angular/angular.js/commit/d434eabec3955f8d56c859c93befe711bfa1de27),
|
||||
[#4679](https://github.com/angular/angular.js/issues/4679))
|
||||
- ensure former nodes are fully cleaned up when a follow-up structural animation takes place
|
||||
([7f0767ac](https://github.com/angular/angular.js/commit/7f0767acaba1ec3c8849244a604b0d1c8c376446),
|
||||
[#4435](https://github.com/angular/angular.js/issues/4435))
|
||||
- ensure enable/disable animations work when the document node is used
|
||||
([6818542c](https://github.com/angular/angular.js/commit/6818542c694aec6c811fb2fe2f86f7d16544c39b),
|
||||
[#4669](https://github.com/angular/angular.js/issues/4669))
|
||||
- skip unnecessary addClass/removeClass animations
|
||||
([76b628bc](https://github.com/angular/angular.js/commit/76b628bcb3511210d312ed667e5c14d908a9fed1),
|
||||
[#4401](https://github.com/angular/angular.js/issues/4401), [#2332](https://github.com/angular/angular.js/issues/2332))
|
||||
- ensure animations work properly when the $rootElement is being animated
|
||||
([2623de14](https://github.com/angular/angular.js/commit/2623de1426219dc799f63a3d155911f93fc03461),
|
||||
[#4397](https://github.com/angular/angular.js/issues/4397), [#4231](https://github.com/angular/angular.js/issues/4231))
|
||||
- only cancel class-based animations if the follow-up class contains CSS transition/keyframe animation code
|
||||
([f5289fe8](https://github.com/angular/angular.js/commit/f5289fe84ffc1f2368dae7bd14c420abbe76749e),
|
||||
[#4463](https://github.com/angular/angular.js/issues/4463), [#3784](https://github.com/angular/angular.js/issues/3784))
|
||||
- **$compile:**
|
||||
- don't leak isolate scope state when replaced directive is used multiple times
|
||||
([b5af198f](https://github.com/angular/angular.js/commit/b5af198f0d5b0f2b3ddb31ea12f700f3e0616271))
|
||||
- correct isolate scope distribution to controllers
|
||||
([3fe4491a](https://github.com/angular/angular.js/commit/3fe4491a6bf57ddeb312b8a30cf1706f6f1d2355))
|
||||
- replaced element has isolate scope
|
||||
([97c7a4e3](https://github.com/angular/angular.js/commit/97c7a4e3791d7cb05c3317cc5f0c49ab93810bf6))
|
||||
- only pass isolate scope to children that belong to the isolate directive
|
||||
([d0efd5ee](https://github.com/angular/angular.js/commit/d0efd5eefcc0aaf167c766513e152b74dd31bafe))
|
||||
- make isolate scope truly isolate
|
||||
([909cabd3](https://github.com/angular/angular.js/commit/909cabd36d779598763cc358979ecd85bb40d4d7),
|
||||
[#1924](https://github.com/angular/angular.js/issues/1924), [#2500](https://github.com/angular/angular.js/issues/2500))
|
||||
- don't instantiate controllers twice for element transclude directives
|
||||
([18ae985c](https://github.com/angular/angular.js/commit/18ae985c3a3147b589c22f6ec21bacad2f578e2b),
|
||||
[#4654](https://github.com/angular/angular.js/issues/4654))
|
||||
- attribute bindings should not break due to terminal directives
|
||||
([79223eae](https://github.com/angular/angular.js/commit/79223eae5022838893342c42dacad5eca83fabe8),
|
||||
[#4525](https://github.com/angular/angular.js/issues/4525), [#4528](https://github.com/angular/angular.js/issues/4528), [#4649](https://github.com/angular/angular.js/issues/4649))
|
||||
- instantiate controlers when re-entering compilation
|
||||
([faf5b980](https://github.com/angular/angular.js/commit/faf5b980da09da2b4c28f1feab33f87269f9f0ba),
|
||||
[#4434](https://github.com/angular/angular.js/issues/4434), [#4616](https://github.com/angular/angular.js/issues/4616))
|
||||
- **$injector:** allow a constructor function to return a function
|
||||
([c22adbf1](https://github.com/angular/angular.js/commit/c22adbf160f32c1839fbb35382b7a8c6bcec2927))
|
||||
- **$parse:** check function call context to be safe
|
||||
([6d324c76](https://github.com/angular/angular.js/commit/6d324c76f0d3ad7dae69ce01b14e0564938fb15e),
|
||||
[#4417](https://github.com/angular/angular.js/issues/4417))
|
||||
- **angular-mocks:** add inline dependency annotation
|
||||
([6d23591c](https://github.com/angular/angular.js/commit/6d23591c31f2b41097ceaa380af09998e4a62f09),
|
||||
[#4448](https://github.com/angular/angular.js/issues/4448))
|
||||
- **animateSpec:** run digest to enable animations before tests
|
||||
([aea76f0d](https://github.com/angular/angular.js/commit/aea76f0d5c43dc17f1319d0a45d2ce50fddf72e4))
|
||||
- **bootstrap-prettify:** share $animate and $$postDigestQueue with demo apps
|
||||
([1df3da36](https://github.com/angular/angular.js/commit/1df3da361d62726bf1dafe629a7fca845b6a8733))
|
||||
- **csp:**
|
||||
- fix csp auto-detection and stylesheet injection
|
||||
([08f376f2](https://github.com/angular/angular.js/commit/08f376f2ea3d3bb384f10e3c01f7d48ed21ce351),
|
||||
[#917](https://github.com/angular/angular.js/issues/917), [#2963](https://github.com/angular/angular.js/issues/2963), [#4394](https://github.com/angular/angular.js/issues/4394), [#4444](https://github.com/angular/angular.js/issues/4444))
|
||||
- don't inline css in csp mode
|
||||
([a86cf20e](https://github.com/angular/angular.js/commit/a86cf20e67202d614bbcaf038c5e04db94483256)
|
||||
- **docModuleComponents:** implement anchor scroll when content added
|
||||
([eb51b024](https://github.com/angular/angular.js/commit/eb51b024c9b77527420014cdf7dbb292b5b9dd6b),
|
||||
[#4703](https://github.com/angular/angular.js/issues/4703))
|
||||
- **input:** keep track of min/max attars on-the-fly
|
||||
([4b653aea](https://github.com/angular/angular.js/commit/4b653aeac1aca7ac551738870a2446b6810ca0df))
|
||||
- **ngAnimate:** fix cancelChildAnimations throwing exception
|
||||
([b9557b0a](https://github.com/angular/angular.js/commit/b9557b0a86206d938a738ea470736d011dff7e1a),
|
||||
[#4548](https://github.com/angular/angular.js/issues/4548))
|
||||
- **ngClassSpec:** clear animation enable fn from postDigestQueue
|
||||
([ffa9d0a6](https://github.com/angular/angular.js/commit/ffa9d0a6db137cba4090e569b8ed4e25a711314e))
|
||||
- **ngEventDirectives:** parse expression only once during compile phase.
|
||||
([9a828738](https://github.com/angular/angular.js/commit/9a828738cd2e959bc2a198989e96c8e416d28b71))
|
||||
- **ngIf:**
|
||||
- destroy child scope when destroying DOM
|
||||
([9483373c](https://github.com/angular/angular.js/commit/9483373c331343648e079420b3eb1f564d410ff2))
|
||||
- ngIf removes elements dynamically added to it
|
||||
([e19067c9](https://github.com/angular/angular.js/commit/e19067c9bbac3c3bb450c80f73eb5518bd0db1a1))
|
||||
- **ngInclude:** only run anchorScroll after animation is done
|
||||
([d378f550](https://github.com/angular/angular.js/commit/d378f5500ab2eef0779338336c6a95656505ebb8),
|
||||
[#4723](https://github.com/angular/angular.js/issues/4723))
|
||||
- **ngMock:** throw more descriptive errors for $animate.flushNext()
|
||||
([6fb19157](https://github.com/angular/angular.js/commit/6fb191570ee72f087e8bb6b1d8f5eea0f585886c))
|
||||
- **ngModel:** deregister from the form on scope not DOM destruction
|
||||
([8f989d65](https://github.com/angular/angular.js/commit/8f989d652f70fd147f66a18411070c7b939e242e),
|
||||
[#4226](https://github.com/angular/angular.js/issues/4226), [#4779](https://github.com/angular/angular.js/issues/4779))
|
||||
- **ngScenario:** correctly disable animations for end 2 end tests
|
||||
([9d004585](https://github.com/angular/angular.js/commit/9d0045856351e9db48ddf66f66e210d9cc53d24a))
|
||||
- **ngView:**
|
||||
- only run anchorScroll after animation is done
|
||||
([da344daa](https://github.com/angular/angular.js/commit/da344daa4023556f8abbef6d8ad87a16362b5861))
|
||||
- ensure the new view element is placed after the old view element
|
||||
([3f568b22](https://github.com/angular/angular.js/commit/3f568b22f9bec09192588e3cae937db5c2e757f9),
|
||||
[#4362](https://github.com/angular/angular.js/issues/4362))
|
||||
- **ngdocs:**
|
||||
- create mock Doc objects correctly
|
||||
([d4493fda](https://github.com/angular/angular.js/commit/d4493fda2c4c2ff1fdfc264bfb479741abc781c7))
|
||||
- `shortDescription()` should not error if no `description`
|
||||
([4c8fa353](https://github.com/angular/angular.js/commit/4c8fa353245b9c32261860caff18f002d294e19f))
|
||||
- remove the side search bar
|
||||
([6c20ec19](https://github.com/angular/angular.js/commit/6c20ec193f11aa647be1b2ad2ac5b3e7c2894bd7))
|
||||
|
||||
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
- **$compile:**
|
||||
- due to [d0efd5ee](https://github.com/angular/angular.js/commit/d0efd5eefcc0aaf167c766513e152b74dd31bafe),
|
||||
Child elements that are defined either in the application template or in some other
|
||||
directives template do not get the isolate scope. In theory, nobody should rely on this behavior, as
|
||||
it is very rare - in most cases the isolate directive has a template.
|
||||
|
||||
- due to [909cabd3](https://github.com/angular/angular.js/commit/909cabd36d779598763cc358979ecd85bb40d4d7),
|
||||
Directives without isolate scope do not get the isolate scope from an isolate directive on the
|
||||
same element. If your code depends on this behavior (non-isolate directive needs to access state
|
||||
from within the isolate scope), change the isolate directive to use scope locals to pass these explicitly.
|
||||
|
||||
**Before**
|
||||
|
||||
```
|
||||
<input ng-model="$parent.value" ng-isolate>
|
||||
|
||||
.directive('ngIsolate', function() {
|
||||
return {
|
||||
scope: {},
|
||||
template: '{{value}}'
|
||||
};
|
||||
});
|
||||
```
|
||||
|
||||
**After**
|
||||
|
||||
```
|
||||
<input ng-model="value" ng-isolate>
|
||||
|
||||
.directive('ngIsolate', function() {
|
||||
return {
|
||||
scope: {value: '=ngModel'},
|
||||
template: '{{value}}
|
||||
};
|
||||
});
|
||||
```
|
||||
|
||||
Closes [#1924](https://github.com/angular/angular.js/issues/1924) and
|
||||
[#2500](https://github.com/angular/angular.js/issues/2500)
|
||||
|
||||
- due to [79223eae](https://github.com/angular/angular.js/commit/79223eae5022838893342c42dacad5eca83fabe8),
|
||||
|
||||
Previously, the interpolation priority was `-100` in 1.2.0-rc.2, and `100` before 1.2.0-rc.2.
|
||||
Before this change the binding was setup in the post-linking phase.
|
||||
|
||||
Now the attribute interpolation (binding) executes as a directive with priority 100 and the
|
||||
binding is set up in the pre-linking phase.
|
||||
|
||||
Closes [#4525](https://github.com/angular/angular.js/issues/4525),
|
||||
[#4528](https://github.com/angular/angular.js/issues/4528), and
|
||||
[#4649](https://github.com/angular/angular.js/issues/4649)
|
||||
|
||||
|
||||
- **$parse:** due to [3d6a89e8](https://github.com/angular/angular.js/commit/3d6a89e8888b14ae5cb5640464e12b7811853c7e),
|
||||
|
||||
This commit introduces the notion of "private" properties (properties
|
||||
whose names begin and/or end with an underscore) on the scope chain.
|
||||
These properties will not be available to Angular expressions (i.e. {{
|
||||
}} interpolation in templates and strings passed to `$parse`) They are
|
||||
freely available to JavaScript code (as before).
|
||||
|
||||
**Motivation**
|
||||
|
||||
Angular expressions execute in a limited context. They do not have
|
||||
direct access to the global scope, `window`, `document` or the Function
|
||||
constructor. However, they have direct access to names/properties on
|
||||
the scope chain. It has been a long standing best practice to keep
|
||||
sensitive APIs outside of the scope chain (in a closure or your
|
||||
controller.) That's easier said that done for two reasons:
|
||||
|
||||
1. JavaScript does not have a notion of private properties so if you need
|
||||
someone on the scope chain for JavaScript use, you also expose it to
|
||||
Angular expressions
|
||||
2. the new "controller as" syntax that's now in increased usage exposes the
|
||||
entire controller on the scope chain greatly increaing the exposed surface.
|
||||
|
||||
Though Angular expressions are written and controlled by the developer, they:
|
||||
|
||||
1. Typically deal with user input
|
||||
2. Don't get the kind of test coverage that JavaScript code would
|
||||
|
||||
This commit provides a way, via a naming convention, to
|
||||
allow publishing/restricting properties from controllers/scopes to
|
||||
Angular expressions enabling one to only expose those properties that
|
||||
are actually needed by the expressions.
|
||||
|
||||
- **csp:** due to [08f376f2](https://github.com/angular/angular.js/commit/08f376f2ea3d3bb384f10e3c01f7d48ed21ce351),
|
||||
triggering ngCsp directive via `ng:csp` attribute is not supported any more.
|
||||
Please use `data-ng-csp` instead.
|
||||
|
||||
- **jqLite:** due to [27e9340b](https://github.com/angular/angular.js/commit/27e9340b3c25b512e45213b39811098d07e12e3b),
|
||||
`jqLite.scope()` (connonly used through `angular.element(node).scope()`) does not return the
|
||||
isolate scope on the element that triggered directive with isolate scope. Use
|
||||
`jqLite.isolateScope()` instead.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="1.2.0-rc.3"></a>
|
||||
# 1.2.0-rc.3 ferocious-twitch (2013-10-14)
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- **$interval:** add a service wrapping setInterval
|
||||
([2b5ce84f](https://github.com/angular/angular.js/commit/2b5ce84fca7b41fca24707e163ec6af84bc12e83))
|
||||
- **$sce:** simpler patterns for `$sceDelegateProviders` white/blacklists
|
||||
([93ce5923](https://github.com/angular/angular.js/commit/93ce5923e92f6d2db831d8715ec62734821c70ce),
|
||||
[#4006](https://github.com/angular/angular.js/issues/4006))
|
||||
- **$filter:** allow map of filters to be registered
|
||||
([4033cf28](https://github.com/angular/angular.js/commit/4033cf28142664c52aa7b4bc95340ac913397ac8),
|
||||
[#4036](https://github.com/angular/angular.js/issues/4036),
|
||||
[#4091](https://github.com/angular/angular.js/issues/4091))
|
||||
- **$compile:** support `tel:` links in `a[href]`
|
||||
([e7730297](https://github.com/angular/angular.js/commit/e773029717f11d727af609a139b173a135c79eab))
|
||||
|
||||
- **Directives:**
|
||||
- **ngRepeat:** support repeating over `ngInclude` and other directives that replace repeated nodes
|
||||
([9efa46ae](https://github.com/angular/angular.js/commit/9efa46ae640cde17487c341daa9a75c0bd79da02),
|
||||
[#3104](https://github.com/angular/angular.js/issues/3104))
|
||||
- **event directives:** add `ngCopy`, `ngCut`, and `ngPaste`
|
||||
([147c6929](https://github.com/angular/angular.js/commit/147c6929a264a7b077a5f2cfc5aa9a0b9513acd7),
|
||||
[#4172](https://github.com/angular/angular.js/issues/4172))
|
||||
|
||||
- **Misc:**
|
||||
- jQuery 1.10.x support
|
||||
([e0c134b8](https://github.com/angular/angular.js/commit/e0c134b8bfa282379daec6a7137512d58f956443),
|
||||
[#3764](https://github.com/angular/angular.js/issues/3764))
|
||||
- **minErr:** linkify error messages on minErr docs pages
|
||||
([6aaae062](https://github.com/angular/angular.js/commit/6aaae062171bfc8e5046c3eae99bc9d63037120a))
|
||||
- **tutorial:** add step 12 on animations to the phonecat tutorial
|
||||
([ad525645](https://github.com/angular/angular.js/commit/ad5256452bb8f1d481d78e7ae15a59d288f0d8e9))
|
||||
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$compile:**
|
||||
- abort compilation when duplicate element transclusion
|
||||
([63c5334c](https://github.com/angular/angular.js/commit/63c5334c84b7269428c710226764d1f08a36e0d4),
|
||||
[#3893](https://github.com/angular/angular.js/issues/3893),
|
||||
[#4217](https://github.com/angular/angular.js/issues/4217),
|
||||
[#3307](https://github.com/angular/angular.js/issues/3307))
|
||||
- make order directives w/ same priority deterministic
|
||||
([4357da85](https://github.com/angular/angular.js/commit/4357da857587d3c28790e7dc654664bec5808768))
|
||||
- fix (reverse) directive postLink fn execution order
|
||||
([31f190d4](https://github.com/angular/angular.js/commit/31f190d4d53921d32253ba80d9ebe57d6c1de82b),
|
||||
[#3558](https://github.com/angular/angular.js/issues/3558))
|
||||
- don't terminate compilation for regular transclusion directives
|
||||
([fe214501](https://github.com/angular/angular.js/commit/fe2145016cb057c92f9f01b32c58b4d7259eb6ee))
|
||||
- ng-attr to support dash separated attribute names
|
||||
([8e6e3eba](https://github.com/angular/angular.js/commit/8e6e3ebad991eaf57a7885549ea3b91932d495c9))
|
||||
- allow interpolations for non-event handlers attrs
|
||||
([8e1276c0](https://github.com/angular/angular.js/commit/8e1276c011b33b90af47494dc5e76baf86468a5a))
|
||||
- link parents before traversing
|
||||
([742271ff](https://github.com/angular/angular.js/commit/742271ffa3a518d9e8ef2cb97c24b45b44e3378d),
|
||||
[#3792](https://github.com/angular/angular.js/issues/3792),
|
||||
[#3923](https://github.com/angular/angular.js/issues/3923),
|
||||
[#3935](https://github.com/angular/angular.js/issues/3935),
|
||||
[#3927](https://github.com/angular/angular.js/issues/3927))
|
||||
- collect ranges on multiple directives on one element
|
||||
([6a8edc1d](https://github.com/angular/angular.js/commit/6a8edc1d43aca7c5a92f86309b1bb1d5f9968442),
|
||||
[#4002](https://github.com/angular/angular.js/issues/4002))
|
||||
- **$parse:**
|
||||
- deprecate promise unwrapping and make it an opt-in
|
||||
([5dc35b52](https://github.com/angular/angular.js/commit/5dc35b527b3c99f6544b8cb52e93c6510d3ac577),
|
||||
[#4158](https://github.com/angular/angular.js/issues/4158),
|
||||
[#4270](https://github.com/angular/angular.js/issues/4270))
|
||||
- disallow access to window and dom in expressions
|
||||
([be0b4856](https://github.com/angular/angular.js/commit/be0b4856699334ff51bacf2d1fd3394663d6bd28))
|
||||
- **$httpBackend:**
|
||||
- set headers with falsy values
|
||||
([e9a22241](https://github.com/angular/angular.js/commit/e9a222418a029d830698444cf95bf13f8ad75805),
|
||||
[#2984](https://github.com/angular/angular.js/issues/2984))
|
||||
- don't send empty string bodies
|
||||
([0d0330ad](https://github.com/angular/angular.js/commit/0d0330adc24a68cd6891a030a56d3ce3bbced03c),
|
||||
[#2149](https://github.com/angular/angular.js/issues/2149))
|
||||
- **$location:**
|
||||
- prevent infinite digest error in IE7
|
||||
([d7071148](https://github.com/angular/angular.js/commit/d70711481e6311c9cd283d650f07ca0cca72ecc2),
|
||||
[#2802](https://github.com/angular/angular.js/issues/2802))
|
||||
- re-assign location after BFCache back
|
||||
([2ebf9316](https://github.com/angular/angular.js/commit/2ebf93163027abc55ba27f673be3b8dc1281c068),
|
||||
[#4044](https://github.com/angular/angular.js/issues/4044))
|
||||
- **$log:** prevent logging `undefined` for $log in IE
|
||||
([4ff1a650](https://github.com/angular/angular.js/commit/4ff1a65031e985bf930f6761c1ecf46e4db98d6e),
|
||||
[#1705](https://github.com/angular/angular.js/issues/1705))
|
||||
- **Scope:**
|
||||
- `$evalAsync` executes on the right scope
|
||||
([10cc1a42](https://github.com/angular/angular.js/commit/10cc1a42c925749f88433546d41d35ba07a88e6f))
|
||||
- make `stopPropagation` only stop its own event
|
||||
([47f7bd70](https://github.com/angular/angular.js/commit/47f7bd706efc5f2944d182e46c1b1d324298ff36),
|
||||
[#4204](https://github.com/angular/angular.js/issues/4204))
|
||||
|
||||
- **Filters:**
|
||||
- **date:** allow negative millisecond value strings
|
||||
([025c9219](https://github.com/angular/angular.js/commit/025c92190376414c15f15fd20a75b41489a4e70a))
|
||||
|
||||
- **Directives:**
|
||||
- correct priority of structural directives (ngRepeat, ngSwitchWhen, ngIf, ngInclude, ngView)
|
||||
([b7af76b4](https://github.com/angular/angular.js/commit/b7af76b4c5aa77648cc1bfd49935b48583419023))
|
||||
- **input:** `false` is no longer an empty value by default
|
||||
([b56b21a8](https://github.com/angular/angular.js/commit/b56b21a898b3c77589a48a290271f9dc181dafe8),
|
||||
[#3490](https://github.com/angular/angular.js/issues/3490))
|
||||
- **ngBindHtml:** watch string value instead of wrapper
|
||||
([e2068ad4](https://github.com/angular/angular.js/commit/e2068ad426075ac34c06c12e2fac5f594cc81969),
|
||||
[#3932](https://github.com/angular/angular.js/issues/3932))
|
||||
- **ngOptions:** ignore object properties which start with $
|
||||
([aa3c54c7](https://github.com/angular/angular.js/commit/aa3c54c73f7470999535294899a1c33cd193f455))
|
||||
- **ngRepeat:** correctly track elements even when the collection is initially undefined
|
||||
([31c56f54](https://github.com/angular/angular.js/commit/31c56f540045b5270f5b8e235873da855caf3486),
|
||||
[#4145](https://github.com/angular/angular.js/issues/4145),
|
||||
[#3964](https://github.com/angular/angular.js/issues/3964))
|
||||
- **ngTransclude:** detect ngTranslude usage without a transclusion directive
|
||||
([5a1a6b86](https://github.com/angular/angular.js/commit/5a1a6b86a8dbcd8aa4fe9c59fad8d005eead686c),
|
||||
[#3759](https://github.com/angular/angular.js/issues/3759))
|
||||
|
||||
|
||||
- **jqLite:**
|
||||
- ignore class methods on comment elements
|
||||
([64fd2c42](https://github.com/angular/angular.js/commit/64fd2c421ed582c16812d164a8a6f031b8e66287))
|
||||
- use get/setAttribute so that jqLite works on SVG nodes
|
||||
([c785267e](https://github.com/angular/angular.js/commit/c785267eb8780d8b7658ef93ebb5ebddd566294d),
|
||||
[#3858](https://github.com/angular/angular.js/issues/3858))
|
||||
|
||||
- **Misc:**
|
||||
- **isArrayLike:** correctly handle string primitives
|
||||
([5b8c7884](https://github.com/angular/angular.js/commit/5b8c78843e8d62a7a67cead8bf04c76aa8ee411d),
|
||||
[#3356](https://github.com/angular/angular.js/issues/3356))
|
||||
- protect calls to hasOwnProperty in public API
|
||||
([7a586e5c](https://github.com/angular/angular.js/commit/7a586e5c19f3d1ecc3fefef084ce992072ee7f60),
|
||||
[#3331](https://github.com/angular/angular.js/issues/3331))
|
||||
|
||||
- **ngRoute:**
|
||||
- **ngView:** IE8 regression due to expando on non-element nodes
|
||||
([255e8c13](https://github.com/angular/angular.js/commit/255e8c13cf0fd78f1c4d7c279be7bf47c2402956),
|
||||
[#3971](https://github.com/angular/angular.js/issues/3971))
|
||||
- **$route:** parametrized routes do not match against locations that would not valorize each parameters.
|
||||
([0ff86c32](https://github.com/angular/angular.js/commit/0ff86c323359fba1a60bacab178e3c68528f8e1f))
|
||||
|
||||
- **ngResource:**
|
||||
- pass transformed value to both callbacks and promises
|
||||
([e36e28eb](https://github.com/angular/angular.js/commit/e36e28ebd4a6c144e47d11fba8e211d8d5a9d03e),
|
||||
[#3817](https://github.com/angular/angular.js/issues/3817))
|
||||
- remove request body from $delete
|
||||
([8336b3a2](https://github.com/angular/angular.js/commit/8336b3a286f8469d4cd7c412c41ca8c1a31fecf0),
|
||||
[#4280](https://github.com/angular/angular.js/issues/4280))
|
||||
|
||||
- **ngSanitize:**
|
||||
- sanitize DOCTYPE declarations correctly
|
||||
([e66c23fe](https://github.com/angular/angular.js/commit/e66c23fe55f8571a014b0686c8dbca128e7a8240),
|
||||
[#3931](https://github.com/angular/angular.js/issues/3931))
|
||||
- sanitizer should not accept <!--> as a valid comment
|
||||
([21e9e8cf](https://github.com/angular/angular.js/commit/21e9e8cf68ef007136da6cc212d2f1f252fb668a))
|
||||
|
||||
- **ngTouch:**
|
||||
- ngClick does not pass touchend event when jQuery is loaded
|
||||
([9fd92cc3](https://github.com/angular/angular.js/commit/9fd92cc3c93a6378e8887fd46fd4ad182a375544))
|
||||
- add $event to ng-swipe
|
||||
([507d8021](https://github.com/angular/angular.js/commit/507d8021b1c91cc0cefc0418e61b04597ad1030b),
|
||||
[#4071](https://github.com/angular/angular.js/issues/4071),
|
||||
[#4321](https://github.com/angular/angular.js/issues/4321))
|
||||
|
||||
- **ngAnimate:**
|
||||
- ensure that a timeStamp is created if not provided by the browser event
|
||||
([cd216c4c](https://github.com/angular/angular.js/commit/cd216c4c30adfebb3ef633f18fab2d98e8c52ebc),
|
||||
[#3053](https://github.com/angular/angular.js/issues/3053))
|
||||
- perform internal caching on getComputedStyle to boost the performance of CSS3 transitions/animations
|
||||
([b1e604e3](https://github.com/angular/angular.js/commit/b1e604e38ceec1714174fb54cc91590a7fe99a92),
|
||||
[#4011](https://github.com/angular/angular.js/issues/4011),
|
||||
[#4124](https://github.com/angular/angular.js/issues/4124))
|
||||
- ensure structural animations skip all child animations even if no animation is present during compile
|
||||
([cc584607](https://github.com/angular/angular.js/commit/cc5846073e57ef190182026d7e5a8e2770d9b770),
|
||||
[#3215](https://github.com/angular/angular.js/issues/3215))
|
||||
- cancel any ongoing child animations during move and leave animations
|
||||
([3f31a7c7](https://github.com/angular/angular.js/commit/3f31a7c7691993893f0724076816f6558643bd91))
|
||||
- ensure elapsedTime always considers delay values
|
||||
([079dd939](https://github.com/angular/angular.js/commit/079dd93991ac79b5f9af6efb7fe2b3600195f10c))
|
||||
- ensure transition-property is not changed when only keyframe animations are in use
|
||||
([2df3c9f5](https://github.com/angular/angular.js/commit/2df3c9f58def9584455f7c4bfdabbd12aab58bf9),
|
||||
[#3933](https://github.com/angular/angular.js/issues/3933))
|
||||
- avoid completing the animation asynchronously unless CSS transtiions/animations are present
|
||||
([2a63dfa6](https://github.com/angular/angular.js/commit/2a63dfa6cc7889888f4296fff2944e74ff30b3af),
|
||||
[#4023](https://github.com/angular/angular.js/issues/4023),
|
||||
[#3940](https://github.com/angular/angular.js/issues/3940))
|
||||
- ensure that delays are always considered before an animation closes
|
||||
([0a63adce](https://github.com/angular/angular.js/commit/0a63adce687d28ada90ea930d5e69883cc11cba5),
|
||||
[#4028](https://github.com/angular/angular.js/issues/4028))
|
||||
- check elapsedTime on current event
|
||||
([d50ed6bf](https://github.com/angular/angular.js/commit/d50ed6bfb8c4982401923ff535fe932ef4f387a2))
|
||||
- support addClass/removeClass animations on SVG nodes
|
||||
([c785267e](https://github.com/angular/angular.js/commit/c785267eb8780d8b7658ef93ebb5ebddd566294d),
|
||||
[#3858](https://github.com/angular/angular.js/issues/3858))
|
||||
|
||||
- **ngScenario:**
|
||||
- remove redundant assignment
|
||||
([a80e96ce](https://github.com/angular/angular.js/commit/a80e96cea184b392505f0a292785a5c66d45e165),
|
||||
[#4315](https://github.com/angular/angular.js/issues/4315))
|
||||
- fix error message description
|
||||
([f8f8f754](https://github.com/angular/angular.js/commit/f8f8f754b02459bb789247476cc0da63d2d7370f))
|
||||
- provide event parameters as object
|
||||
([28f56a38](https://github.com/angular/angular.js/commit/28f56a383e9d1ff378e3568a3039e941c7ffb1d8))
|
||||
- include "not " in error messages if test is inverted
|
||||
([3589f178](https://github.com/angular/angular.js/commit/3589f17824376e9db4e8d002caeb4483943eeb18),
|
||||
[#3840](https://github.com/angular/angular.js/issues/3840))
|
||||
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
- **$compile:** due to [31f190d4](https://github.com/angular/angular.js/commit/31f190d4d53921d32253ba80d9ebe57d6c1de82b),
|
||||
the order of postLink fn is now mirror opposite of the order in which corresponding preLinking and compile functions execute.
|
||||
|
||||
Previously the compile/link fns executed in this order controlled via priority:
|
||||
|
||||
- CompilePriorityHigh, CompilePriorityMedium, CompilePriorityLow
|
||||
- compile child nodes
|
||||
- PreLinkPriorityHigh, PreLinkPriorityMedium, PreLinkPriorityLow
|
||||
- link child nodes
|
||||
- PostLinkPriorityHigh, PostLinkPriorityMedium, PostLinkPriorityLow
|
||||
|
||||
This was changed to:
|
||||
|
||||
- CompilePriorityHigh, CompilePriorityMedium, CompilePriorityLow
|
||||
- compile child nodes
|
||||
- PreLinkPriorityHigh, PreLinkPriorityMedium, PreLinkPriorityLow
|
||||
- link child nodes
|
||||
- PostLinkPriorityLow, PostLinkPriorityMedium , PostLinkPriorityHigh
|
||||
|
||||
Very few directives in practice rely on order of postLinking function (unlike on the order of compile functions), so
|
||||
in the rare case of this change affecting an existing directive, it might be necessary to convert it to a preLinking
|
||||
function or give it negative priority (look at the diff of this commit to see how an internal attribute interpolation
|
||||
directive was adjusted).
|
||||
|
||||
- **$parse:**
|
||||
- due to [5dc35b52](https://github.com/angular/angular.js/commit/5dc35b527b3c99f6544b8cb52e93c6510d3ac577),
|
||||
$parse and templates in general will no longer automatically unwrap promises. This feature has been deprecated and if absolutely needed, it can be reenabled during transitional period via `$parseProvider.unwrapPromises(true)` api.
|
||||
- due to [b6a37d11](https://github.com/angular/angular.js/commit/b6a37d112b3e1478f4d14a5f82faabf700443748),
|
||||
feature added in rc.2 that unwraps return values from functions if the values are promises (if promise unwrapping is enabled - see previous point), was reverted due to breaking a popular usage pattern.
|
||||
|
||||
- **directives:** due to [b7af76b4](https://github.com/angular/angular.js/commit/b7af76b4c5aa77648cc1bfd49935b48583419023),
|
||||
the priority of ngRepeat, ngSwitchWhen, ngIf, ngInclude and ngView has changed. This could affect directives that explicitly specify their priority.
|
||||
|
||||
In order to make ngRepeat, ngSwitchWhen, ngIf, ngInclude and ngView work together in all common scenarios their directives are being adjusted to achieve the following precendence:
|
||||
|
||||
```
|
||||
Directive | Old Priority | New Priority
|
||||
=============================================
|
||||
ngRepeat | 1000 | 1000
|
||||
---------------------------------------------
|
||||
ngSwitchWhen | 500 | 800
|
||||
---------------------------------------------
|
||||
ngIf | 1000 | 600
|
||||
---------------------------------------------
|
||||
ngInclude/ngView | 1000 | 400
|
||||
```
|
||||
|
||||
- **form/ngForm** due to [7a586e5c](https://github.com/angular/angular.js/commit/7a586e5c19f3d1ecc3fefef084ce992072ee7f60),
|
||||
Inputs with name equal to "hasOwnProperty" are not allowed inside form or ngForm directives.
|
||||
|
||||
Before, inputs whose name was "hasOwnProperty" were quietly ignored and not added to the scope. Now a badname exception is thrown.
|
||||
|
||||
Using "hasOwnProperty" for an input name would be very unusual and bad practice.
|
||||
|
||||
Either do not include such an input in a `form` or `ngForm` directive or change the name of the input.
|
||||
|
||||
|
||||
- **ngScenario:** due to [28f56a38](https://github.com/angular/angular.js/commit/28f56a383e9d1ff378e3568a3039e941c7ffb1d8),
|
||||
browserTrigger now uses an eventData object instead of direct parameters for mouse events.
|
||||
To migrate, place the `keys`,`x` and `y` parameters inside of an object and place that as the third parameter for the browserTrigger function.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="1.2.0-rc.2"></a>
|
||||
# 1.2.0-rc.2 barehand-atomsplitting (2013-09-04)
|
||||
|
||||
## Features
|
||||
|
||||
- **Scope:** asynchronously auto-flush `$evalAsync` queue when outside of `$digest` cycle
|
||||
([6b91aa0a](https://github.com/angular/angular.js/commit/6b91aa0a18098100e5f50ea911ee135b50680d67),
|
||||
[#3539](https://github.com/angular/angular.js/issues/3539), [#2438](https://github.com/angular/angular.js/issues/2438))
|
||||
- **minErr:** log minerr doc url in development builds
|
||||
([37123cd2](https://github.com/angular/angular.js/commit/37123cd2858b4e318ed8109af745312df4848577),
|
||||
[#3566](https://github.com/angular/angular.js/issues/3566))
|
||||
- **ngMock:**
|
||||
- allow passing an object literal as shorthand to module
|
||||
([f737c97d](https://github.com/angular/angular.js/commit/f737c97df02918eb5b19bf5c8248fa3e20f9b361))
|
||||
- add support for creating dynamic style sheets within test code
|
||||
([fb3a7db0](https://github.com/angular/angular.js/commit/fb3a7db0809b959d50be4cb93a65a91200071dd5))
|
||||
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$http:** allow empty responses to be cached
|
||||
([8e48c4ff](https://github.com/angular/angular.js/commit/8e48c4ff6abf7083a04cf20312d2b106f4ba5b2c),
|
||||
[#3809](https://github.com/angular/angular.js/issues/3809))
|
||||
- **$injector:** don't parse fns with no args
|
||||
([44b6b72e](https://github.com/angular/angular.js/commit/44b6b72e5e9d193ec878ac7a4f25a00815f68cca))
|
||||
- **$parse:** handle promises returned from parsed function calls
|
||||
([3a658220](https://github.com/angular/angular.js/commit/3a65822023119b71deab5e298c7ef2de204caa13),
|
||||
[#3503](https://github.com/angular/angular.js/issues/3503))
|
||||
- **$q:**
|
||||
- reject should catch & forward exceptions thrown in error callbacks
|
||||
([5d9f4205](https://github.com/angular/angular.js/commit/5d9f42050a11015adbd5dc4dde73818919e93a99))
|
||||
- fix forwarding resolution when callbacks aren't functions
|
||||
([7d188d63](https://github.com/angular/angular.js/commit/7d188d630c63fde05d8765d0ad2d75a5baa8e5d3),
|
||||
[#3535](https://github.com/angular/angular.js/issues/3535))
|
||||
- **$location:** fix history problems on Boxee box
|
||||
([eefcdad0](https://github.com/angular/angular.js/commit/eefcdad013b56d5d3a05c0b2137a5860091b2575))
|
||||
- **$timeout:** clean deferreds immediately after callback exec/cancel
|
||||
([920a3804](https://github.com/angular/angular.js/commit/920a3804136d49cdaf7bc2712f5832bc50409dc9))
|
||||
|
||||
- **Directives:**
|
||||
- **ngTransclude:**
|
||||
- clear the translusion point before transcluding
|
||||
([eed299a3](https://github.com/angular/angular.js/commit/eed299a31b5a6dd0363133c5f9271bf33d090c94))
|
||||
- make the transclusion available to parent post-link function
|
||||
([bf79bd41](https://github.com/angular/angular.js/commit/bf79bd4194eca2118ae1c492c08dbd217f5ae810))
|
||||
- **ngView:** ensure `ngClass` works with together with `ngView`'s transclusion behavior
|
||||
([40c0220c](https://github.com/angular/angular.js/commit/40c0220c47c620070b30aec6ec4552c68a8689eb))
|
||||
|
||||
- **Filters:**
|
||||
- **filter:** filter on false properties
|
||||
([3bc4e7fd](https://github.com/angular/angular.js/commit/3bc4e7fd20372c0cad8298bff019b32681b16026),
|
||||
[#2797](https://github.com/angular/angular.js/issues/2797))
|
||||
- **orderBy:** remove redundant if statement
|
||||
([5e45fd4a](https://github.com/angular/angular.js/commit/5e45fd4ac6ff7c00d34deb099fca12301cafd7b0))
|
||||
|
||||
- **Misc:**
|
||||
- parse IE11 UA string correctly
|
||||
([427ee93f](https://github.com/angular/angular.js/commit/427ee93f11d0ef64b8844f9b43b2a0f21f2be2cb),
|
||||
[#3682](https://github.com/angular/angular.js/issues/3682))
|
||||
|
||||
- **i18n:** remove obsolete locale files
|
||||
([6382e21f](https://github.com/angular/angular.js/commit/6382e21fb28541a2484ac1a241d41cf9fbbe9d2c))
|
||||
|
||||
- **ngAnimate:**
|
||||
- ensure that `ngClass` is always compiled before enter, leave and move animations are applied
|
||||
([36ad40b1](https://github.com/angular/angular.js/commit/36ad40b18cfdd0690411a5169aa94e222946b5cf),
|
||||
[#3727](https://github.com/angular/angular.js/issues/3727), [#3603](https://github.com/angular/angular.js/issues/3603))
|
||||
- cut down on extra `$timeout` calls
|
||||
([4382df03](https://github.com/angular/angular.js/commit/4382df03fa1962aed027742c1b463406c40653c9))
|
||||
- skip `ngAnimate` animations if the provided element already has transitions applied to it
|
||||
([7c605ddf](https://github.com/angular/angular.js/commit/7c605ddf1c57c9f162827713ca5b0fbb12de5fa5),
|
||||
[#3587](https://github.com/angular/angular.js/issues/3587))
|
||||
- only apply a timeout when transitions or keyframe animations are used
|
||||
([ee2f3d21](https://github.com/angular/angular.js/commit/ee2f3d21da6c9fccfe1e6a4ea8a65627519c8bf2),
|
||||
[#3613](https://github.com/angular/angular.js/issues/3613))
|
||||
- ensure older versions of webkit work for animations
|
||||
([b1a43cd0](https://github.com/angular/angular.js/commit/b1a43cd04e8727df5bef3197f5fda3b98ecab740))
|
||||
|
||||
- **ngMocks:** `$logProvider` should not use internal APIs
|
||||
([baaa73ee](https://github.com/angular/angular.js/commit/baaa73ee1ef25fa506ff7aaab3159d710acdafdb),
|
||||
[#3612](https://github.com/angular/angular.js/issues/3612))
|
||||
|
||||
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
- **i18n:** due to [6382e21f](https://github.com/angular/angular.js/commit/6382e21fb28541a2484ac1a241d41cf9fbbe9d2c),
|
||||
some uncommon region-specific local files were removed.
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="1.0.8"></a>
|
||||
# 1.0.8 bubble-burst (2013-08-22)
|
||||
|
||||
@@ -752,7 +15,7 @@ Contains only these fixes cherry-picked from [v1.2.0rc1](#1.2.0rc1).
|
||||
- **$http:** ensure case-insensitive header overriding
|
||||
([25d9f5a8](https://github.com/angular/angular.js/commit/25d9f5a804b7a6a61db6e84e594b1b5fe7ea14bf))
|
||||
- **$location:**
|
||||
- default to / for the url base if no `base[href]`
|
||||
- default to / for the url base if no base[href]
|
||||
([cbe31d8d](https://github.com/angular/angular.js/commit/cbe31d8dfd12ce973c574bfc825ffc0ffb8eb7c4),
|
||||
[#2762](https://github.com/angular/angular.js/issues/2762))
|
||||
- prevent infinite digest error due to IE bug
|
||||
@@ -834,8 +97,8 @@ Contains only these fixes cherry-picked from [v1.2.0rc1](#1.2.0rc1).
|
||||
|
||||
|
||||
|
||||
<a name="1.2.0rc1"></a>
|
||||
# 1.2.0rc1 spooky-giraffe (2013-08-13)
|
||||
<a name="1.2.0-rc1"></a>
|
||||
# 1.2.0-rc1 spooky-giraffe (2013-08-13)
|
||||
|
||||
[Full Commit Log](https://github.com/angular/angular.js/compare/v1.1.5...master)
|
||||
|
||||
@@ -1203,12 +466,6 @@ Contains only these fixes cherry-picked from [v1.2.0rc1](#1.2.0rc1).
|
||||
JS: scope.foo = function() { alert(1); }
|
||||
HTML: <div ng-click="foo()">
|
||||
|
||||
- due to [e46100f7](https://github.com/angular/angular.js/commit/e46100f7097d9a8f174bdb9e15d4c6098395c3f2), existing directives
|
||||
with name ending with `"-start"` or `"-end"` will stop working.
|
||||
|
||||
This change was necessary to enable multi-element directives. The best fix is to rename existing directives, so that they
|
||||
don't end with these suffixes.
|
||||
|
||||
- **$q:** due to [f078762d](https://github.com/angular/angular.js/commit/f078762d48d0d5d9796dcdf2cb0241198677582c),
|
||||
the `always` method is now exposed as `finally`.
|
||||
|
||||
|
||||
+19
-203
@@ -1,216 +1,32 @@
|
||||
#Contributing to AngularJS
|
||||
## Submitting issues
|
||||
|
||||
We'd love for you to contribute to our source code and to make AngularJS even better than it is
|
||||
today! Here are the guidelines we'd like you to follow:
|
||||
If you have questions about how to use AngularJS, please direct these to the
|
||||
[Google Group][groups] discussion list or [StackOverflow][stackoverflow]. We are
|
||||
also available on [IRC][irc].
|
||||
|
||||
## Got a Question or Problem?
|
||||
|
||||
If you have questions about how to use AngularJS, please direct these to the [Google Group][groups]
|
||||
discussion list or [StackOverflow][stackoverflow]. We are also available on [IRC][irc].
|
||||
|
||||
## Found an Issue?
|
||||
If you find a bug in the source code or a mistake in the documentation, you can help us by
|
||||
submitting and issue to our [GitHub Repository][github]. Even better you can submit a Pull Request
|
||||
with a fix.
|
||||
|
||||
***Localization Issue:*** *Angular.js uses the [Google Closure I18N library], to generate its own I18N files. This means that
|
||||
any changes to these files would be lost the next time that we import the library. The recommended
|
||||
approach is to submit a patch to the I18N project directly, instead of submitting it here.*
|
||||
|
||||
**Please see the Submission Guidelines below**.
|
||||
|
||||
## Want a Feature?
|
||||
You can request a new feature by submitting an issue to our [GitHub Repository][github]. If you
|
||||
would like to implement a new feature then consider what kind of change it is:
|
||||
|
||||
* **Major Changes** that you wish to contribute to the project should be discussed first on our
|
||||
[dev mailing list][angular-dev] or [IRC][irc] so that we can better coordinate our efforts, prevent
|
||||
duplication of work, and help you to craft the change so that it is successfully accepted into the
|
||||
project.
|
||||
* **Small Changes** can be crafted and submitted to [GitHub Repository][github] as a Pull Request.
|
||||
|
||||
## Submission Guidelines
|
||||
|
||||
### Submitting an Issue
|
||||
Before you submit your issue follow the following guidelines:
|
||||
### Guidelines
|
||||
|
||||
* Search the archive first, it's likely that your question was already answered.
|
||||
* A live example demonstrating the issue, will get an answer faster.
|
||||
* Create one using [Plunker][plunker] or [JSFiddle][jsfiddle].
|
||||
* A live example demonstrating your problem or question, will get an answer faster.
|
||||
* Create one using this [template][template]
|
||||
* If you get help, help others. Good karma rulez!
|
||||
|
||||
If your issue appears to be a bug, and hasn't been reported, open a new issue.
|
||||
Help us to maximize the effort we can spend fixing issues and adding new
|
||||
features, by not reporting duplicate issues.
|
||||
|
||||
### Submitting a Pull Request
|
||||
Before you submit your pull request follow the following guidelines:
|
||||
|
||||
* Search GitHub for an open or closed Pull Request that relates to your submission. You don't want
|
||||
to duplicate effort.
|
||||
* Make your changes in a new git branch
|
||||
* Follow our Coding Rules
|
||||
* Follow our Git Commit Guidelines
|
||||
* Build your changes locally and on Travis (by pushing to GitHub) to ensure all the tests pass.
|
||||
* Sign the Contributor License Agreement (CLA). We cannot accept code without this.
|
||||
* If we suggest changes then you can modify your branch, rebase and force a new push to your GitHub
|
||||
repository to update the Pull Request.
|
||||
|
||||
## Coding Rules
|
||||
To ensure consistency throughout the source code, keep these rules in mind as you are working:
|
||||
|
||||
* All features or bug fixes **must be tested** by one or more [specs][unit-testing].
|
||||
* All public API methods **must be documented** with ngdoc, an extended version of jsdoc (we added
|
||||
support for markdown and templating via @ngdoc tag). To see how we document our APIs, please check
|
||||
out the existing ngdocs and see [this wiki page][ngDocs].
|
||||
* With the exceptions listed below, we follow the rules contained in
|
||||
[Google's JavaScript Style Guide][js-style-guide]:
|
||||
* **Do not use namespaces**: Instead, wrap the entire angular code base in an anonymous closure and
|
||||
export our API explicitly rather than implicitly.
|
||||
* Wrap all code at **100 characters**.
|
||||
* Instead of complex inheritance hierarchies, we **prefer simple objects**. We use prototypical
|
||||
inheritance only when absolutely necessary.
|
||||
* We **love functions and closures** and, whenever possible, prefer them over objects.
|
||||
* To write concise code that can be better minified, we **use aliases internally** that map to the
|
||||
external API. See our existing code to see what we mean.
|
||||
* We **don't go crazy with type annotations** for private internal APIs unless it's an internal API
|
||||
that is used throughout AngularJS. The best guidance is to do what makes the most sense.
|
||||
|
||||
## Git Commit Guidelines
|
||||
|
||||
We have very precise rules over how our git commit messages can be formatted. This leads to **more
|
||||
readable messages** that are easy to follow when looking through the **project history**. But also,
|
||||
we use the git commit messages to **generate the AngularJS change log**.
|
||||
|
||||
### Commit Message Format
|
||||
Each commit message consists of a **header**, a **body** and a **footer**. The header has a special
|
||||
format that includes a **type**, a **scope** and a **subject**:
|
||||
|
||||
```
|
||||
<type>(<scope>): <subject>
|
||||
<BLANK LINE>
|
||||
<body>
|
||||
<BLANK LINE>
|
||||
<footer>
|
||||
```
|
||||
|
||||
Any line of the commit message cannot be longer 100 characters! This allows the message to be easier
|
||||
to read on github as well as in various git tools.
|
||||
|
||||
### Type
|
||||
Must be one of the following:
|
||||
|
||||
* **feat**: A new feature
|
||||
* **fix**: A bug fix
|
||||
* **docs**: Documentation only changes
|
||||
* **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing
|
||||
semi-colons, etc)
|
||||
* **refactor**: A code change that neither fixes a bug or adds a feature
|
||||
* **test**: Adding missing tests
|
||||
* **chore**: Changes to the build process or auxiliary tools and libraries such as documentation
|
||||
generation
|
||||
|
||||
### Scope
|
||||
The scope could be anything specifying place of the commit change. For example `$location`,
|
||||
`$browser`, `$compile`, `$rootScope`, `ngHref`, `ngClick`, `ngView`, etc...
|
||||
|
||||
### Subject
|
||||
The subject contains succinct description of the change:
|
||||
|
||||
* use the imperative, present tense: "change" not "changed" nor "changes"
|
||||
* don't capitalize first letter
|
||||
* no dot (.) at the end
|
||||
|
||||
###Body
|
||||
Just as in the **subject**, use the imperative, present tense: "change" not "changed" nor "changes"
|
||||
The body should include the motivation for the change and contrast this with previous behavior.
|
||||
|
||||
###Footer
|
||||
The footer should contain any information about **Breaking Changes** and is also the place to
|
||||
reference GitHub issues that this commit **Closes**.
|
||||
|
||||
|
||||
A detailed explanation can be found in this [document][commit-message-format].
|
||||
|
||||
## Signing the CLA
|
||||
|
||||
Please sign our Contributor License Agreement (CLA) before sending pull requests. For any code
|
||||
changes to be accepted, the CLA must be signed. It's a quick process, we promise!
|
||||
|
||||
* For individuals we have a [simple click-through form][individual-cla].
|
||||
* For corporations we'll need you to
|
||||
[print, sign and one of scan+email, fax or mail the form][corporate-cla].
|
||||
|
||||
## Further Information
|
||||
You can find out more detailed information about contributing in the
|
||||
[AngularJS documentation][contributing].
|
||||
|
||||
|
||||
## Submitting Your Changes
|
||||
|
||||
To create and submit a change:
|
||||
|
||||
1. Please sign our [Contributor License Agreement (CLA)](#signing-the-cla) before sending pull
|
||||
requests.
|
||||
|
||||
2. Create and checkout a new branch off the master branch for your changes:
|
||||
|
||||
```shell
|
||||
git checkout -b my-fix-branch master
|
||||
```
|
||||
|
||||
3. Create your patch, including appropriate test cases.
|
||||
|
||||
4. Commit your changes and create a descriptive commit message (the commit message is used to
|
||||
generate release notes, please check out our [commit message conventions](#commit-message-format)
|
||||
and our commit message presubmit hook `validate-commit-msg.js`):
|
||||
|
||||
```shell
|
||||
git commit -a
|
||||
```
|
||||
|
||||
5. Push your branch to Github:
|
||||
|
||||
```shell
|
||||
git push origin my-fix-branch
|
||||
```
|
||||
|
||||
6. In Github, send a pull request to `angular:master`.
|
||||
|
||||
That's it! Thank you for your contribution!
|
||||
|
||||
When the patch is reviewed and merged, you can safely delete your branch and pull the changes
|
||||
from the main (upstream) repository:
|
||||
|
||||
```shell
|
||||
# Delete the remote branch on Github:
|
||||
git push origin :my-fix-branch
|
||||
|
||||
# Check out the master branch:
|
||||
git checkout master
|
||||
|
||||
# Delete the local branch:
|
||||
git branch -D my-fix-branch
|
||||
|
||||
# Update your master with the latest upstream version:
|
||||
git pull --ff upstream master
|
||||
```
|
||||
|
||||
|
||||
[github]: https://github.com/angular/angular.js
|
||||
[Google Closure I18N library]: https://code.google.com/p/closure-library/source/browse/closure/goog/i18n/
|
||||
[list]: https://groups.google.com/forum/?fromgroups#!forum/angular
|
||||
[contribute]: http://docs.angularjs.org/misc/contribute
|
||||
[stackoverflow]: http://stackoverflow.com/questions/tagged/angularjs
|
||||
[groups]: https://groups.google.com/forum/?fromgroups#!forum/angular
|
||||
[angular-dev]: https://groups.google.com/forum/?fromgroups#!forum/angular-dev
|
||||
[irc]: http://webchat.freenode.net/?channels=angularjs&uio=d4
|
||||
[plunker]: http://plnkr.co/edit
|
||||
[jsfiddle]: http://jsfiddle.net/
|
||||
[ngDocs]: https://github.com/angular/angular.js/wiki/Writing-AngularJS-Documentation
|
||||
[unit-testing]: http://docs.angularjs.org/guide/dev_guide.unit-testing
|
||||
[js-style-guide]: http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml
|
||||
[contributing]: http://docs.angularjs.org/misc/contribute
|
||||
[individual-cla]: http://code.google.com/legal/individual-cla-v1.0.html
|
||||
[corporate-cla]: http://code.google.com/legal/corporate-cla-v1.0.html
|
||||
[commit-message-format]: https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#
|
||||
[template]: http://plnkr.co/edit/gist:3510140
|
||||
|
||||
## Contributing to Source Code
|
||||
|
||||
We'd love for you to contribute to our source code and to make AngularJS even
|
||||
better than it is today!
|
||||
|
||||
Please read the [contribution guidelines][contribute] to learn about how to submit code as well as
|
||||
other useful info like how to build and test AngularJS code.
|
||||
|
||||
[list]: https://groups.google.com/forum/?fromgroups#!forum/angular
|
||||
[contribute]: http://docs.angularjs.org/misc/contribute
|
||||
|
||||
+40
-111
@@ -1,6 +1,5 @@
|
||||
var files = require('./angularFiles').files;
|
||||
var util = require('./lib/grunt/utils.js');
|
||||
var path = require('path');
|
||||
|
||||
module.exports = function(grunt) {
|
||||
//grunt plugins
|
||||
@@ -8,12 +7,9 @@ module.exports = function(grunt) {
|
||||
grunt.loadNpmTasks('grunt-contrib-copy');
|
||||
grunt.loadNpmTasks('grunt-contrib-connect');
|
||||
grunt.loadNpmTasks('grunt-contrib-compress');
|
||||
grunt.loadNpmTasks('grunt-jasmine-node');
|
||||
grunt.loadNpmTasks('grunt-ddescribe-iit');
|
||||
grunt.loadNpmTasks('grunt-merge-conflict');
|
||||
grunt.loadNpmTasks('grunt-parallel');
|
||||
grunt.loadNpmTasks('grunt-shell');
|
||||
grunt.loadNpmTasks('grunt-contrib-jshint');
|
||||
grunt.loadTasks('lib/grunt');
|
||||
|
||||
var NG_VERSION = util.getVersion();
|
||||
@@ -30,9 +26,14 @@ module.exports = function(grunt) {
|
||||
|
||||
parallel: {
|
||||
travis: {
|
||||
options: {
|
||||
stream: true,
|
||||
},
|
||||
tasks: [
|
||||
util.parallelTask(['test:unit', 'test:docgen', 'test:promises-aplus', 'tests:docs'], {stream: true}),
|
||||
util.parallelTask(['test:e2e'])
|
||||
util.parallelTask('test:modules'),
|
||||
util.parallelTask('test:jquery'),
|
||||
util.parallelTask('test:jqlite'),
|
||||
util.parallelTask('test:e2e')
|
||||
]
|
||||
}
|
||||
},
|
||||
@@ -82,10 +83,9 @@ module.exports = function(grunt) {
|
||||
},
|
||||
|
||||
|
||||
tests: {
|
||||
test: {
|
||||
jqlite: 'karma-jqlite.conf.js',
|
||||
jquery: 'karma-jquery.conf.js',
|
||||
docs: 'karma-docs.conf.js',
|
||||
modules: 'karma-modules.conf.js',
|
||||
//NOTE run grunt test:e2e instead and it will start a webserver for you
|
||||
end2end: 'karma-e2e.conf.js'
|
||||
@@ -94,65 +94,18 @@ module.exports = function(grunt) {
|
||||
|
||||
autotest: {
|
||||
jqlite: 'karma-jqlite.conf.js',
|
||||
jquery: 'karma-jquery.conf.js',
|
||||
modules: 'karma-modules.conf.js',
|
||||
docs: 'karma-docs.conf.js'
|
||||
jquery: 'karma-jquery.conf.js'
|
||||
},
|
||||
|
||||
|
||||
clean: {
|
||||
build: ['build'],
|
||||
tmp: ['tmp']
|
||||
},
|
||||
clean: {build: ['build']},
|
||||
|
||||
jshint: {
|
||||
ng: {
|
||||
files: { src: files['angularSrc'] },
|
||||
options: { jshintrc: 'src/.jshintrc' }
|
||||
},
|
||||
ngAnimate: {
|
||||
files: { src: 'src/ngAnimate/**/*.js' },
|
||||
options: { jshintrc: 'src/ngAnimate/.jshintrc' }
|
||||
},
|
||||
ngCookies: {
|
||||
files: { src: 'src/ngCookies/**/*.js' },
|
||||
options: { jshintrc: 'src/ngCookies/.jshintrc' }
|
||||
},
|
||||
ngLocale: {
|
||||
files: { src: 'src/ngLocale/**/*.js' },
|
||||
options: { jshintrc: 'src/ngLocale/.jshintrc' }
|
||||
},
|
||||
ngMock: {
|
||||
files: { src: 'src/ngMock/**/*.js' },
|
||||
options: { jshintrc: 'src/ngMock/.jshintrc' }
|
||||
},
|
||||
ngResource: {
|
||||
files: { src: 'src/ngResource/**/*.js' },
|
||||
options: { jshintrc: 'src/ngResource/.jshintrc' }
|
||||
},
|
||||
ngRoute: {
|
||||
files: { src: 'src/ngRoute/**/*.js' },
|
||||
options: { jshintrc: 'src/ngRoute/.jshintrc' }
|
||||
},
|
||||
ngSanitize: {
|
||||
files: { src: 'src/ngSanitize/**/*.js' },
|
||||
options: { jshintrc: 'src/ngSanitize/.jshintrc' }
|
||||
},
|
||||
ngScenario: {
|
||||
files: { src: 'src/ngScenario/**/*.js' },
|
||||
options: { jshintrc: 'src/ngScenario/.jshintrc' }
|
||||
},
|
||||
ngTouch: {
|
||||
files: { src: 'src/ngTouch/**/*.js' },
|
||||
options: { jshintrc: 'src/ngTouch/.jshintrc' }
|
||||
}
|
||||
},
|
||||
|
||||
build: {
|
||||
scenario: {
|
||||
dest: 'build/angular-scenario.js',
|
||||
src: [
|
||||
'bower_components/jquery/jquery.js',
|
||||
'lib/jquery/jquery.js',
|
||||
util.wrap([files['angularSrc'], files['angularScenario']], 'ngScenario/angular')
|
||||
],
|
||||
styles: {
|
||||
@@ -164,59 +117,57 @@ module.exports = function(grunt) {
|
||||
src: util.wrap([files['angularSrc']], 'angular'),
|
||||
styles: {
|
||||
css: ['css/angular.css'],
|
||||
generateCspCssFile: true,
|
||||
minify: true
|
||||
}
|
||||
},
|
||||
loader: {
|
||||
dest: 'build/angular-loader.js',
|
||||
src: util.wrap(files['angularLoader'], 'loader')
|
||||
},
|
||||
touch: {
|
||||
dest: 'build/angular-touch.js',
|
||||
src: util.wrap(files['angularModules']['ngTouch'], 'module')
|
||||
src: util.wrap(['src/loader.js'], 'loader')
|
||||
},
|
||||
mocks: {
|
||||
dest: 'build/angular-mocks.js',
|
||||
src: files['angularModules']['ngMock'],
|
||||
src: ['src/ngMock/angular-mocks.js'],
|
||||
strict: false
|
||||
},
|
||||
sanitize: {
|
||||
dest: 'build/angular-sanitize.js',
|
||||
src: util.wrap(files['angularModules']['ngSanitize'], 'module')
|
||||
src: util.wrap([
|
||||
'src/ngSanitize/sanitize.js',
|
||||
'src/ngSanitize/directive/ngBindHtml.js',
|
||||
'src/ngSanitize/filter/linky.js',
|
||||
], 'module')
|
||||
},
|
||||
resource: {
|
||||
dest: 'build/angular-resource.js',
|
||||
src: util.wrap(files['angularModules']['ngResource'], 'module')
|
||||
},
|
||||
animate: {
|
||||
dest: 'build/angular-animate.js',
|
||||
src: util.wrap(files['angularModules']['ngAnimate'], 'module')
|
||||
},
|
||||
route: {
|
||||
dest: 'build/angular-route.js',
|
||||
src: util.wrap(files['angularModules']['ngRoute'], 'module')
|
||||
src: util.wrap(['src/ngResource/resource.js'], 'module')
|
||||
},
|
||||
cookies: {
|
||||
dest: 'build/angular-cookies.js',
|
||||
src: util.wrap(files['angularModules']['ngCookies'], 'module')
|
||||
src: util.wrap(['src/ngCookies/cookies.js'], 'module')
|
||||
},
|
||||
"promises-aplus-adapter": {
|
||||
dest:'tmp/promises-aplus-adapter++.js',
|
||||
src:['src/ng/q.js','lib/promises-aplus/promises-aplus-test-adapter.js']
|
||||
bootstrap: {
|
||||
dest: 'build/angular-bootstrap.js',
|
||||
src: util.wrap(['src/bootstrap/bootstrap.js'], 'module')
|
||||
},
|
||||
bootstrapPrettify: {
|
||||
dest: 'build/angular-bootstrap-prettify.js',
|
||||
src: util.wrap(['src/bootstrap/bootstrap-prettify.js', 'src/bootstrap/google-prettify/prettify.js'], 'module'),
|
||||
styles: {
|
||||
css: ['src/bootstrap/google-prettify/prettify.css'],
|
||||
minify: true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
min: {
|
||||
angular: 'build/angular.js',
|
||||
animate: 'build/angular-animate.js',
|
||||
cookies: 'build/angular-cookies.js',
|
||||
loader: 'build/angular-loader.js',
|
||||
touch: 'build/angular-touch.js',
|
||||
resource: 'build/angular-resource.js',
|
||||
route: 'build/angular-route.js',
|
||||
sanitize: 'build/angular-sanitize.js'
|
||||
sanitize: 'build/angular-sanitize.js',
|
||||
bootstrap: 'build/angular-bootstrap.js',
|
||||
bootstrapPrettify: 'build/angular-bootstrap-prettify.js',
|
||||
},
|
||||
|
||||
|
||||
@@ -224,9 +175,6 @@ module.exports = function(grunt) {
|
||||
process: ['build/docs/*.html', 'build/docs/.htaccess']
|
||||
},
|
||||
|
||||
"jasmine_node": {
|
||||
projectRoot: 'docs/spec'
|
||||
},
|
||||
|
||||
"ddescribe-iit": {
|
||||
files: [
|
||||
@@ -244,6 +192,7 @@ module.exports = function(grunt) {
|
||||
]
|
||||
},
|
||||
|
||||
|
||||
copy: {
|
||||
i18n: {
|
||||
files: [
|
||||
@@ -260,17 +209,6 @@ module.exports = function(grunt) {
|
||||
}
|
||||
},
|
||||
|
||||
shell:{
|
||||
"promises-aplus-tests":{
|
||||
options:{
|
||||
//stdout:true,
|
||||
stderr:true,
|
||||
failOnError:true
|
||||
},
|
||||
command:path.normalize('./node_modules/.bin/promises-aplus-tests tmp/promises-aplus-adapter++.js')
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
write: {
|
||||
versionTXT: {file: 'build/version.txt', val: NG_VERSION.full},
|
||||
@@ -280,20 +218,11 @@ module.exports = function(grunt) {
|
||||
|
||||
|
||||
//alias tasks
|
||||
grunt.registerTask('test', 'Run unit, docs and e2e tests with Karma', ['jshint', 'package','test:unit','test:promises-aplus', 'tests:docs', 'test:e2e']);
|
||||
grunt.registerTask('test:jqlite', 'Run the unit tests with Karma' , ['tests:jqlite']);
|
||||
grunt.registerTask('test:jquery', 'Run the jQuery unit tests with Karma', ['tests:jquery']);
|
||||
grunt.registerTask('test:modules', 'Run the Karma module tests with Karma', ['tests:modules']);
|
||||
grunt.registerTask('test:docs', 'Run the doc-page tests with Karma', ['package', 'tests:docs']);
|
||||
grunt.registerTask('test:unit', 'Run unit, jQuery and Karma module tests with Karma', ['tests:jqlite', 'tests:jquery', 'tests:modules']);
|
||||
grunt.registerTask('test:e2e', 'Run the end to end tests with Karma and keep a test server running in the background', ['connect:testserver', 'tests:end2end']);
|
||||
grunt.registerTask('test:docgen', ['jasmine_node']);
|
||||
grunt.registerTask('test:promises-aplus',['build:promises-aplus-adapter','shell:promises-aplus-tests']);
|
||||
|
||||
grunt.registerTask('minify', ['bower','clean', 'build', 'minall']);
|
||||
grunt.registerTask('test:unit', ['test:jqlite', 'test:jquery', 'test:modules']);
|
||||
grunt.registerTask('minify', ['clean', 'build', 'minall']);
|
||||
grunt.registerTask('test:e2e', ['connect:testserver', 'test:end2end']);
|
||||
grunt.registerTask('webserver', ['connect:devserver']);
|
||||
grunt.registerTask('package', ['bower','clean', 'buildall', 'minall', 'collect-errors', 'docs', 'copy', 'write', 'compress']);
|
||||
grunt.registerTask('package-without-bower', ['clean', 'buildall', 'minall', 'collect-errors', 'docs', 'copy', 'write', 'compress']);
|
||||
grunt.registerTask('ci-checks', ['ddescribe-iit', 'merge-conflict', 'jshint', 'test:docgen']);
|
||||
grunt.registerTask('package', ['clean', 'buildall', 'minall', 'docs', 'copy', 'write', 'compress']);
|
||||
grunt.registerTask('ci-checks', ['ddescribe-iit', 'merge-conflict']);
|
||||
grunt.registerTask('default', ['package']);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
Using AngularJS with the Closure Compiler
|
||||
=========================================
|
||||
|
||||
The Closure Compiler project contains externs definitions for AngularJS
|
||||
JavaScript in its `contrib/externs` directory.
|
||||
|
||||
The definitions contain externs for use with the Closure compiler (aka
|
||||
JSCompiler). Passing these files to the --externs parameter of a compiler
|
||||
pass allows using type annotations for AngularJS objects. For example,
|
||||
Angular's $scope objects can be annotated as:
|
||||
```js
|
||||
/** @type {angular.Scope} */
|
||||
var scope = $scope;
|
||||
```
|
||||
|
||||
This allows JSCompiler to type check accesses to scope, give warnings about
|
||||
missing methods or incorrect arguments, and also prevents renaming of property
|
||||
accesses with advanced compilation.
|
||||
|
||||
The externs are incomplete and maintained on an as-needed basis, but strive to
|
||||
be correct. Externs for individual modules should be added in separate files.
|
||||
|
||||
See https://developers.google.com/closure/compiler/
|
||||
@@ -1,4 +1,4 @@
|
||||
AngularJS [](https://travis-ci.org/angular/angular.js)
|
||||
AngularJS
|
||||
=========
|
||||
|
||||
AngularJS lets you write client-side web applications as if you had a smarter browser. It lets you
|
||||
|
||||
+38
-69
@@ -1,6 +1,5 @@
|
||||
angularFiles = {
|
||||
'angularSrc': [
|
||||
'src/minErr.js',
|
||||
'src/Angular.js',
|
||||
'src/loader.js',
|
||||
'src/AngularPublic.js',
|
||||
@@ -10,28 +9,26 @@ angularFiles = {
|
||||
'src/auto/injector.js',
|
||||
|
||||
'src/ng/anchorScroll.js',
|
||||
'src/ng/animate.js',
|
||||
'src/ng/browser.js',
|
||||
'src/ng/cacheFactory.js',
|
||||
'src/ng/compile.js',
|
||||
'src/ng/controller.js',
|
||||
'src/ng/document.js',
|
||||
'src/ng/exceptionHandler.js',
|
||||
'src/ng/http.js',
|
||||
'src/ng/httpBackend.js',
|
||||
'src/ng/interpolate.js',
|
||||
'src/ng/interval.js',
|
||||
'src/ng/locale.js',
|
||||
'src/ng/location.js',
|
||||
'src/ng/log.js',
|
||||
'src/ng/parse.js',
|
||||
'src/ng/q.js',
|
||||
'src/ng/route.js',
|
||||
'src/ng/routeParams.js',
|
||||
'src/ng/rootScope.js',
|
||||
'src/ng/sce.js',
|
||||
'src/ng/sniffer.js',
|
||||
'src/ng/timeout.js',
|
||||
'src/ng/urlUtils.js',
|
||||
'src/ng/window.js',
|
||||
'src/ng/http.js',
|
||||
'src/ng/httpBackend.js',
|
||||
'src/ng/locale.js',
|
||||
'src/ng/timeout.js',
|
||||
|
||||
'src/ng/filter.js',
|
||||
'src/ng/filter/filter.js',
|
||||
@@ -50,7 +47,6 @@ angularFiles = {
|
||||
'src/ng/directive/ngController.js',
|
||||
'src/ng/directive/ngCsp.js',
|
||||
'src/ng/directive/ngEventDirs.js',
|
||||
'src/ng/directive/ngIf.js',
|
||||
'src/ng/directive/ngInclude.js',
|
||||
'src/ng/directive/ngInit.js',
|
||||
'src/ng/directive/ngNonBindable.js',
|
||||
@@ -60,49 +56,25 @@ angularFiles = {
|
||||
'src/ng/directive/ngStyle.js',
|
||||
'src/ng/directive/ngSwitch.js',
|
||||
'src/ng/directive/ngTransclude.js',
|
||||
'src/ng/directive/ngView.js',
|
||||
'src/ng/directive/script.js',
|
||||
'src/ng/directive/select.js',
|
||||
'src/ng/directive/style.js'
|
||||
],
|
||||
|
||||
'angularLoader': [
|
||||
'src/minErr.js',
|
||||
'src/loader.js'
|
||||
],
|
||||
'angularSrcModules': [
|
||||
'src/ngCookies/cookies.js',
|
||||
'src/ngResource/resource.js',
|
||||
'src/ngSanitize/sanitize.js',
|
||||
'src/ngSanitize/directive/ngBindHtml.js',
|
||||
'src/ngSanitize/filter/linky.js',
|
||||
'src/ngMock/angular-mocks.js',
|
||||
|
||||
'angularModules': {
|
||||
'ngAnimate': [
|
||||
'src/ngAnimate/animate.js'
|
||||
],
|
||||
'ngCookies': [
|
||||
'src/ngCookies/cookies.js'
|
||||
],
|
||||
'ngResource': [
|
||||
'src/ngResource/resource.js'
|
||||
],
|
||||
'ngRoute': [
|
||||
'src/ngRoute/route.js',
|
||||
'src/ngRoute/routeParams.js',
|
||||
'src/ngRoute/directive/ngView.js'
|
||||
],
|
||||
'ngSanitize': [
|
||||
'src/ngSanitize/sanitize.js',
|
||||
'src/ngSanitize/filter/linky.js'
|
||||
],
|
||||
'ngMock': [
|
||||
'src/ngMock/angular-mocks.js'
|
||||
],
|
||||
'ngTouch': [
|
||||
'src/ngTouch/touch.js',
|
||||
'src/ngTouch/swipe.js',
|
||||
'src/ngTouch/directive/ngClick.js',
|
||||
'src/ngTouch/directive/ngSwipe.js'
|
||||
],
|
||||
},
|
||||
'src/bootstrap/bootstrap.js'
|
||||
],
|
||||
|
||||
'angularScenario': [
|
||||
'src/ngScenario/Scenario.js',
|
||||
'src/ngScenario/browserTrigger.js',
|
||||
'src/ngScenario/Application.js',
|
||||
'src/ngScenario/Describe.js',
|
||||
'src/ngScenario/Future.js',
|
||||
@@ -118,23 +90,26 @@ angularFiles = {
|
||||
],
|
||||
|
||||
'angularTest': [
|
||||
'test/helpers/*.js',
|
||||
'test/testabilityPatch.js',
|
||||
'test/matchers.js',
|
||||
'test/ngScenario/*.js',
|
||||
'test/ngScenario/output/*.js',
|
||||
'test/*.js',
|
||||
'test/auto/*.js',
|
||||
'test/ng/**/*.js',
|
||||
'test/ngAnimate/*.js',
|
||||
'test/bootstrap/*.js',
|
||||
'test/ng/*.js',
|
||||
'test/ng/directive/*.js',
|
||||
'test/ng/filter/*.js',
|
||||
'test/ngCookies/*.js',
|
||||
'test/ngResource/*.js',
|
||||
'test/ngRoute/**/*.js',
|
||||
'test/ngSanitize/**/*.js',
|
||||
'test/ngMock/*.js',
|
||||
'test/ngTouch/**/*.js'
|
||||
'test/ngSanitize/*.js',
|
||||
'test/ngSanitize/directive/*.js',
|
||||
'test/ngSanitize/filter/*.js',
|
||||
'test/ngMock/*.js'
|
||||
],
|
||||
|
||||
'karma': [
|
||||
'bower_components/jquery/jquery.js',
|
||||
'lib/jquery/jquery.js',
|
||||
'test/jquery_remove.js',
|
||||
'@angularSrc',
|
||||
'src/publishExternalApis.js',
|
||||
@@ -158,19 +133,23 @@ angularFiles = {
|
||||
|
||||
"karmaModules": [
|
||||
'build/angular.js',
|
||||
'@angularSrcModules',
|
||||
'src/ngScenario/browserTrigger.js',
|
||||
'test/helpers/*.js',
|
||||
'src/ngMock/angular-mocks.js',
|
||||
'src/ngCookies/cookies.js',
|
||||
'src/ngResource/resource.js',
|
||||
'src/ngSanitize/sanitize.js',
|
||||
'src/ngSanitize/directive/ngBindHtml.js',
|
||||
'src/ngSanitize/filter/linky.js',
|
||||
'test/matchers.js',
|
||||
'test/ngMock/*.js',
|
||||
'test/ngCookies/*.js',
|
||||
'test/ngRoute/**/*.js',
|
||||
'test/ngResource/*.js',
|
||||
'test/ngSanitize/**/*.js',
|
||||
'test/ngTouch/**/*.js'
|
||||
'test/ngSanitize/*.js',
|
||||
'test/ngSanitize/directive/*.js',
|
||||
'test/ngSanitize/filter/*.js'
|
||||
],
|
||||
|
||||
'karmaJquery': [
|
||||
'bower_components/jquery/jquery.js',
|
||||
'lib/jquery/jquery.js',
|
||||
'test/jquery_alias.js',
|
||||
'@angularSrc',
|
||||
'src/publishExternalApis.js',
|
||||
@@ -189,16 +168,6 @@ angularFiles = {
|
||||
]
|
||||
};
|
||||
|
||||
angularFiles['angularSrcModules'] = [].concat(
|
||||
angularFiles['angularModules']['ngAnimate'],
|
||||
angularFiles['angularModules']['ngCookies'],
|
||||
angularFiles['angularModules']['ngResource'],
|
||||
angularFiles['angularModules']['ngRoute'],
|
||||
angularFiles['angularModules']['ngSanitize'],
|
||||
angularFiles['angularModules']['ngMock'],
|
||||
angularFiles['angularModules']['ngTouch']
|
||||
);
|
||||
|
||||
if (exports) {
|
||||
exports.files = angularFiles;
|
||||
exports.mergeFilesFor = function() {
|
||||
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"name": "AngularJS",
|
||||
"devDependencies": {
|
||||
"jquery": "1.10.2",
|
||||
"lunr.js": "0.4.0",
|
||||
"google-code-prettify": "1.0.0",
|
||||
"components-font-awesome": "3.1.0",
|
||||
"bootstrap": "https://raw.github.com/twbs/bootstrap/v2.0.2/docs/assets/bootstrap.zip",
|
||||
"closure-compiler": "https://closure-compiler.googlecode.com/files/compiler-20130603.zip",
|
||||
"ng-closure-runner": "https://raw.github.com/angular/ng-closure-runner/v0.2.2/assets/ng-closure-runner.zip"
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ var LINK_ISSUE = '[#%s](https://github.com/angular/angular.js/issues/%s)';
|
||||
var LINK_COMMIT = '[%s](https://github.com/angular/angular.js/commit/%s)';
|
||||
|
||||
var EMPTY_COMPONENT = '$$';
|
||||
var MAX_SUBJECT_LENGTH = 80;
|
||||
|
||||
|
||||
var warn = function() {
|
||||
@@ -53,6 +54,11 @@ var parseRawCommit = function(raw) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (match[3].length > MAX_SUBJECT_LENGTH) {
|
||||
warn('Too long subject: %s %s', msg.hash, msg.subject);
|
||||
match[3] = match[3].substr(0, MAX_SUBJECT_LENGTH);
|
||||
}
|
||||
|
||||
msg.type = match[1];
|
||||
msg.component = match[2];
|
||||
msg.subject = match[3];
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
This file contains externs for use with the Closure compiler (aka JSCompiler).
|
||||
Passing these files to the --externs parameter of a compiler pass allows using
|
||||
type annotations for AngularJS objects. For example, Angular's $scope objects
|
||||
can be annotated as:
|
||||
```js
|
||||
/** @type {angular.Scope} */
|
||||
var scope = $scope;
|
||||
```
|
||||
|
||||
This allows JSCompiler to type check accesses to scope, give warnings about
|
||||
missing methods or incorrect arguments, and also prevents renaming of property
|
||||
accesses with advanced compilation.
|
||||
|
||||
The externs are incomplete and maintained on an as-needed basis, but strive to
|
||||
be correct. Externs for individual modules should be added in separate files.
|
||||
|
||||
See https://developers.google.com/closure/compiler/
|
||||
Vendored
-1912
File diff suppressed because it is too large
Load Diff
@@ -1,163 +0,0 @@
|
||||
#!/usr/local/bin/node
|
||||
|
||||
var util = require('util');
|
||||
var cp = require('child_process');
|
||||
|
||||
var Q = require('q');
|
||||
var _ = require('lodash');
|
||||
var semver = require('semver');
|
||||
|
||||
var exec = function (cmd) {
|
||||
return function () {
|
||||
var args = Array.prototype.slice.call(arguments, 0);
|
||||
args.unshift(cmd);
|
||||
var fullCmd = util.format.apply(util, args);
|
||||
return Q.nfcall(cp.exec, fullCmd).then(function (out) {
|
||||
return out[0].split('\n');
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
var andThen = function (fn, after) {
|
||||
return function () {
|
||||
return fn.apply(this, arguments).then(after);
|
||||
};
|
||||
};
|
||||
|
||||
var oneArg = function (fn) {
|
||||
return function (arg) {
|
||||
return fn(arg);
|
||||
};
|
||||
};
|
||||
|
||||
var oneLine = function (lines) {
|
||||
return lines[0].trim();
|
||||
};
|
||||
|
||||
var noArgs = function (fn) {
|
||||
return function () {
|
||||
return fn();
|
||||
};
|
||||
};
|
||||
|
||||
var identity = function (i) { return i; };
|
||||
|
||||
// like Q.all, but runs the comands in series
|
||||
// useful for ensuring env state (like which branch is checked out)
|
||||
var allInSeries = function (fn) {
|
||||
return function (args) {
|
||||
var results = [];
|
||||
var def;
|
||||
while (args.length > 0) {
|
||||
(function (arg) {
|
||||
if (def) {
|
||||
def = def.then(function () {
|
||||
return fn(arg);
|
||||
});
|
||||
} else {
|
||||
def = fn(arg);
|
||||
}
|
||||
def = def.then(function (res) {
|
||||
results.push(res);
|
||||
});
|
||||
}(args.pop()));
|
||||
}
|
||||
return def.then(function () {
|
||||
return results;
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
var compareBranches = function (left, right) {
|
||||
console.log('# These commits are in ' + left.name + ' but not in ' + right.name + '\n');
|
||||
console.log(_(left.log).
|
||||
difference(right.log).
|
||||
map(function (line) {
|
||||
return left.full[left.log.indexOf(line)]; // lol O(n^2)
|
||||
}).
|
||||
value().
|
||||
join('\n'));
|
||||
};
|
||||
|
||||
var checkout = oneArg(exec('git checkout %s'));
|
||||
|
||||
var getCurrentBranch = andThen(noArgs(exec('git rev-parse --abbrev-ref HEAD')), oneLine);
|
||||
var getTags = noArgs(exec('git tag'));
|
||||
var getShaOfTag = oneArg(exec('git rev-list %s | head -n 1'));
|
||||
var getTheLog = oneArg(exec('git log --pretty=oneline %s..HEAD | cat'));
|
||||
|
||||
// remember this so we can restore state
|
||||
var currentBranch;
|
||||
|
||||
getCurrentBranch().
|
||||
then(function (branch) {
|
||||
currentBranch = branch;
|
||||
}).
|
||||
then(getTags).
|
||||
then(function (tags) {
|
||||
return tags.
|
||||
filter(semver.valid).
|
||||
map(semver.clean).
|
||||
sort(semver.rcompare);
|
||||
}).
|
||||
then(function (tags) {
|
||||
var major = tags[0].split('.')[0] + '.x';
|
||||
return tags.
|
||||
filter(function (ver) {
|
||||
return semver.satisfies(ver, major);
|
||||
});
|
||||
}).
|
||||
then(function (tags) {
|
||||
return _(tags).
|
||||
groupBy(function (tag) {
|
||||
return tag.split('.')[1];
|
||||
}).
|
||||
map(function (group) {
|
||||
return _.first(group);
|
||||
}).
|
||||
map(function (tag) {
|
||||
return 'v' + tag;
|
||||
}).
|
||||
value();
|
||||
}).
|
||||
then(function (tags) {
|
||||
return [
|
||||
{ name: 'v1.0.x', tag: tags[0] },
|
||||
{ name: 'master', tag: tags[1] }
|
||||
];
|
||||
}).
|
||||
then(allInSeries(function (branch) {
|
||||
return checkout(branch.name).
|
||||
then(function () {
|
||||
return getTheLog(branch.tag);
|
||||
}).
|
||||
then(function (log) {
|
||||
return log.
|
||||
filter(identity);
|
||||
}).
|
||||
then(function (log) {
|
||||
branch.full = log.map(function (line) {
|
||||
line = line.split(' ');
|
||||
var sha = line.shift();
|
||||
var msg = line.join(' ');
|
||||
return sha + (msg.toLowerCase().indexOf('fix') === -1 ? ' ' : ' * ') + msg;
|
||||
});
|
||||
branch.log = log.map(function (line) {
|
||||
return line.substr(41)
|
||||
});
|
||||
return branch;
|
||||
});
|
||||
})).
|
||||
then(function (pairs) {
|
||||
compareBranches(pairs[0], pairs[1]);
|
||||
console.log('\n');
|
||||
compareBranches(pairs[1], pairs[0]);
|
||||
return pairs;
|
||||
}).
|
||||
then(function () {
|
||||
return checkout(currentBranch);
|
||||
}).
|
||||
catch(function (e) {
|
||||
console.log(e.stack);
|
||||
});
|
||||
|
||||
+1
-13
@@ -1,22 +1,10 @@
|
||||
@charset "UTF-8";
|
||||
|
||||
[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak],
|
||||
.ng-cloak, .x-ng-cloak,
|
||||
.ng-hide {
|
||||
.ng-cloak, .x-ng-cloak {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
ng\:form {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* The styles below ensure that the CSS transition will ALWAYS
|
||||
* animate and close. A nasty bug occurs with CSS transitions where
|
||||
* when the active class isn't set, or if the active class doesn't
|
||||
* contain any styles to transition to, then, if ngAnimate is used,
|
||||
* it will appear as if the webpage is broken due to the forever hanging
|
||||
* animations. The border-spacing (!ie) and zoom (ie) CSS properties are
|
||||
* used below since they trigger a transition without making the browser
|
||||
* animate anything and they're both highly underused CSS properties */
|
||||
.ng-animate-start { border-spacing:1px 1px; -ms-zoom:1.0001; }
|
||||
.ng-animate-active { border-spacing:0px 0px; -ms-zoom:1; }
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
describe("DocsNavigationCtrl", function() {
|
||||
|
||||
beforeEach(module('docsApp'));
|
||||
|
||||
var ctrl, $scope;
|
||||
|
||||
beforeEach(function() {
|
||||
module(function($provide) {
|
||||
$provide.value('docsPages', []);
|
||||
$provide.factory('docsSearch', function() {
|
||||
return function(q) {
|
||||
return ['one','two','three'];
|
||||
};
|
||||
});
|
||||
});
|
||||
inject(function($controller, $rootScope, $location, docsSearch) {
|
||||
$scope = $rootScope.$new();
|
||||
ctrl = $controller('DocsNavigationCtrl', {
|
||||
$scope : $scope,
|
||||
$location : $location,
|
||||
docsSearch : docsSearch
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should search and return data from docsSearch", function() {
|
||||
$scope.search('1234')
|
||||
expect($scope.results.join(',')).toBe('one,two,three');
|
||||
expect($scope.hasResults).toBe(true);
|
||||
});
|
||||
|
||||
it("should avoid searching if the search term is too short", function() {
|
||||
$scope.search('1')
|
||||
expect($scope.results.length).toBe(0);
|
||||
expect($scope.hasResults).toBe(false);
|
||||
});
|
||||
|
||||
it("should set the columns classname based on the total grouped results", function() {
|
||||
$scope.search('1234');
|
||||
expect($scope.colClassName).toBe('cols-3');
|
||||
|
||||
$scope.search('1');
|
||||
expect($scope.colClassName).toBe(null);
|
||||
});
|
||||
|
||||
it("should hide and clear the results when called", function() {
|
||||
$scope.hasResults = true;
|
||||
$scope.results = ['one'];
|
||||
$scope.colClassName = '...';
|
||||
$scope.hideResults();
|
||||
expect($scope.hasResults).toBe(false);
|
||||
expect($scope.results.length).toBe(0);
|
||||
expect($scope.colClassName).toBe(null);
|
||||
});
|
||||
|
||||
it("should hide, clear and change the path of the page when submitted", inject(function($location) {
|
||||
$scope.hasResults = true;
|
||||
$scope.results = {
|
||||
api : [
|
||||
{url : '/home'}
|
||||
],
|
||||
tutorial : [
|
||||
{url : '/tutorial'}
|
||||
]
|
||||
};
|
||||
$scope.submit();
|
||||
expect($location.path()).toBe('/home');
|
||||
expect($scope.results.length).toBe(0);
|
||||
expect($scope.hasResults).toBe(false);
|
||||
}));
|
||||
|
||||
});
|
||||
@@ -1,195 +0,0 @@
|
||||
describe('Docs Annotations', function() {
|
||||
|
||||
beforeEach(module('docsApp'));
|
||||
|
||||
var body;
|
||||
beforeEach(function() {
|
||||
body = angular.element(document.body);
|
||||
body.html('');
|
||||
});
|
||||
|
||||
var normalizeHtml = function(html) {
|
||||
return html.toLowerCase().replace(/\s*$/, '');
|
||||
};
|
||||
|
||||
describe('popover directive', function() {
|
||||
|
||||
var $scope, element;
|
||||
beforeEach(inject(function($rootScope, $compile) {
|
||||
$scope = $rootScope.$new();
|
||||
element = angular.element(
|
||||
'<div style="margin:200px;" data-title="title_text" data-content="content_text" popover></div>'
|
||||
);
|
||||
element.attr('id','idx');
|
||||
body.append(element);
|
||||
$compile(element)($scope);
|
||||
$scope.$apply();
|
||||
}));
|
||||
|
||||
it('should be hidden by default', inject(function(popoverElement) {
|
||||
expect(popoverElement.visible()).toBe(false);
|
||||
}));
|
||||
|
||||
it('should capture the click event and set the title and content and position the tip', inject(function(popoverElement) {
|
||||
element.triggerHandler('click');
|
||||
expect(popoverElement.isSituatedAt(element)).toBe(true);
|
||||
expect(popoverElement.visible()).toBe(true);
|
||||
expect(popoverElement.title()).toBe('title_text');
|
||||
expect(popoverElement.content()).toContain('content_text');
|
||||
expect(popoverElement.besideElement.attr('id')).toBe('idx');
|
||||
}));
|
||||
|
||||
it('should hide and clear the title and content if the same element is clicked again', inject(function(popoverElement) {
|
||||
//show the element
|
||||
element.triggerHandler('click');
|
||||
expect(popoverElement.isSituatedAt(element)).toBe(true);
|
||||
|
||||
//hide the element
|
||||
element.triggerHandler('click');
|
||||
expect(popoverElement.isSituatedAt(element)).toBe(false);
|
||||
expect(popoverElement.visible()).toBe(false);
|
||||
expect(popoverElement.title()).toBe('');
|
||||
expect(popoverElement.content()).toBe('');
|
||||
}));
|
||||
|
||||
it('should parse markdown content', inject(function(popoverElement, $compile) {
|
||||
element = angular.element(
|
||||
'<div style="margin:200px;" data-title="#title_text" data-content="#heading" popover></div>'
|
||||
);
|
||||
body.append(element);
|
||||
$compile(element)($scope);
|
||||
$scope.$apply();
|
||||
element.triggerHandler('click');
|
||||
expect(popoverElement.title()).toBe('#title_text');
|
||||
expect(normalizeHtml(popoverElement.content())).toMatch('<h1>heading</h1>');
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('foldout directive', function() {
|
||||
|
||||
// Do not run this suite on Internet Explorer.
|
||||
if (msie < 10) return;
|
||||
|
||||
var $scope, parent, element, url;
|
||||
beforeEach(function() {
|
||||
module(function($provide, $animateProvider) {
|
||||
$animateProvider.register('.foldout', function($timeout) {
|
||||
return {
|
||||
enter : function(element, done) {
|
||||
$timeout(done, 1000);
|
||||
},
|
||||
removeClass : function(element, className, done) {
|
||||
$timeout(done, 500);
|
||||
},
|
||||
addClass : function(element, className, done) {
|
||||
$timeout(done, 200);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
inject(function($rootScope, $compile, $templateCache, $rootElement, $animate) {
|
||||
$animate.enabled(true);
|
||||
url = '/page.html';
|
||||
$scope = $rootScope.$new();
|
||||
parent = angular.element('<div class="parent"></div>');
|
||||
|
||||
//we're injecting the element to the $rootElement since the changes in
|
||||
//$animate only detect and perform animations if the root element has
|
||||
//animations enabled. If the element is not apart of the DOM
|
||||
//then animations are skipped.
|
||||
element = angular.element('<div data-url="' + url + '" class="foldout" foldout></div>');
|
||||
parent.append(element);
|
||||
$rootElement.append(parent);
|
||||
body.append($rootElement);
|
||||
|
||||
$compile(parent)($scope);
|
||||
$scope.$apply();
|
||||
});
|
||||
});
|
||||
|
||||
it('should inform that it is loading', inject(function($httpBackend) {
|
||||
$httpBackend.expect('GET', url).respond('hello');
|
||||
element.triggerHandler('click');
|
||||
|
||||
var kids = body.children();
|
||||
var foldout = angular.element(kids[kids.length-1]);
|
||||
expect(foldout.html()).toContain('loading');
|
||||
}));
|
||||
|
||||
//TODO(matias): this test is bad. it's not clear what is being tested and what the assertions are.
|
||||
// Additionally, now that promises get auto-flushed there are extra tasks in the deferred queue which screws up
|
||||
// these brittle tests.
|
||||
xit('should download a foldout HTML page and animate the contents', inject(function($httpBackend, $timeout, $sniffer) {
|
||||
$httpBackend.expect('GET', url).respond('hello');
|
||||
|
||||
element.triggerHandler('click');
|
||||
$httpBackend.flush();
|
||||
|
||||
$timeout.flushNext(0);
|
||||
$timeout.flushNext(1000);
|
||||
|
||||
var kids = body.children();
|
||||
var foldout = angular.element(kids[kids.length-1]);
|
||||
expect(foldout.text()).toContain('hello');
|
||||
}));
|
||||
|
||||
//TODO(matias): this test is bad. it's not clear what is being tested and what the assertions are.
|
||||
// Additionally, now that promises get auto-flushed there are extra tasks in the deferred queue which screws up
|
||||
// these brittle tests.
|
||||
xit('should hide then show when clicked again', inject(function($httpBackend, $timeout, $sniffer) {
|
||||
$httpBackend.expect('GET', url).respond('hello');
|
||||
|
||||
//enter
|
||||
element.triggerHandler('click');
|
||||
$httpBackend.flush();
|
||||
$timeout.flushNext(0);
|
||||
$timeout.flushNext(1000);
|
||||
|
||||
//hide
|
||||
element.triggerHandler('click');
|
||||
$timeout.flushNext(0);
|
||||
$timeout.flushNext(200);
|
||||
|
||||
//show
|
||||
element.triggerHandler('click');
|
||||
$timeout.flushNext(0);
|
||||
$timeout.flushNext(500);
|
||||
$timeout.flushNext(0);
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
describe('DocsController fold', function() {
|
||||
|
||||
var $scope, ctrl;
|
||||
beforeEach(function() {
|
||||
inject(function($rootScope, $controller, $location, $cookies, sections) {
|
||||
$scope = $rootScope.$new();
|
||||
ctrl = $controller('DocsController',{
|
||||
$scope : $scope,
|
||||
$location : $location,
|
||||
$cookies : $cookies,
|
||||
sections : sections
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should download and reveal the foldover container', inject(function($compile, $httpBackend) {
|
||||
var url = '/page.html';
|
||||
var fullUrl = '/notes/' + url;
|
||||
$httpBackend.expect('GET', fullUrl).respond('hello');
|
||||
|
||||
var element = angular.element('<div ng-include="docs_fold"></div>');
|
||||
$compile(element)($scope);
|
||||
$scope.$apply();
|
||||
|
||||
$scope.fold(url);
|
||||
|
||||
$httpBackend.flush();
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
@@ -1,59 +0,0 @@
|
||||
describe("docsSearch", function() {
|
||||
|
||||
beforeEach(module('docsApp'));
|
||||
|
||||
var interceptedLunrResults;
|
||||
beforeEach(function() {
|
||||
interceptedLunrResults = [];
|
||||
});
|
||||
|
||||
beforeEach(function() {
|
||||
module(function($provide) {
|
||||
var results = [];
|
||||
results[0] = { section: 'tutorial', shortName: 'item one', keywords: 'item, one, 1' };
|
||||
results[1] = { section: 'tutorial', shortName: 'item man', keywords: 'item, man' };
|
||||
results[2] = { section: 'api', shortName: 'item other', keywords: 'item, other' };
|
||||
results[3] = { section: 'cookbook', shortName: 'item cookbook', keywords: 'item, other' };
|
||||
results[4] = { section: 'api', shortName: 'ngRepeat', keywords: 'item, other' };
|
||||
|
||||
$provide.value('NG_PAGES', results);
|
||||
$provide.factory('lunrSearch', function() {
|
||||
return function() {
|
||||
return {
|
||||
store : function(value) {
|
||||
interceptedLunrResults.push(value);
|
||||
},
|
||||
search : function(q) {
|
||||
var data = [];
|
||||
angular.forEach(results, function(res, i) {
|
||||
data.push({ ref : i });
|
||||
});
|
||||
return data;
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should lookup and organize values properly", inject(function(docsSearch) {
|
||||
var items = docsSearch('item');
|
||||
expect(items['api'].length).toBe(2);
|
||||
}));
|
||||
|
||||
it("should place cookbook items in the tutorial", inject(function(docsSearch) {
|
||||
var items = docsSearch('item');
|
||||
expect(items['tutorial'].length).toBe(3);
|
||||
}));
|
||||
|
||||
it("should return all results without a search", inject(function(docsSearch) {
|
||||
var items = docsSearch();
|
||||
expect(items['tutorial'].length).toBe(3);
|
||||
expect(items['api'].length).toBe(2);
|
||||
}));
|
||||
|
||||
it("should store values with and without a ng prefix", inject(function(docsSearch) {
|
||||
expect(interceptedLunrResults[4].title).toBe('ngRepeat repeat');
|
||||
}));
|
||||
|
||||
});
|
||||
@@ -1,76 +0,0 @@
|
||||
describe("errorDisplay", function () {
|
||||
|
||||
var $location, compileHTML;
|
||||
|
||||
beforeEach(module('docsApp'));
|
||||
|
||||
beforeEach(inject(function ($injector) {
|
||||
var $rootScope = $injector.get('$rootScope'),
|
||||
$compile = $injector.get('$compile');
|
||||
|
||||
$location = $injector.get('$location');
|
||||
|
||||
compileHTML = function (code) {
|
||||
var elm = angular.element(code);
|
||||
$compile(elm)($rootScope);
|
||||
$rootScope.$digest();
|
||||
return elm;
|
||||
};
|
||||
|
||||
this.addMatchers({
|
||||
toInterpolateTo: function (expected) {
|
||||
// Given a compiled DOM node with a minerr-display attribute,
|
||||
// assert that its interpolated string matches the expected text.
|
||||
return this.actual.text() === expected;
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
it('should interpolate a template with no parameters', function () {
|
||||
var elm;
|
||||
|
||||
spyOn($location, 'search').andReturn({});
|
||||
elm = compileHTML('<div error-display="This is a test"></div>');
|
||||
expect(elm).toInterpolateTo('This is a test');
|
||||
});
|
||||
|
||||
it('should interpolate a template with no parameters when search parameters are present', function () {
|
||||
var elm;
|
||||
|
||||
spyOn($location, 'search').andReturn({ p0: 'foobaz' });
|
||||
elm = compileHTML('<div error-display="This is a test"></div>');
|
||||
expect(elm).toInterpolateTo('This is a test');
|
||||
});
|
||||
|
||||
it('should correctly interpolate search parameters', function () {
|
||||
var elm;
|
||||
|
||||
spyOn($location, 'search').andReturn({ p0: '42' });
|
||||
elm = compileHTML('<div error-display="The answer is {0}"></div>');
|
||||
expect(elm).toInterpolateTo('The answer is 42');
|
||||
});
|
||||
|
||||
it('should interpolate parameters in the specified order', function () {
|
||||
var elm;
|
||||
|
||||
spyOn($location, 'search').andReturn({ p0: 'second', p1: 'first' });
|
||||
elm = compileHTML('<div error-display="{1} {0}"></div>');
|
||||
expect(elm).toInterpolateTo('first second');
|
||||
});
|
||||
|
||||
it('should preserve interpolation markers when fewer arguments than needed are provided', function () {
|
||||
var elm;
|
||||
|
||||
spyOn($location, 'search').andReturn({ p0: 'Fooooo' });
|
||||
elm = compileHTML('<div error-display="This {0} is {1} on {2}"></div>');
|
||||
expect(elm).toInterpolateTo('This Fooooo is {1} on {2}');
|
||||
});
|
||||
|
||||
it('should correctly handle the empty string as an interpolation parameter', function () {
|
||||
var elm;
|
||||
|
||||
spyOn($location, 'search').andReturn({ p0: 'test', p1: '' });
|
||||
elm = compileHTML('<div error-display="This {0} is a {1}"></div>');
|
||||
expect(elm).toInterpolateTo('This test is a ');
|
||||
});
|
||||
});
|
||||
@@ -1,52 +0,0 @@
|
||||
describe("errorLinkFilter", function () {
|
||||
|
||||
var errorLinkFilter;
|
||||
|
||||
beforeEach(module('docsApp'));
|
||||
|
||||
beforeEach(inject(function ($filter) {
|
||||
errorLinkFilter = $filter('errorLink');
|
||||
}));
|
||||
|
||||
it('should not change text that does not contain links', function () {
|
||||
expect(errorLinkFilter('This is a test')).toBe('This is a test');
|
||||
});
|
||||
|
||||
it('should find links in text and linkify them', function () {
|
||||
var output = errorLinkFilter("http://ab/ (http://a/) http://1.2/v:~-123. c");
|
||||
//temporary fix for IE8 sanitization whitespace bug
|
||||
output = output.replace('</a>(','</a> (');
|
||||
expect(output).
|
||||
toBe('<a href="http://ab/">http://ab/</a> ' +
|
||||
'(<a href="http://a/">http://a/</a>) ' +
|
||||
'<a href="http://1.2/v:~-123">http://1.2/v:~-123</a>. c');
|
||||
expect(errorLinkFilter(undefined)).not.toBeDefined();
|
||||
});
|
||||
|
||||
it('should handle mailto', function () {
|
||||
expect(errorLinkFilter("mailto:me@example.com")).
|
||||
toBe('<a href="mailto:me@example.com">me@example.com</a>');
|
||||
expect(errorLinkFilter("me@example.com")).
|
||||
toBe('<a href="mailto:me@example.com">me@example.com</a>');
|
||||
expect(errorLinkFilter("send email to me@example.com, but")).
|
||||
toBe('send email to <a href="mailto:me@example.com">me@example.com</a>, but');
|
||||
});
|
||||
|
||||
it('should handle target', function () {
|
||||
expect(errorLinkFilter("http://example.com", "_blank")).
|
||||
toBe('<a target="_blank" href="http://example.com">http://example.com</a>')
|
||||
expect(errorLinkFilter("http://example.com", "someNamedIFrame")).
|
||||
toBe('<a target="someNamedIFrame" href="http://example.com">http://example.com</a>')
|
||||
});
|
||||
|
||||
it('should not linkify stack trace URLs', function () {
|
||||
expect(errorLinkFilter("http://example.com/angular.min.js:42:1337")).
|
||||
toBe("http://example.com/angular.min.js:42:1337");
|
||||
});
|
||||
|
||||
it('should truncate linked URLs at 60 characters', function () {
|
||||
expect(errorLinkFilter("http://errors.angularjs.org/very-long-version-string/$injector/nomod?p0=myApp")).
|
||||
toBe('<a href="http://errors.angularjs.org/very-long-version-string/$injector/nomod?p0=myApp">' +
|
||||
'http://errors.angularjs.org/very-long-version-string/$inj...</a>');
|
||||
});
|
||||
});
|
||||
@@ -1,32 +0,0 @@
|
||||
// Copy/pasted from src/Angular.js, so that we can disable specific tests on IE.
|
||||
var msie = parseInt((/msie (\d+)/.exec(navigator.userAgent.toLowerCase()) || [])[1], 10);
|
||||
|
||||
var createMockWindow = function() {
|
||||
var mockWindow = {};
|
||||
var setTimeoutQueue = [];
|
||||
|
||||
mockWindow.location = window.location;
|
||||
mockWindow.document = window.document;
|
||||
mockWindow.getComputedStyle = angular.bind(window, window.getComputedStyle);
|
||||
mockWindow.scrollTo = angular.bind(window, window.scrollTo);
|
||||
mockWindow.navigator = window.navigator;
|
||||
mockWindow.setTimeout = function(fn, delay) {
|
||||
setTimeoutQueue.push({fn: fn, delay: delay});
|
||||
};
|
||||
mockWindow.setTimeout.queue = setTimeoutQueue;
|
||||
mockWindow.setTimeout.expect = function(delay) {
|
||||
if (setTimeoutQueue.length > 0) {
|
||||
return {
|
||||
process: function() {
|
||||
var tick = setTimeoutQueue.shift();
|
||||
expect(tick.delay).toEqual(delay);
|
||||
tick.fn();
|
||||
}
|
||||
};
|
||||
} else {
|
||||
expect('SetTimoutQueue empty. Expecting delay of ').toEqual(delay);
|
||||
}
|
||||
};
|
||||
|
||||
return mockWindow;
|
||||
};
|
||||
@@ -1,50 +0,0 @@
|
||||
describe('Docs Syntax', function() {
|
||||
|
||||
beforeEach(module('bootstrap'));
|
||||
|
||||
describe('syntax', function() {
|
||||
|
||||
var id, element, document;
|
||||
|
||||
beforeEach(inject(function($compile, $rootScope, $document) {
|
||||
document = $document[0];
|
||||
//create the HTML elements missing in IE8 for this directive
|
||||
document.createElement('nav');
|
||||
|
||||
element = angular.element(
|
||||
'<div>' +
|
||||
'<pre syntax ' +
|
||||
'syntax-github="gh-url" ' +
|
||||
'syntax-plunkr="pl-url" ' +
|
||||
'syntax-fiddle="jf-url">' +
|
||||
'</pre>' +
|
||||
'</div>'
|
||||
);
|
||||
$compile(element)($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
element = element[0];
|
||||
document.body.appendChild(element);
|
||||
}));
|
||||
|
||||
it("should properly prepare a github link in the page", function() {
|
||||
var github = element.querySelector('.syntax-github');
|
||||
expect(github.innerHTML).toMatch(/View on Github/i);
|
||||
expect(github.getAttribute('href')).toBe('gh-url');
|
||||
});
|
||||
|
||||
it("should properly prepare a plunkr link in the page", function() {
|
||||
var plunkr = element.querySelector('.syntax-plunkr');
|
||||
expect(plunkr.innerHTML).toMatch(/View on Plunkr/i);
|
||||
expect(plunkr.getAttribute('href')).toBe('pl-url');
|
||||
});
|
||||
|
||||
it("should properly prepare a jsfiddle link in the page", function() {
|
||||
var jsfiddle = element.querySelector('.syntax-jsfiddle');
|
||||
expect(jsfiddle.innerHTML).toMatch(/View on JSFiddle/i);
|
||||
expect(jsfiddle.getAttribute('href')).toBe('jf-url');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
@@ -1,33 +0,0 @@
|
||||
describe('DocsApp', function() {
|
||||
|
||||
// Do not run this suite on Internet Explorer.
|
||||
if (msie < 10) return;
|
||||
|
||||
beforeEach(module('docsApp'));
|
||||
|
||||
describe('DocsVersionsCtrl', function() {
|
||||
var $scope, ctrl, window, version = '9.8.7';
|
||||
|
||||
beforeEach(function() {
|
||||
module(function($provide) {
|
||||
$provide.value('$window', window = createMockWindow());
|
||||
});
|
||||
inject(function($controller, $rootScope) {
|
||||
$scope = $rootScope.$new();
|
||||
$scope.version = version;
|
||||
ctrl = $controller('DocsVersionsCtrl',{
|
||||
$scope : $scope,
|
||||
$window : window
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('changing the URL', function() {
|
||||
it('should jump to the url provided', function() {
|
||||
$scope.jumpToDocsVersion({ version: '1.0.1', url : 'page123'});
|
||||
expect(window.location).toBe('page123');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
-392
@@ -1,392 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var directive = {};
|
||||
|
||||
directive.dropdownToggle =
|
||||
['$document', '$location', '$window',
|
||||
function ($document, $location, $window) {
|
||||
var openElement = null, close;
|
||||
return {
|
||||
restrict: 'C',
|
||||
link: function(scope, element, attrs) {
|
||||
scope.$watch(function dropdownTogglePathWatch(){return $location.path();}, function dropdownTogglePathWatchAction() {
|
||||
close && close();
|
||||
});
|
||||
|
||||
element.parent().on('click', function(event) {
|
||||
close && close();
|
||||
});
|
||||
|
||||
element.on('click', function(event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
var iWasOpen = false;
|
||||
|
||||
if (openElement) {
|
||||
iWasOpen = openElement === element;
|
||||
close();
|
||||
}
|
||||
|
||||
if (!iWasOpen){
|
||||
element.parent().addClass('open');
|
||||
openElement = element;
|
||||
|
||||
close = function (event) {
|
||||
event && event.preventDefault();
|
||||
event && event.stopPropagation();
|
||||
$document.off('click', close);
|
||||
element.parent().removeClass('open');
|
||||
close = null;
|
||||
openElement = null;
|
||||
}
|
||||
|
||||
$document.on('click', close);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}];
|
||||
|
||||
directive.syntax = function() {
|
||||
return {
|
||||
restrict: 'A',
|
||||
link: function(scope, element, attrs) {
|
||||
function makeLink(type, text, link, icon) {
|
||||
return '<a href="' + link + '" class="btn syntax-' + type + '" target="_blank" rel="nofollow">' +
|
||||
'<span class="' + icon + '"></span> ' + text +
|
||||
'</a>';
|
||||
};
|
||||
|
||||
var html = '';
|
||||
var types = {
|
||||
'github' : {
|
||||
text : 'View on Github',
|
||||
key : 'syntaxGithub',
|
||||
icon : 'icon-github'
|
||||
},
|
||||
'plunkr' : {
|
||||
text : 'View on Plunkr',
|
||||
key : 'syntaxPlunkr',
|
||||
icon : 'icon-arrow-down'
|
||||
},
|
||||
'jsfiddle' : {
|
||||
text : 'View on JSFiddle',
|
||||
key : 'syntaxFiddle',
|
||||
icon : 'icon-cloud'
|
||||
}
|
||||
};
|
||||
for(var type in types) {
|
||||
var data = types[type];
|
||||
var link = attrs[data.key];
|
||||
if(link) {
|
||||
html += makeLink(type, data.text, link, data.icon);
|
||||
}
|
||||
};
|
||||
|
||||
var nav = document.createElement('nav');
|
||||
nav.className = 'syntax-links';
|
||||
nav.innerHTML = html;
|
||||
|
||||
var node = element[0];
|
||||
var par = node.parentNode;
|
||||
par.insertBefore(nav, node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
directive.tabbable = function() {
|
||||
return {
|
||||
restrict: 'C',
|
||||
compile: function(element) {
|
||||
var navTabs = angular.element('<ul class="nav nav-tabs"></ul>'),
|
||||
tabContent = angular.element('<div class="tab-content"></div>');
|
||||
|
||||
tabContent.append(element.contents());
|
||||
element.append(navTabs).append(tabContent);
|
||||
},
|
||||
controller: ['$scope', '$element', function($scope, $element) {
|
||||
var navTabs = $element.contents().eq(0),
|
||||
ngModel = $element.controller('ngModel') || {},
|
||||
tabs = [],
|
||||
selectedTab;
|
||||
|
||||
ngModel.$render = function() {
|
||||
var $viewValue = this.$viewValue;
|
||||
|
||||
if (selectedTab ? (selectedTab.value != $viewValue) : $viewValue) {
|
||||
if(selectedTab) {
|
||||
selectedTab.paneElement.removeClass('active');
|
||||
selectedTab.tabElement.removeClass('active');
|
||||
selectedTab = null;
|
||||
}
|
||||
if($viewValue) {
|
||||
for(var i = 0, ii = tabs.length; i < ii; i++) {
|
||||
if ($viewValue == tabs[i].value) {
|
||||
selectedTab = tabs[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (selectedTab) {
|
||||
selectedTab.paneElement.addClass('active');
|
||||
selectedTab.tabElement.addClass('active');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
this.addPane = function(element, attr) {
|
||||
var li = angular.element('<li><a href></a></li>'),
|
||||
a = li.find('a'),
|
||||
tab = {
|
||||
paneElement: element,
|
||||
paneAttrs: attr,
|
||||
tabElement: li
|
||||
};
|
||||
|
||||
tabs.push(tab);
|
||||
|
||||
attr.$observe('value', update)();
|
||||
attr.$observe('title', function(){ update(); a.text(tab.title); })();
|
||||
|
||||
function update() {
|
||||
tab.title = attr.title;
|
||||
tab.value = attr.value || attr.title;
|
||||
if (!ngModel.$setViewValue && (!ngModel.$viewValue || tab == selectedTab)) {
|
||||
// we are not part of angular
|
||||
ngModel.$viewValue = tab.value;
|
||||
}
|
||||
ngModel.$render();
|
||||
}
|
||||
|
||||
navTabs.append(li);
|
||||
li.on('click', function(event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
if (ngModel.$setViewValue) {
|
||||
$scope.$apply(function() {
|
||||
ngModel.$setViewValue(tab.value);
|
||||
ngModel.$render();
|
||||
});
|
||||
} else {
|
||||
// we are not part of angular
|
||||
ngModel.$viewValue = tab.value;
|
||||
ngModel.$render();
|
||||
}
|
||||
});
|
||||
|
||||
return function() {
|
||||
tab.tabElement.remove();
|
||||
for(var i = 0, ii = tabs.length; i < ii; i++ ) {
|
||||
if (tab == tabs[i]) {
|
||||
tabs.splice(i, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}]
|
||||
};
|
||||
};
|
||||
|
||||
directive.table = function() {
|
||||
return {
|
||||
restrict: 'E',
|
||||
link: function(scope, element, attrs) {
|
||||
if (!attrs['class']) {
|
||||
element.addClass('table table-bordered table-striped code-table');
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
var popoverElement = function() {
|
||||
var object = {
|
||||
init : function() {
|
||||
this.element = angular.element(
|
||||
'<div class="popover popover-incode top">' +
|
||||
'<div class="arrow"></div>' +
|
||||
'<div class="popover-inner">' +
|
||||
'<div class="popover-title"><code></code></div>' +
|
||||
'<div class="popover-content"></div>' +
|
||||
'</div>' +
|
||||
'</div>'
|
||||
);
|
||||
this.node = this.element[0];
|
||||
this.element.css({
|
||||
'display':'block',
|
||||
'position':'absolute'
|
||||
});
|
||||
angular.element(document.body).append(this.element);
|
||||
|
||||
var inner = this.element.children()[1];
|
||||
this.titleElement = angular.element(inner.childNodes[0].firstChild);
|
||||
this.contentElement = angular.element(inner.childNodes[1]);
|
||||
|
||||
//stop the click on the tooltip
|
||||
this.element.bind('click', function(event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
});
|
||||
|
||||
var self = this;
|
||||
angular.element(document.body).bind('click',function(event) {
|
||||
if(self.visible()) self.hide();
|
||||
});
|
||||
},
|
||||
|
||||
show : function(x,y) {
|
||||
this.element.addClass('visible');
|
||||
this.position(x || 0, y || 0);
|
||||
},
|
||||
|
||||
hide : function() {
|
||||
this.element.removeClass('visible');
|
||||
this.position(-9999,-9999);
|
||||
},
|
||||
|
||||
visible : function() {
|
||||
return this.position().y >= 0;
|
||||
},
|
||||
|
||||
isSituatedAt : function(element) {
|
||||
return this.besideElement ? element[0] == this.besideElement[0] : false;
|
||||
},
|
||||
|
||||
title : function(value) {
|
||||
return this.titleElement.html(value);
|
||||
},
|
||||
|
||||
content : function(value) {
|
||||
if(value && value.length > 0) {
|
||||
value = marked(value);
|
||||
}
|
||||
return this.contentElement.html(value);
|
||||
},
|
||||
|
||||
positionArrow : function(position) {
|
||||
this.node.className = 'popover ' + position;
|
||||
},
|
||||
|
||||
positionAway : function() {
|
||||
this.besideElement = null;
|
||||
this.hide();
|
||||
},
|
||||
|
||||
positionBeside : function(element) {
|
||||
this.besideElement = element;
|
||||
|
||||
var elm = element[0];
|
||||
var x = elm.offsetLeft;
|
||||
var y = elm.offsetTop;
|
||||
x -= 30;
|
||||
y -= this.node.offsetHeight + 10;
|
||||
this.show(x,y);
|
||||
},
|
||||
|
||||
position : function(x,y) {
|
||||
if(x != null && y != null) {
|
||||
this.element.css('left',x + 'px');
|
||||
this.element.css('top', y + 'px');
|
||||
}
|
||||
else {
|
||||
return {
|
||||
x : this.node.offsetLeft,
|
||||
y : this.node.offsetTop
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
object.init();
|
||||
object.hide();
|
||||
|
||||
return object;
|
||||
};
|
||||
|
||||
directive.popover = ['popoverElement', function(popover) {
|
||||
return {
|
||||
restrict: 'A',
|
||||
priority : 500,
|
||||
link: function(scope, element, attrs) {
|
||||
element.bind('click',function(event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
if(popover.isSituatedAt(element) && popover.visible()) {
|
||||
popover.title('');
|
||||
popover.content('');
|
||||
popover.positionAway();
|
||||
}
|
||||
else {
|
||||
popover.title(attrs.title);
|
||||
popover.content(attrs.content);
|
||||
popover.positionBeside(element);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}];
|
||||
|
||||
directive.tabPane = function() {
|
||||
return {
|
||||
require: '^tabbable',
|
||||
restrict: 'C',
|
||||
link: function(scope, element, attrs, tabsCtrl) {
|
||||
element.on('$remove', tabsCtrl.addPane(element, attrs));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
directive.foldout = ['$http', '$animate','$window', function($http, $animate, $window) {
|
||||
return {
|
||||
restrict: 'A',
|
||||
priority : 500,
|
||||
link: function(scope, element, attrs) {
|
||||
var container, loading, url = attrs.url;
|
||||
if(/\/build\//.test($window.location.href)) {
|
||||
url = '/build/docs' + url;
|
||||
}
|
||||
element.bind('click',function() {
|
||||
scope.$apply(function() {
|
||||
if(!container) {
|
||||
if(loading) return;
|
||||
|
||||
loading = true;
|
||||
var par = element.parent();
|
||||
container = angular.element('<div class="foldout">loading...</div>');
|
||||
$animate.enter(container, null, par);
|
||||
|
||||
$http.get(url, { cache : true }).success(function(html) {
|
||||
loading = false;
|
||||
|
||||
html = '<div class="foldout-inner">' +
|
||||
'<div calss="foldout-arrow"></div>' +
|
||||
html +
|
||||
'</div>';
|
||||
container.html(html);
|
||||
|
||||
//avoid showing the element if the user has already closed it
|
||||
if(container.css('display') == 'block') {
|
||||
container.css('display','none');
|
||||
$animate.addClass(container, 'ng-hide');
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
container.hasClass('ng-hide') ? $animate.removeClass(container, 'ng-hide') : $animate.addClass(container, 'ng-hide');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}];
|
||||
|
||||
angular.module('bootstrap', [])
|
||||
.directive(directive)
|
||||
.factory('popoverElement', popoverElement)
|
||||
.run(function() {
|
||||
marked.setOptions({
|
||||
gfm: true,
|
||||
tables: true
|
||||
});
|
||||
});
|
||||
@@ -2,297 +2,6 @@
|
||||
@name API Reference
|
||||
@description
|
||||
|
||||
# AngularJS API Docs
|
||||
Welcome to the AngularJS API docs page. These pages contain the AngularJS reference materials for version <strong ng-bind="version"></strong>.
|
||||
|
||||
The documentation is organized into **modules** which contain various components of an AngularJS application.
|
||||
These components are directives, services, filters, providers, types, global APIs and testing mocks.
|
||||
|
||||
<div class="alert alert-info">
|
||||
**Angular Namespaces `$` and `$$`**
|
||||
|
||||
To prevent accidental name collisions with your code,
|
||||
Angular prefixes names of public objects with `$` and names of private objects with `$$`.
|
||||
Please do not use the `$` or `$$` prefix in your code.
|
||||
</div>
|
||||
|
||||
## Angular Namespace
|
||||
|
||||
|
||||
## {@link ng ng (core module)}
|
||||
This module is provided by default and contains the core components of AngularJS.
|
||||
|
||||
<table class="definition-table spaced">
|
||||
<tr>
|
||||
<td>{@link ng#directive Directives}</td>
|
||||
<td>
|
||||
<p>
|
||||
This is the core collection of directives you would use in your template code to build an AngularJS application.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Some examples include:
|
||||
{@link ng.directive:ngClick ngClick},
|
||||
{@link ng.directive:ngInclude ngInclude},
|
||||
{@link ng.directive:ngRepeat ngRepeat},
|
||||
etc… <br />
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
{@link ng#service Services / Factories}
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
This is the core collection of services which are used within the DI of your application.
|
||||
</p>
|
||||
<p>
|
||||
Some examples include:
|
||||
{@link ng.$compile $compile},
|
||||
{@link ng.$http $http},
|
||||
{@link ngRoute.$routeParams $routeParams},
|
||||
{@link ng.$location $location},
|
||||
etc…
|
||||
<p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
{@link ng#filter Filters}
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
The core filters available in the ng module are used to transform template data before it is renders within directives and expressions.
|
||||
</p>
|
||||
<p>
|
||||
Some examples include:
|
||||
{@link ng.filter:filter filter},
|
||||
{@link ng.filter:date date},
|
||||
{@link ng.filter:currency currency},
|
||||
{@link ng.filter:lowercase lowercase},
|
||||
{@link ng.filter:uppercase uppercase},
|
||||
etc...
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
{@link ng#function Global APIs}
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
The core global API functions are attached to the angular object. These core functions are useful for low level JavaScript operations within your application.
|
||||
</p>
|
||||
<p>
|
||||
Some examples include:
|
||||
{@link angular.copy angular.copy()},
|
||||
{@link angular.equals angular.equals()},
|
||||
{@link angular.element angular.element()},
|
||||
etc...
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
## {@link ngRoute ngRoute}
|
||||
|
||||
Use ngRoute to enable URL routing to your application. The ngRoute module supports URL management via both hashbang and HTML5 pushState.
|
||||
|
||||
<div class="alert alert-info">Include the **angular-route.js** file and set **ngRoute** as a dependency for this to work in your application.</div>
|
||||
|
||||
<table class="definition-table spaced">
|
||||
<tr>
|
||||
<td>
|
||||
{@link ngRoute#service Services / Factories}
|
||||
</td>
|
||||
<td>
|
||||
The following services are used for route management:
|
||||
<ul>
|
||||
<li>{@link ngRoute.$routeParams $routeParams} is used to access the querystring values present in the URL.</li>
|
||||
<li>{@link ngRoute.$route $route} is used to access the details of the route that is currently being accessed.</li>
|
||||
<li>{@link ngRoute.$routeProvider $routeProvider} is used to register routes for the application.</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
{@link ngRoute#directive Directives}
|
||||
</td>
|
||||
<td>
|
||||
The {@link ngRoute.directive:ngView ngView} directive will display the template of the current route within the page.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
## {@link ngAnimate ngAnimate}
|
||||
|
||||
Use ngAnimate to enable animation features into your application. Various core ng directives will provide
|
||||
animation hooks into your application when ngAnimate is included. Animations are defined by using CSS transitions/animations
|
||||
or JavaScript callbacks.
|
||||
|
||||
<div class="alert alert-info">Include the **angular-animate.js** file and set **ngAnimate** as a dependency for this to work in your application.</div>
|
||||
|
||||
<table class="definition-table spaced">
|
||||
<tr>
|
||||
<td>
|
||||
{@link ngAnimate#service Services / Factories}
|
||||
</td>
|
||||
<td>
|
||||
Use {@link ngAnimate.$animate $animate} to trigger animation operations within your directive code.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
{@link ngAnimate CSS-based animations}
|
||||
</td>
|
||||
<td>
|
||||
Follow ngAnimate’s CSS naming structure to reference CSS transitions / keyframe animations in AngularJS. Once defined the animation can be triggered by referencing the CSS class within the HTML template code.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
{@link ngAnimate JS-based animations}
|
||||
</td>
|
||||
<td>
|
||||
Use {@link angular.Module#methods_animation module.animation()} to register a JavaScript animation. Once registered the animation can be triggered by referencing the CSS class within the HTML template code.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
## {@link ngResource ngResource}
|
||||
|
||||
Use the ngResource module when querying and posting data to a REST API.
|
||||
|
||||
<div class="alert alert-info">Include the **angular-resource.js** file and set **ngResource** as a dependency for this to work in your application.</div>
|
||||
|
||||
<table class="definition-table spaced">
|
||||
<tr>
|
||||
<td>
|
||||
{@link ngResource#service Services / Factories}
|
||||
</td>
|
||||
<td>
|
||||
The {@link ngResource.$resource $resource} service is used to define RESTful objects which communicate with a REST API.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
## {@link ngCookies ngCookies}
|
||||
|
||||
Use the ngCookies module to handle cookie management within your application.
|
||||
|
||||
<div class="alert alert-info">Include the **angular-cookies.js** file and set **ngCookies** as a dependency for this to work in your application.</div>
|
||||
|
||||
<table class="definition-table spaced">
|
||||
<tr>
|
||||
<td>
|
||||
{@link ngCookies#service Services / Factories}
|
||||
</td>
|
||||
<td>
|
||||
The following services are used for cookie management:
|
||||
<ul>
|
||||
<li>The {@link ngCookies.$cookies $cookie} service is a convenient wrapper to store simple data within browser cookies.</li>
|
||||
<li>{@link ngCookies.$cookieStore $cookieStore} is used to store more complex data using serialization.</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
## {@link ngTouch ngTouch}
|
||||
|
||||
Use ngTouch when developing for mobile browsers/devices.
|
||||
|
||||
<div class="alert alert-info">Include the **angular-touch.js** file and set **ngTouch** as a dependency for this to work in your application.</div>
|
||||
|
||||
<table class="definition-table spaced">
|
||||
<tr>
|
||||
<td>
|
||||
{@link ngTouch#service Services / Factories}
|
||||
</td>
|
||||
<td>
|
||||
The {@link ngTouch.$swipe $swipe} service is used to register and manage mobile DOM events.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
{@link ngTouch#directive Directives}
|
||||
</td>
|
||||
<td>
|
||||
Various directives are available in ngTouch to emulate mobile DOM events.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
## {@link ngSanitize ngSanitize}
|
||||
|
||||
Use ngSanitize to securely parse and manipulate HTML data in your application.
|
||||
|
||||
<div class="alert alert-info">Include the **angular-sanitize.js** file and set **ngSanitize** as a dependency for this to work in your application.</div>
|
||||
|
||||
<table class="definition-table spaced">
|
||||
<tr>
|
||||
<td>
|
||||
{@link ngSanitize#service Services / Factories}
|
||||
</td>
|
||||
<td>
|
||||
The {@link ngSanitize.$sanitize $sanitize} service is used to clean up dangerous HTML code in a quick and convenient way.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
{@link ngTouch#filter Filters}
|
||||
</td>
|
||||
<td>
|
||||
The {@link ngSanitize.filter:linky linky filter} is used to turn URLs into HTML links within the provided string.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
## {@link ngMock ngMock}
|
||||
|
||||
Use ngMock to inject and mock modules, factories, services and providers within your unit tests
|
||||
|
||||
<div class="alert alert-info">Include the **angular-mocks.js** file into your test runner for this to work.</div>
|
||||
|
||||
<table class="definition-table spaced">
|
||||
<tr>
|
||||
<td>
|
||||
{@link ngMock#service Services / Factories}
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
ngMock will extend the behavior of various core services to become testing aware and manageable in a synchronous manner.
|
||||
<p>
|
||||
|
||||
<p>
|
||||
Some examples include:
|
||||
{@link ngMock.$timeout $timeout},
|
||||
{@link ngMock.$interval $interval},
|
||||
{@link ngMock.$log $log},
|
||||
{@link ngMock.$httpBackend $httpBackend},
|
||||
etc...
|
||||
<p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
{@link ngMock#function Global APIs}
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
Various helper functions are available to inject and mock modules within unit test code.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Some examples
|
||||
{@link angular.mock.inject inject()},
|
||||
{@link angular.mock.module module()},
|
||||
{@link angular.mock.dump dump()},
|
||||
etc...
|
||||
<p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
Use the API Reference documentation when you need more information about a specific feature. Check out
|
||||
{@link guide/ Developer Guide} for AngularJS concepts. If you are new to AngularJS we recommend the
|
||||
{@link tutorial/ Tutorial}.
|
||||
|
||||
@@ -2,7 +2,4 @@
|
||||
@name ng
|
||||
@description
|
||||
|
||||
# ng (core module)
|
||||
The ng module is loaded by default when an AngularJS application is started. The module itself contains the essential components to for an AngularJS application to function. The table below lists a high level breakdown of each of the services/factories, filters, directives and testing components available within this core module.
|
||||
|
||||
<div doc-module-components="ng"></div>
|
||||
The `ng` is an angular module which contains all of the core angular services.
|
||||
|
||||
@@ -38,8 +38,13 @@ detection, and preventing invalid form submission.
|
||||
$scope.form.contacts.push({type:'', value:''});
|
||||
};
|
||||
|
||||
$scope.removeContact = function(index) {
|
||||
$scope.form.contacts.splice(index, 1);
|
||||
$scope.removeContact = function(contact) {
|
||||
var contacts = $scope.form.contacts;
|
||||
for (var i = 0, ii = contacts.length; i < ii; i++) {
|
||||
if (contact === contacts[i]) {
|
||||
contacts.splice(i, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$scope.isCancelDisabled = function() {
|
||||
@@ -78,7 +83,7 @@ detection, and preventing invalid form submission.
|
||||
<option>IM</option>
|
||||
</select>
|
||||
<input type="text" ng-model="contact.value" required/>
|
||||
[ <a href="" ng-click="removeContact($index)">X</a> ]
|
||||
[ <a href="" ng-click="removeContact(contact)">X</a> ]
|
||||
</div>
|
||||
<button ng-click="cancel()" ng-disabled="isCancelDisabled()">Cancel</button>
|
||||
<button ng-click="save()" ng-disabled="isSaveDisabled()">Save</button>
|
||||
|
||||
@@ -30,9 +30,9 @@ In this example we have a simple app which consist of two screens:
|
||||
* Welcome: url `welcome` Show the user contact information.
|
||||
* Settings: url `settings` Show an edit screen for user contact information.
|
||||
|
||||
<example module="deepLinking" deps="angular-route.js, angular-sanitize.js">
|
||||
<example module="deepLinking" deps="angular-sanitize.js">
|
||||
<file name="script.js">
|
||||
angular.module('deepLinking', ['ngRoute', 'ngSanitize'])
|
||||
angular.module('deepLinking', ['ngSanitize'])
|
||||
.config(function($routeProvider) {
|
||||
$routeProvider.
|
||||
when("/welcome", {templateUrl:'welcome.html', controller:WelcomeCntl}).
|
||||
@@ -141,11 +141,11 @@ In this example we have a simple app which consist of two screens:
|
||||
# Things to notice
|
||||
|
||||
* Routes are defined in the `AppCntl` class. The initialization of the controller causes the
|
||||
initialization of the {@link api/ngRoute.$route $route} service with the proper URL
|
||||
initialization of the {@link api/ng.$route $route} service with the proper URL
|
||||
routes.
|
||||
* The {@link api/ngRoute.$route $route} service then watches the URL and instantiates the
|
||||
* The {@link api/ng.$route $route} service then watches the URL and instantiates the
|
||||
appropriate controller when the URL changes.
|
||||
* The {@link api/ngRoute.directive:ngView ngView} widget loads the
|
||||
* The {@link api/ng.directive:ngView ngView} widget loads the
|
||||
view when the URL changes. It also sets the view scope to the newly instantiated controller.
|
||||
* Changing the URL is sufficient to change the controller and view. It makes no difference whether
|
||||
the URL is changed programmatically or by the user.
|
||||
the URL is changed programatically or by the user.
|
||||
|
||||
@@ -34,6 +34,6 @@ Take a look through the source and note:
|
||||
* There is no need for listener registration and event firing on change events.
|
||||
* The implicit presence of the `name` variable which is in the root {@link api/ng.$rootScope.Scope scope}.
|
||||
* The double curly brace `{{markup}}`, which binds the name variable to the greeting text.
|
||||
* The concept of {@link guide/databinding data binding}, which reflects any
|
||||
* The concept of {@link guide/dev_guide.templates.databinding data binding}, which reflects any
|
||||
changes to the
|
||||
input field in the greeting text.
|
||||
|
||||
@@ -85,8 +85,8 @@ view.
|
||||
Next Player: {{nextMove}}
|
||||
<div class="winner" ng-show="winner">Player {{winner}} has won!</div>
|
||||
<table class="board">
|
||||
<tr ng-repeat="row in board track by $index" style="height:15px;">
|
||||
<td ng-repeat="cell in row track by $index" ng-style="cellStyle"
|
||||
<tr ng-repeat="row in board" style="height:15px;">
|
||||
<td ng-repeat="cell in row" ng-style="cellStyle"
|
||||
ng-click="dropPiece($parent.$index, $index)">{{cell}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
@@ -125,4 +125,4 @@ board variable.
|
||||
* The view can call any controller function.
|
||||
* In this example, the `setUrl()` and `readUrl()` functions copy the game state to/from the URL's
|
||||
hash so the browser's back button will undo game steps. See deep-linking. This example calls {@link
|
||||
api/ng.$rootScope.Scope#methods_$watch $watch()} to set up a listener that invokes `readUrl()` when needed.
|
||||
api/ng.$rootScope.Scope#$watch $watch()} to set up a listener that invokes `readUrl()` when needed.
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $animate:notcsel
|
||||
@fullName Not class CSS selector
|
||||
@description
|
||||
|
||||
Expecting a CSS selector for class. Class selectors must start with `.`, for example: `.my-class-name`.
|
||||
@@ -1,8 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $cacheFactory:iid
|
||||
@fullName Invalid ID
|
||||
@description
|
||||
|
||||
This error occurs when trying to create a new `cache` object via {@link api/ng.$cacheFactory} with an ID that was already used to create another cache object.
|
||||
|
||||
To resolve the error please use a different cache ID when calling `$cacheFactory`.
|
||||
@@ -1,49 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $compile:ctreq
|
||||
@fullName Missing Required Controller
|
||||
@description
|
||||
|
||||
This error occurs when {@link api/ng.$compile HTML compiler} tries to process a directive that specifies the {@link api/ng.$compile#description_comprehensive-directive-api_directive-definition-object `require` option} in a {@link api/ng.$compile#description_comprehensive-directive-api directive definition},
|
||||
but the required directive controller is not present on the current DOM element (or its ancestor element, if `^` was specified).
|
||||
|
||||
To resolve this error ensure that there is no typo in the required controller name and that the required directive controller is present on the current element.
|
||||
|
||||
If the required controller is expected to be on a ancestor element, make ensure that you prefix the controller name in the `require` definition with `^`.
|
||||
|
||||
If the required controller is optionally requested, use `?` or `^?` to specify that.
|
||||
|
||||
|
||||
Example of a directive that requires {@link api/ng.directive:ngModel ngModel} controller:
|
||||
```
|
||||
myApp.directive('myDirective', function() {
|
||||
return {
|
||||
require: 'ngModel',
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This directive can then be used as:
|
||||
```
|
||||
<input ng-model="some.path" my-directive>
|
||||
```
|
||||
|
||||
|
||||
Example of a directive that optionally requires a {@link api/ng.directive:form form} controller from an ancestor:
|
||||
```
|
||||
myApp.directive('myDirective', function() {
|
||||
return {
|
||||
require: '^?form',
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This directive can then be used as:
|
||||
```
|
||||
<form name="myForm">
|
||||
<div>
|
||||
<span my-directive></span>
|
||||
</div>
|
||||
</form>
|
||||
```
|
||||
@@ -1,25 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $compile:iscp
|
||||
@fullName Invalid Isolate Scope Definition
|
||||
@description
|
||||
|
||||
When declaring isolate scope the scope definition object must be in specific format which starts with mode character (`@&=`) with an optional local name.
|
||||
|
||||
```
|
||||
myModule.directive('directiveName', function factory() {
|
||||
return {
|
||||
...
|
||||
scope: {
|
||||
'attrName': '@', // OK
|
||||
'attrName2': '=localName', // OK
|
||||
'attrName3': 'name', // ERROR: missing mode @&=
|
||||
'attrName4': ' = name', // ERROR: extra spaces
|
||||
'attrName5': 'name=', // ERROR: must be prefixed with @&=
|
||||
}
|
||||
...
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Please refer to the {@link api/ng.$compile#description_comprehensive-directive-api_directive-definition-object
|
||||
`scope` option} of the directive definition documentation to learn more about the API.
|
||||
@@ -1,17 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $compile:multidir
|
||||
@fullName Multiple Directive Resource Contention
|
||||
@description
|
||||
|
||||
This error occurs when multiple directives are applied to the same DOM element, and
|
||||
processing them would result in a collision or an unsupported configuration.
|
||||
|
||||
|
||||
To resolve this issue remove one of the directives which is causing the collision.
|
||||
|
||||
Example scenarios of multiple incompatible directives applied to the same element include:
|
||||
|
||||
* Multiple directives requesting `isolated scope`.
|
||||
* Multiple directives publishing a controller under the same name.
|
||||
* Multiple directives declared with the `transclusion` option.
|
||||
* Multiple directives attempting to define a `template` or `templateURL`.
|
||||
@@ -1,20 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $compile:nodomevents
|
||||
@fullName Interpolated Event Attributes
|
||||
@description
|
||||
|
||||
This error occurs when one tries to create a binding for event handler attributes like `onclick`, `onload`, `onsubmit`, etc.
|
||||
|
||||
There is no practical value in binding to these attributes and doing so only exposes your application to security vulnerabilities like XSS.
|
||||
For these reasons binding to event handler attributes (all attributes that start with `on` and `formaction` attribute) is not supported.
|
||||
|
||||
|
||||
An example code that would allow XSS vulnerability by evaluating user input in the window context could look like this:
|
||||
```
|
||||
<input ng-mode="username">
|
||||
<div onclick="{{username}}">click me</div>
|
||||
```
|
||||
|
||||
Since the `onclick` evaluates the value as JavaScript code in the window context, setting the `username` model to a value like `javascript:alert('PWND')` would result in script injection when the `div` is clicked.
|
||||
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $compile:nonassign
|
||||
@fullName Non-Assignable Expression
|
||||
@description
|
||||
|
||||
This error occurs when a directive defines an isolate scope property
|
||||
(using the `=` mode in the {@link api/ng.$compile#description_comprehensive-directive-api_directive-definition-object
|
||||
`scope` option} of a directive definition) but the directive is used with an expression that is not-assignable.
|
||||
|
||||
In order for the two-way data-binding to work, it must be possible to write new values back into the path defined with the expression.
|
||||
|
||||
For example, given a directive:
|
||||
|
||||
```
|
||||
myModule.directive('myDirective', function factory() {
|
||||
return {
|
||||
...
|
||||
scope: {
|
||||
'bind': '=localValue'
|
||||
}
|
||||
...
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Following are invalid uses of this directive:
|
||||
```
|
||||
<!-- ERROR because `1+2=localValue` is an invalid statement -->
|
||||
<my-directive bind="1+2">
|
||||
|
||||
<!-- ERROR because `myFn()=localValue` is an invalid statement -->
|
||||
<my-directive bind="myFn()">
|
||||
```
|
||||
|
||||
|
||||
To resolve this error, always use path expressions with scope properties that are two-way data-bound:
|
||||
```
|
||||
<my-directive bind="some.property">
|
||||
<my-directive bind="some[3]['property']">
|
||||
```
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $compile:selmulti
|
||||
@fullName Binding to Multiple Attribute
|
||||
@description
|
||||
|
||||
Binding to the `multiple` attribute of `select` element is not supported since switching between multiple and single mode changes the {@link api/ng.directive:ngModel `ngModel`} object type from instance to array of instances which breaks the model semantics.
|
||||
|
||||
If you need to use different types of `select` elements in your template based on some variable, please use {@link api/ng.directive:ngIf ngIf} or {@link api/ng.directive:ngSwitch ngSwitch} directives to select one of them to be used at runtime.
|
||||
|
||||
|
||||
Example with invalid usage:
|
||||
```
|
||||
<select ng-model="some.model" multiple="{{mode}}"></select>
|
||||
```
|
||||
|
||||
Example that uses ngIf to pick one of the `select` elements based on a variable:
|
||||
```
|
||||
<select ng-if="mode == 'multiple'" ng-model="some.model" multiple></select>
|
||||
<select ng-if="mode != 'multiple'" ng-model="some.model"></select>
|
||||
```
|
||||
@@ -1,11 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $compile:tpload
|
||||
@fullName Error Loading Template
|
||||
@description
|
||||
|
||||
This error occurs when {@link api/ng.$compile `$compile`} attempts to fetch a template from some URL, and the request fails.
|
||||
|
||||
To resolve this error, ensure that the URL of the template is spelled correctly and resolves to correct absolute URL.
|
||||
The [Chrome Developer Tools](https://developers.google.com/chrome-developer-tools/docs/network#network_panel_overview) might also be helpful in determining why the request failed.
|
||||
|
||||
If you are using {@link api/ng.$templateCache} to pre-load templates, ensure that the cache was populated with the template.
|
||||
@@ -1,39 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $compile:tplrt
|
||||
@fullName Invalid Template Root
|
||||
@description
|
||||
|
||||
When a directive is declared with `template` (or `templateUrl`) and `replace` mode on, the template
|
||||
must have exactly one root element. That is, the text of the template property or the content
|
||||
referenced by the templateUrl must be contained within a single html element.
|
||||
For example, `<p>blah <em>blah</em> blah</p>` instead of simply `blah <em>blah</em> blah`.
|
||||
Otherwise, the replacement operation would result in a single element (the directive) being replaced
|
||||
with multiple elements or nodes, which is unsupported and not commonly needed in practice.
|
||||
|
||||
|
||||
For example a directive with definition:
|
||||
|
||||
```
|
||||
myModule.directive('myDirective', function factory() {
|
||||
return {
|
||||
...
|
||||
replace: true,
|
||||
templateUrl: 'someUrl'
|
||||
...
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
And a template provided at URL `someUrl`. The template must be an html fragment that has only a
|
||||
single root element, like the `div` element in this template:
|
||||
|
||||
```
|
||||
<div><b>Hello</b> World!</div>
|
||||
```
|
||||
|
||||
An an invalid template to be used with this directive is one that defines multiple root nodes or
|
||||
elements. For example:
|
||||
|
||||
```
|
||||
<b>Hello</b> World!
|
||||
```
|
||||
@@ -1,34 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $compile:uterdir
|
||||
@fullName Unterminated Directive
|
||||
@description
|
||||
|
||||
This error occurs when using multi-element directives and a `directive-start` attribute fails to form a matching pair with a corresponding `directive-end` attribute.
|
||||
A `directive-start` should have a matching `directive-end` on a sibling node in the DOM. For instance,
|
||||
|
||||
```
|
||||
<table>
|
||||
<tr ng-repeat-start="item in list">I get repeated</tr>
|
||||
<tr ng-repeat-end>I also get repeated</tr>
|
||||
</table>
|
||||
```
|
||||
|
||||
is a valid example.
|
||||
|
||||
This error can occur in several different ways. One is by leaving out the `directive-end` attribute, like so:
|
||||
|
||||
```
|
||||
<div>
|
||||
<span foo-start></span>
|
||||
</div>
|
||||
```
|
||||
|
||||
Another is by nesting a `directive-end` inside of `directive-start`, or vice versa:
|
||||
|
||||
```
|
||||
<div>
|
||||
<span foo-start><span foo-end></span></span>
|
||||
</div>
|
||||
```
|
||||
|
||||
To avoid this error, make sure each `directive-start` you use has a matching `directive-end` on a sibling node in the DOM.
|
||||
@@ -1,21 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $controller:noscp
|
||||
@fullName Missing $scope object
|
||||
@description
|
||||
|
||||
This error occurs when {@link api/ng.$controller $controller} service is called in order to instantiate a new controller but no scope is provided via `$scope` property of the locals map.
|
||||
|
||||
Example of incorrect usage that leads to this error:
|
||||
```
|
||||
$controller(MyController);
|
||||
//or
|
||||
$controller(MyController, {scope: newScope});
|
||||
```
|
||||
|
||||
To fix the example above please provide a scope to the $controller call:
|
||||
|
||||
```
|
||||
$controller(MyController, {$scope, newScope});
|
||||
```
|
||||
|
||||
Please consult the {@link api/ng.$controller $controller} service api docs to learn more.
|
||||
@@ -1,9 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $httpBackend:noxhr
|
||||
@fullName Unsupported XHR
|
||||
@description
|
||||
|
||||
This error occurs in browsers that do not support XmlHttpRequest. AngularJS
|
||||
supports Safari, Chrome, Firefox, Opera, IE8 and higher, and mobile browsers
|
||||
(Android, Chrome Mobile, iOS Safari). To avoid this error, use an officially
|
||||
supported browser.
|
||||
@@ -1,13 +0,0 @@
|
||||
@ngdoc overview
|
||||
@name Error Reference
|
||||
@description
|
||||
|
||||
Use the Error Reference manual to find information about error conditions in
|
||||
your AngularJS app. Errors thrown in production builds of AngularJS will log
|
||||
links to this site on the console.
|
||||
|
||||
Other useful references for debugging your app include:
|
||||
|
||||
- {@link api/ API Reference} for detailed information about specific features
|
||||
- {@link guide/ Developer Guide} for AngularJS concepts
|
||||
- {@link tutorial/ Tutorial} for getting started
|
||||
@@ -1,26 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $injector:cdep
|
||||
@fullName Circular Dependency
|
||||
@description
|
||||
|
||||
This error occurs when the {@link api/angular.injector $injector} tries to get
|
||||
a service that depends on itself, either directly or indirectly. To fix this,
|
||||
construct your dependency chain such that there are no circular dependencies.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
angular.module('myApp', [])
|
||||
.factory('myService', function (myService) {
|
||||
// ...
|
||||
})
|
||||
.controller('MyCtrl', function ($scope, myService) {
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
When an instance of `MyCtrl` is created, the service `myService` will be created
|
||||
by the `$injector`. `myService` depends on itself, which causes the `$injector`
|
||||
to detect a circular dependency and throw the error.
|
||||
|
||||
For more information, see the {@link guide/di Dependency Injection Guide}.
|
||||
@@ -1,26 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $injector:itkn
|
||||
@fullName Bad Injection Token
|
||||
@description
|
||||
|
||||
This error occurs when using a bad token as a dependency injection annotation.
|
||||
Dependency injection annotation tokens should always be strings. Using any other
|
||||
type will cause this error to be thrown.
|
||||
|
||||
Examples of code with bad injection tokens include:
|
||||
|
||||
```
|
||||
var myCtrl = function ($scope, $http) { /* ... */ };
|
||||
myCtrl.$inject = ['$scope', 42];
|
||||
|
||||
myAppModule.controller('MyCtrl', ['$scope', {}, function ($scope, $timeout) {
|
||||
// ...
|
||||
}]);
|
||||
```
|
||||
|
||||
The bad injection tokens are `42` in the first example and `{}` in the second.
|
||||
To avoid the error, always use string literals for dependency injection annotation
|
||||
tokens.
|
||||
|
||||
For an explanation of what injection annotations are and how to use them, refer
|
||||
to the {@link guide/di Dependency Injection Guide}.
|
||||
@@ -1,11 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $injector:modulerr
|
||||
@fullName Module Error
|
||||
@description
|
||||
|
||||
This error occurs when a module fails to load due to some exception. The error
|
||||
message above should provide additional context.
|
||||
|
||||
In AngularJS `1.2.0` and later, `ngRoute` has been moved to its own module.
|
||||
If you are getting this error after upgrading to `1.2.x`, be sure that you've
|
||||
installed {@link api/ngRoute `ngRoute`}.
|
||||
@@ -1,26 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $injector:nomod
|
||||
@fullName Module Unavailable
|
||||
@description
|
||||
|
||||
This error occurs when trying to "re-open" a module that has not yet been defined.
|
||||
|
||||
To define a new module, call {@link api/angular.module angular.module} with a name
|
||||
and an array of dependent modules, like so:
|
||||
|
||||
```
|
||||
// When defining a module with no module dependencies,
|
||||
// the requires array should be defined and empty.
|
||||
var myApp = angular.module('myApp', []);
|
||||
```
|
||||
|
||||
To retrieve a reference to the same module for further configuration, call
|
||||
`angular.module` without the `requires` array.
|
||||
|
||||
```
|
||||
var myApp = angular.module('myApp');
|
||||
```
|
||||
|
||||
Calling `angular.module` without the `requires` array when the module has not yet
|
||||
been defined causes this error to be thrown. To fix it, define your module with
|
||||
a name and an empty array, as in the first example above.
|
||||
@@ -1,26 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $injector:pget
|
||||
@fullName Provider Missing $get
|
||||
@description
|
||||
|
||||
This error occurs when attempting to register a provider that does not have a
|
||||
`$get` method. For example:
|
||||
|
||||
```
|
||||
function BadProvider() {} // No $get method!
|
||||
angular.module("myApp", [])
|
||||
.provider('bad', BadProvider); // this throws the error
|
||||
```
|
||||
|
||||
To fix the error, fill in the `$get` method on the provider like so:
|
||||
|
||||
```
|
||||
function GoodProvider() {
|
||||
this.$get = angular.noop;
|
||||
}
|
||||
angular.module("myApp", [])
|
||||
.provider('good', GoodProvider);
|
||||
```
|
||||
|
||||
For more information, refer to the {@link api/AUTO.$provide#methods_provider
|
||||
$provide.provider} api doc.
|
||||
@@ -1,26 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $injector:unpr
|
||||
@fullName Unknown Provider
|
||||
@description
|
||||
|
||||
This error results from the `$injector` being unable to resolve a required
|
||||
dependency. To fix this, make sure the dependency is defined and spelled
|
||||
correctly. For example:
|
||||
|
||||
```
|
||||
angular.module('myApp', [])
|
||||
.controller('myCtrl', ['myService', function (myService) {
|
||||
// Do something with myService
|
||||
}]);
|
||||
```
|
||||
|
||||
This code will fail with `$injector:unpr` if `myService` is not defined. Making
|
||||
sure each dependency is defined will fix the problem.
|
||||
|
||||
```
|
||||
angular.module('myApp', [])
|
||||
.service('myService', function () { /* ... */ })
|
||||
.controller('myCtrl', ['myService', function (myService) {
|
||||
// Do something with myService
|
||||
}]);
|
||||
```
|
||||
@@ -1,7 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $interpolate:interr
|
||||
@fullName Interpolation Error
|
||||
@description
|
||||
|
||||
This error occurs when interpolation fails due to some exception. The error
|
||||
message above should provide additional context.
|
||||
@@ -1,12 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $interpolate:noconcat
|
||||
@fullName Multiple Expressions
|
||||
@description
|
||||
|
||||
This error occurs when performing an interpolation that concatenates multiple
|
||||
expressions when a trusted value is required. Concatenating expressions makes
|
||||
it hard to reason about whether some combination of concatenated values are
|
||||
unsafe to use and could easily lead to XSS.
|
||||
|
||||
For more information about how AngularJS helps keep your app secure, refer to
|
||||
the {@link api/ng.$sce $sce} API doc.
|
||||
@@ -1,11 +0,0 @@
|
||||
@ngdoc error
|
||||
@name jqLite:nosel
|
||||
@fullName Unsupported Selector Lookup
|
||||
@description
|
||||
|
||||
In order to keep Angular small, Angular implements only a subset of the selectors in {@link api/angular.element#description_angulars-jqlite jqLite}.
|
||||
This error occurs when a jqLite instance is invoked with a selector other than this subset.
|
||||
|
||||
In order to resolve this error, rewrite your code to only use tag name selectors and manually traverse the DOM using the APIs provided by jqLite.
|
||||
|
||||
Alternatively, you can include a full version of jQuery, which Angular will automatically use and that will make all selectors available.
|
||||
@@ -1,7 +0,0 @@
|
||||
@ngdoc error
|
||||
@name jqLite:offargs
|
||||
@fullName Invalid jqLite#off() parameter
|
||||
@description
|
||||
|
||||
This error occurs when trying to pass too many arguments to `jqLite#off`. Note
|
||||
that `jqLite#off` does not support namespaces or selectors like jQuery.
|
||||
@@ -1,8 +0,0 @@
|
||||
@ngdoc error
|
||||
@name jqLite:onargs
|
||||
@fullName Invalid jqLite#on() Parameters
|
||||
@description
|
||||
|
||||
This error occurs when trying to pass too many arguments to `jqLite#on`. Note
|
||||
that `jqLite#on` does not support the `selector` or `eventData` parameters as
|
||||
jQuery does.
|
||||
@@ -1,17 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $location:ihshprfx
|
||||
@fullName Missing Hash Prefix
|
||||
@description
|
||||
|
||||
This error occurs when {@link api/ng.$location $location} service is configured to use a hash prefix but this prefix was not present in a url that the `$location` service was asked to parse.
|
||||
|
||||
For example if you configure `$location` service with prefix `'!'`:
|
||||
```
|
||||
myApp.config(function($locationProvider) {
|
||||
$locationProvider.prefix('!');
|
||||
});
|
||||
```
|
||||
|
||||
If you enter the app at url `http:/myapp.com/#/myView` this error will be throw.
|
||||
|
||||
The correct url for this configuration is `http:/myapp.com/#!/myView` (note the `'!'` after `'#'` symbol).
|
||||
@@ -1,8 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $location:ipthprfx
|
||||
@fullName Invalid or Missing Path Prefix
|
||||
@description
|
||||
|
||||
This error occurs when you configure the {@link api/ng.$location `$location`} service in the html5 mode, specify a base url for your application via `<base>` element and try to update the location with a path that doesn't match the base prefix.
|
||||
|
||||
To resolve this issue, please check the base url specified via the `<base>` tag in the head of your main html document, as well as the url that you tried to set the location to.
|
||||
@@ -1,9 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $location:isrcharg
|
||||
@fullName Wrong $location.search() argument type
|
||||
@description
|
||||
|
||||
To resolve this error, ensure that the first argument for the `$location.search` call is a `string` or an object.
|
||||
You can use the stack trace associated with this error to identify the call site that caused this issue.
|
||||
|
||||
To learn more, please consult the {@link api/ng.$location `$location`} api docs.
|
||||
@@ -1,8 +0,0 @@
|
||||
@ngdoc error
|
||||
@name ng:areq
|
||||
@fullName Bad Argument
|
||||
@description
|
||||
|
||||
AngularJS often asserts that certain values will be present and truthy using a
|
||||
helper function. If the assertion fails, this error is thrown. To fix this problem,
|
||||
make sure that the value the assertion expects is defined and truthy.
|
||||
@@ -1,8 +0,0 @@
|
||||
@ngdoc error
|
||||
@name ng:badname
|
||||
@fullName Bad `hasOwnProperty` Name
|
||||
@description
|
||||
|
||||
Occurs when you try to use the name `hasOwnProperty` in a context where it is not allow.
|
||||
Generally, a name cannot be `hasOwnProperty` because it is used, internally, on a object
|
||||
and allowing such a name would break lookups on this object.
|
||||
@@ -1,29 +0,0 @@
|
||||
@ngdoc error
|
||||
@name ng:btstrpd
|
||||
@fullName App Already Bootstrapped with this Element
|
||||
@description
|
||||
|
||||
Occurs when calling angular.bootstrap on an element that has already been bootstrapped.
|
||||
|
||||
This usually happens when you accidentally use both `ng-app` and `angular.bootstrap` to bootstrap an application.
|
||||
|
||||
```
|
||||
<html>
|
||||
...
|
||||
<body ng-app="myApp">
|
||||
<script>
|
||||
angular.bootstrap(document.body, ['myApp']);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
Note that for bootrapping purposes, the `<html>` element is the same as `document`, so the following will also throw an error.
|
||||
```
|
||||
<html>
|
||||
...
|
||||
<script>
|
||||
angular.bootstrap(document, ['myApp']);
|
||||
</script>
|
||||
</html>
|
||||
```
|
||||
@@ -1,10 +0,0 @@
|
||||
@ngdoc error
|
||||
@name ng:cpi
|
||||
@fullName Bad Copy
|
||||
@description
|
||||
|
||||
This error occurs when attempting to copy an object to itself. Calling {@link
|
||||
api/angular.copy angular.copy} with a `destination` object deletes
|
||||
all of the elements or properties on `destination` before copying to it. Copying
|
||||
an object to itself is not supported. Make sure to check your calls to
|
||||
`angular.copy` and avoid copying objects or arrays to themselves.
|
||||
@@ -1,10 +0,0 @@
|
||||
@ngdoc error
|
||||
@name ng:cpws
|
||||
@fullName Copying Window or Scope
|
||||
@description
|
||||
|
||||
Copying Window or Scope instances is not supported because of cyclical and self
|
||||
references. Avoid copying windows and scopes, as well as any other cyclical or
|
||||
self-referential structures. Note that trying to deep copy an object containing
|
||||
cyclical references that is neither a window nor a scope will cause infinite
|
||||
recursion and a stack overflow.
|
||||
@@ -1,27 +0,0 @@
|
||||
@ngdoc error
|
||||
@name ngModel:nonassign
|
||||
@fullName Non-Assignable Expression
|
||||
@description
|
||||
|
||||
This error occurs when expression the {@link api/ng.directive:ngModel ngModel} directive is bound to is a non-assignable expression.
|
||||
|
||||
Examples using assignable expressions include:
|
||||
|
||||
```
|
||||
<input ng-model="namedVariable">
|
||||
<input ng-model="myObj.someProperty">
|
||||
<input ng-model="indexedArray[0]">
|
||||
```
|
||||
|
||||
Examples of non-assignable expressions include:
|
||||
|
||||
```
|
||||
<input ng-model="foo + bar">
|
||||
<input ng-model="42">
|
||||
<input ng-model="'oops'">
|
||||
<input ng-model="myFunc()">
|
||||
```
|
||||
|
||||
Always make sure that the expression bound via `ngModel` directive can be assigned to.
|
||||
|
||||
For more information, see the {@link api/ng.directive:ngModel ngModel API doc}.
|
||||
@@ -1,13 +0,0 @@
|
||||
@ngdoc error
|
||||
@name ngOptions:iexp
|
||||
@fullName Invalid Expression
|
||||
@description
|
||||
This error occurs when 'ngOptions' is passed an expression that isn't in an expected form.
|
||||
|
||||
Here's an example of correct syntax:
|
||||
|
||||
```
|
||||
<select ng-model="color" ng-options="c.name for c in colors">
|
||||
```
|
||||
|
||||
For more information on valid expression syntax, see 'ngOptions' in {@link api/ng.directive:select select} directive docs.
|
||||
@@ -1,7 +0,0 @@
|
||||
@ngdoc error
|
||||
@name ngPattern:noregexp
|
||||
@fullName Expected Regular Expression
|
||||
@description
|
||||
This error occurs when 'ngPattern' is passed an expression that isn't a regular expression or doesn't have the expected format.
|
||||
|
||||
For more information on valid expression syntax, see 'ngPattern' in {@link api/ng.directive:select input} directive docs.
|
||||
@@ -1,22 +0,0 @@
|
||||
@ngdoc error
|
||||
@name ngRepeat:dupes
|
||||
@fullName Duplicate Key in Repeater
|
||||
@description
|
||||
|
||||
Occurs if there are duplicate keys in an {@link api/ng.directive:ngRepeat ngRepeat} expression. Duplicate keys are banned because AngularJS uses keys to associate DOM nodes with items.
|
||||
|
||||
By default, collections are keyed by reference which is desirable for most common models but can be problematic for primitive types that are interned (share references).
|
||||
|
||||
For example the issue can be triggered by this *invalid* code:
|
||||
|
||||
```
|
||||
<div ng-repeat="value in [4, 4]"></div>
|
||||
```
|
||||
|
||||
To resolve this error either ensure that the items in the collection have unique identity of use the `track by` syntax to specify how to track the association between models and DOM.
|
||||
|
||||
To resolve the example above can be resolved by using `track by $index`, which will cause the items to be keyed by their position in the array instead of their value:
|
||||
|
||||
```
|
||||
<div ng-repeat="value in [4, 4] track by $index"></div>
|
||||
```
|
||||
@@ -1,12 +0,0 @@
|
||||
@ngdoc error
|
||||
@name ngRepeat:iexp
|
||||
@fullName Invalid Expression
|
||||
@description
|
||||
|
||||
Occurs when there is a syntax error in an {@link api/ng.directive:ngRepeat ngRepeat}'s expression. The expression should be in the form '_item_ in _collection_[ track by _id_]'.
|
||||
|
||||
Be aware, the ngRepeat directive parses the expression using a regex before sending _collection_ and optionally _id_ to the AngularJS parser. This error comes from the regex parsing.
|
||||
|
||||
To resolve, identify and fix errors in the expression, paying special attention to the 'in' and 'track by' keywords in the expression.
|
||||
|
||||
Please consult the api documentation of {@link api/ng.directive:ngRepeat ngRepeat} to learn more about valid syntax.
|
||||
@@ -1,25 +0,0 @@
|
||||
@ngdoc error
|
||||
@name ngRepeat:iidexp
|
||||
@fullName Invalid Identifier
|
||||
@description
|
||||
|
||||
Occurs when there is an error in the identifier part of {@link api/ng.directive:ngRepeat ngRepeat}'s expression.
|
||||
|
||||
To resolve, use either a valid identifier or a tuple (_key_, _value_) where both _key_ and _value_ are valid identifiers.
|
||||
|
||||
Examples of *invalid* syntax:
|
||||
|
||||
```
|
||||
<div ng-repeat="33 in users"></div>
|
||||
<div ng-repeat="someFn() in users"></div>
|
||||
<div ng-repeat="some user in users"></div>
|
||||
```
|
||||
|
||||
Examples of *valid* syntax:
|
||||
|
||||
```
|
||||
<div ng-repeat="user in users"></div>
|
||||
<div ng-repeat="(id, user) in userMap"></div>
|
||||
```
|
||||
|
||||
Please consult the api documentation of {@link api/ng.directive:ngRepeat ngRepeat} to learn more about valid syntax.
|
||||
@@ -1,12 +0,0 @@
|
||||
@ngdoc error
|
||||
@name ngTransclude:orphan
|
||||
@fullName Orphan ngTransclude Directive
|
||||
@description
|
||||
|
||||
Occurs when an `ngTransclude` occurs without a transcluded ancesstor element.
|
||||
|
||||
This error often occurs when you have forgotten to set `transclude: true` in some directive definition, and then used `ngTranslude` in the driective's template.
|
||||
|
||||
To resolve, either remove the offending `ngTransclude` or check that `transclude: true` is included in the intended directive definition.
|
||||
|
||||
Consult the API documentation for {@link guide/directive writing directives} to learn more.
|
||||
@@ -1,16 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $parse:isecdom
|
||||
@fullName Referencing a DOM node in Expression
|
||||
@description
|
||||
|
||||
Occurs when an expression attempts to access a DOM node.
|
||||
|
||||
AngularJS restricts access to DOM nodes from within expressions since it's a known way to
|
||||
execute arbitrary Javascript code.
|
||||
|
||||
This check is only performed on object index and function calls in Angular expressions. These are
|
||||
places that are harder for the developer to guard. Dotted member access (such as a.b.c) does not
|
||||
perform this check - it's up to the developer to not expose such sensitive and powerful objects
|
||||
directly on the scope chain.
|
||||
|
||||
To resolve this error, avoid access to DOM nodes.
|
||||
@@ -1,18 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $parse:isecfld
|
||||
@fullName Referencing 'constructor' Field in Expression
|
||||
@description
|
||||
|
||||
Occurs when an expression attempts to access an objects constructor field.
|
||||
|
||||
AngularJS bans constructor access from within expressions since constructor
|
||||
access is a known way to execute arbitrary Javascript code.
|
||||
|
||||
To resolve this error, avoid constructor access. As a last resort, alias
|
||||
the constructor and access it through the alias instead.
|
||||
|
||||
Example expression that would result in this error:
|
||||
|
||||
```
|
||||
<div>{{user.constructor.name}}</div>
|
||||
```
|
||||
@@ -1,10 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $parse:isecfn
|
||||
@fullName Referencing Function Disallowed
|
||||
@description
|
||||
|
||||
Occurs when an expression attempts to access the 'Function' object (constructor for all functions in JavaScript).
|
||||
|
||||
Angular bans access to Function from within expressions since constructor access is a known way to execute arbitrary Javascript code.
|
||||
|
||||
To resolve this error, avoid Function access.
|
||||
@@ -1,16 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $parse:isecwindow
|
||||
@fullName Referencing Window object in Expression
|
||||
@description
|
||||
|
||||
Occurs when an expression attempts to access a Window object.
|
||||
|
||||
AngularJS restricts access to the Window object from within expressions since it's a known way to
|
||||
execute arbitrary Javascript code.
|
||||
|
||||
This check is only performed on object index and function calls in Angular expressions. These are
|
||||
places that are harder for the developer to guard. Dotted member access (such as a.b.c) does not
|
||||
perform this check - it's up to the developer to not expose such sensitive and powerful objects
|
||||
directly on the scope chain.
|
||||
|
||||
To resolve this error, avoid Window access.
|
||||
@@ -1,10 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $parse:lexerr
|
||||
@fullName Lexer Error
|
||||
@description
|
||||
|
||||
Occurs when an expression has a lexical error, for example a malformed number (0.5e-) or an invalid unicode escape.
|
||||
|
||||
The error message contains a more precise error.
|
||||
|
||||
To resolve, learn more about {@link guide/expression Angular expressions}, identify the error and fix the expression's syntax.
|
||||
@@ -1,9 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $parse:syntax
|
||||
@fullName Syntax Error
|
||||
@description
|
||||
|
||||
Occurs when there is a syntax error in an expression. These errors are thrown while compiling the expression.
|
||||
The error message contains a more precise description of the error, including the location (column) in the expression where the error occurred.
|
||||
|
||||
To resolve, learn more about {@link guide/expression Angular expressions}, identify the error and fix the expression's syntax.
|
||||
@@ -1,9 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $parse:ueoe
|
||||
@fullName Unexpected End of Expression
|
||||
@description
|
||||
|
||||
Occurs when an expression is missing tokens at the end of the expression.
|
||||
For example, forgetting a closing bracket in an expression will trigger this error.
|
||||
|
||||
To resolve, learn more about {@link guide/expression Angular expressions}, identify the error and fix the expression's syntax.
|
||||
@@ -1,9 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $resource:badargs
|
||||
@fullName Too Many Arguments
|
||||
@description
|
||||
|
||||
This error occurs when specifying too many arguments to a {@link api/ngResource.$resource `$resource`} action, such as `get`, `query` or any user-defined custom action.
|
||||
These actions may take up to 4 arguments.
|
||||
|
||||
For more information, refer to the {@link api/ngResource.$resource `$resource`} API reference documentation.
|
||||
@@ -1,11 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $resource:badcfg
|
||||
@fullName Response does not match configured parameter
|
||||
@description
|
||||
|
||||
This error occurs when the {@link api/ngResource.$resource `$resource`} service expects a response that can be deserialized as an array, receives an object, or vice versa.
|
||||
By default, all resource actions expect objects, except `query` which expects arrays.
|
||||
|
||||
To resolve this error, make sure your `$resource` configuration matches the actual format of the data returned from the server.
|
||||
|
||||
For more information, see the {@link api/ngResource.$resource `$resource`} API reference documentation.
|
||||
@@ -1,27 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $resource:badmember
|
||||
@fullName Syntax error in param value using @member lookup
|
||||
@description
|
||||
|
||||
Occurs when there is a syntax error when attempting to extract a param
|
||||
value from the data object.
|
||||
|
||||
Here's an example of valid syntax for `params` or `paramsDefault`:
|
||||
|
||||
````javascript
|
||||
{
|
||||
bar: '@foo.bar'
|
||||
}
|
||||
````
|
||||
|
||||
The part following the `@`, `foo.bar` in this case, should be a simple
|
||||
dotted member lookup using only ASCII identifiers. This error occurs
|
||||
when there is an error in that expression. The following are all syntax
|
||||
errors
|
||||
|
||||
| Value | Error |
|
||||
|---------|----------------|
|
||||
| `@` | Empty expression following `@`. |
|
||||
| `@1.a` | `1` is an invalid javascript identifier. |
|
||||
| `@.a` | Leading `.` is invalid. |
|
||||
| `@a[1]` | Only dotted lookups are supported (no index operator) |
|
||||
@@ -1,8 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $resource:badname
|
||||
@fullName Cannot use hasOwnProperty as a parameter name
|
||||
@description
|
||||
|
||||
Occurs when you try to use the name `hasOwnProperty` as a name of a parameter.
|
||||
Generally, a name cannot be `hasOwnProperty` because it is used, internally, on a object
|
||||
and allowing such a name would break lookups on this object.
|
||||
@@ -1,17 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $rootScope:infdig
|
||||
@fullName Infinite $digest Loop
|
||||
@description
|
||||
|
||||
This error occurs when the application's model becomes unstable and each `$digest` cycle triggers a state change and subsequent `$digest` cycle.
|
||||
Angular detects this situation and prevents an infinite loop from causing the browser to become unresponsive.
|
||||
|
||||
For example, the situation can occur by setting up a watch on a path and subsequently updating the same path when the value changes.
|
||||
|
||||
```
|
||||
$scope.$watch('foo', function() {
|
||||
$scope.foo = $scope.foo + 1;
|
||||
});
|
||||
```
|
||||
|
||||
The maximum number of allowed iterations of the `$digest` cycle is controlled via TTL setting which can be configured via {@link api/ng.$rootScopeProvider $rootScopeProvider}.
|
||||
@@ -1,74 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $rootScope:inprog
|
||||
@fullName Action Already In Progress
|
||||
@description
|
||||
|
||||
At any point in time there can be only one `$digest` or $apply operation in progress.
|
||||
The stack trace of this error allows you to trace the origin of the currently executing $apply or $digest call.
|
||||
|
||||
`$digest` or `$apply` are processing operational states of the Scope - data-structure in Angular that provides context for models and enables model mutation observation.
|
||||
|
||||
Trying to reenter a `$digest` or `$apply` while one of them is already in progress is typically a sign of programming error that needs to be fixed.
|
||||
|
||||
This error is often seen when interacting with an API that is sometimes sync and sometimes async.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
function MyController() {
|
||||
thirdPartyComponent.getData(function(someData) {
|
||||
scope.$apply(function() {
|
||||
scope.someData = someData;
|
||||
});
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
The controller constructor is always instantiated from within an $apply cycle, so if the third-party component called our callback synchronously, we'd be trying to enter the $apply again.
|
||||
|
||||
To resolve this type of issue, either fix the api to be always synchronous or asynchronous or wrap the call to the api with setTimeout call to make it always asynchronous.
|
||||
|
||||
|
||||
Other situation that leads to this error is when you are trying to reuse a function to by using it as a callback for code that is called by various apis inside and outside of $apply.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
myApp.directive('myDirective', function() {
|
||||
return {
|
||||
link: function($scope, $element) {
|
||||
function doSomeWork() {
|
||||
$scope.$apply(function() {
|
||||
// do work here, and update the model
|
||||
};
|
||||
}
|
||||
|
||||
$element.on('click', doSomeWork);
|
||||
doSomeWork(); // << this will throw an exception because templates are compiled within $apply
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
```
|
||||
|
||||
The fix for the example above looks like this:
|
||||
```
|
||||
myApp.directive('myDirective', function() {
|
||||
return {
|
||||
link: function($scope, $element) {
|
||||
function doSomeWork() {
|
||||
// do work here, and update the model
|
||||
}
|
||||
|
||||
$element.on('click', function() {
|
||||
$scope.$apply(doSomeWork); // <<< the $apply call was moved to the callsite that doesn't execute in $apply call already
|
||||
});
|
||||
|
||||
doSomeWork();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
```
|
||||
|
||||
To learn more about Angular processing model please check out the {@link guide/concepts concepts doc} as well as the {@link api/ng.$rootScope.Scope api} doc.
|
||||
@@ -1,11 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $sanitize:badparse
|
||||
@fullName Parsing Error while Sanitizing
|
||||
@description
|
||||
|
||||
This error occurs when the HTML string passed to '$sanitize' can't be parsed by the sanitizer.
|
||||
The error contains part of the html string that can't be parsed.
|
||||
|
||||
The parser is more strict than a typical browser parser, so it's possible that some obscure input would produce this error despite the string being recognized as valid HTML by a browser.
|
||||
|
||||
If a valid html code results in this error, please file a bug.
|
||||
@@ -1,8 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $sce:icontext
|
||||
@fullName Invalid / Unknown SCE context
|
||||
@description
|
||||
|
||||
The context enum passed to {@link api/ng.$sce#methods_trustAs $sce.trustAs} was not recognized.
|
||||
|
||||
Please consult the list of {@link api/ng.$sce#contexts supported Strict Contextual Escaping (SCE) contexts}.
|
||||
@@ -1,15 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $sce:iequirks
|
||||
@fullName IE8 in quirks mode is unsupported
|
||||
@description
|
||||
|
||||
This error occurs when you are using AngularJS with {@link api/ng.$sce Strict Contextual Escaping (SCE)} mode enabled (the default) on IE8 or lower in quirks mode.
|
||||
|
||||
In this mode, IE8 allows one to execute arbitrary javascript by the use of the `expression()` syntax and is not supported.
|
||||
Refer {@link http://blogs.msdn.com/b/ie/archive/2008/10/16/ending-expressions.aspx MSDN Blogs > IEBlog > Ending Expressions} to learn more about them.
|
||||
|
||||
To resolve this error please specify the proper doctype at the top of your main html document:
|
||||
|
||||
```
|
||||
<!doctype html>
|
||||
```
|
||||
@@ -1,9 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $sce:imatcher
|
||||
@fullName Invalid matcher (only string patterns and RegExp instances are supported)
|
||||
@description
|
||||
|
||||
Please see {@link api/ng.$sceDelegateProvider#methods_resourceUrlWhitelist
|
||||
$sceDelegateProvider.resourceUrlWhitelist} and {@link
|
||||
api/ng.$sceDelegateProvider#methods_resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist} for the
|
||||
list of acceptable items.
|
||||
@@ -1,26 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $sce:insecurl
|
||||
@fullName Processing of a Resource from Untrusted Source Blocked
|
||||
@description
|
||||
|
||||
AngularJS' {@link api/ng.$sce Strict Contextual Escaping (SCE)} mode (enabled by default) has blocked loading a resource from an insecure URL.
|
||||
|
||||
Typically, this would occur if you're attempting to load an Angular template from an untrusted source.
|
||||
It's also possible that a custom directive threw this error for a similar reason.
|
||||
|
||||
Angular only loads templates from trusted URLs (by calling {@link api/ng.$sce#methods_getTrustedResourceUrl $sce.getTrustedResourceUrl} on the template URL).
|
||||
|
||||
By default, only URLs that belong to the same origin are trusted. These are urls with the same domain and protocol as the application document.
|
||||
|
||||
The {@link api/ng.directive:ngInclude ngInclude} directive and {@link guide/directive directives} that specify a `templateUrl` require a trusted resource URL.
|
||||
|
||||
To load templates from other domains and/or protocols, either adjust the {@link
|
||||
api/ng.$sceDelegateProvider#methods_resourceUrlWhitelist whitelist}/ {@link
|
||||
api/ng.$sceDelegateProvider#methods_resourceUrlBlacklist blacklist} or wrap the URL with a call to {@link
|
||||
api/ng.$sce#methods_trustAsResourceUrl $sce.trustAsResourceUrl}.
|
||||
|
||||
**Note**: The browser's {@link
|
||||
https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest Same Origin
|
||||
Policy} and {@link http://www.w3.org/TR/cors/ Cross-Origin Resource Sharing (CORS)} policy apply
|
||||
that may further restrict whether the template is successfully loaded. (e.g. neither cross-domain
|
||||
requests won't work on all browsers nor `file://` requests on some browsers)
|
||||
@@ -1,8 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $sce:itype
|
||||
@fullName String Value is Required for SCE Trust Call
|
||||
@description
|
||||
|
||||
{@link api/ng.$sce#methods_trustAs $sce.trustAs} requires a string value.
|
||||
|
||||
Read more about {@link api/ng.$sce Strict Contextual Escaping (SCE)} in AngularJS.
|
||||
@@ -1,9 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $sce:iwcard
|
||||
@fullName The sequence *** is not a valid pattern wildcard
|
||||
@description
|
||||
|
||||
The strings in {@link api/ng.$sceDelegateProvider#methods_resourceUrlWhitelist
|
||||
$sceDelegateProvider.resourceUrlWhitelist} and {@link
|
||||
api/ng.$sceDelegateProvider#methods_resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist} may not
|
||||
contain the undefined sequence `***`. Only `*` and `**` wildcard patterns are defined.
|
||||
@@ -1,15 +0,0 @@
|
||||
@ngdoc error
|
||||
@name $sce:unsafe
|
||||
@fullName Require a safe/trusted value
|
||||
@description
|
||||
|
||||
The value provided for use in a specific context was not found to be safe/trusted for use.
|
||||
|
||||
Angular's {@link api/ng.$sce Strict Contextual Escaping (SCE)} mode
|
||||
(enabled by default), requires bindings in certain
|
||||
contexts to result in a value that is trusted as safe for use in such a context. (e.g. loading an
|
||||
Angular template from a URL requires that the URL is one considered safe for loading resources.)
|
||||
|
||||
This helps prevent XSS and other security issues. Read more at {@link
|
||||
api/ng.$sce Strict Contextual Escaping (SCE)}
|
||||
|
||||
@@ -1,289 +0,0 @@
|
||||
@ngdoc overview
|
||||
@name Developer Guide: Animations
|
||||
@description
|
||||
|
||||
|
||||
# Animations
|
||||
|
||||
AngularJS 1.2 provides animation hooks for common directives such as `ngRepeat`, `ngSwitch`, and `ngView`, as well as custom directives
|
||||
via the `$animate` service. These animation hooks are set in place to trigger animations during the life cycle of various directives and when
|
||||
triggered, will attempt to perform a CSS Transition, CSS Keyframe Animation or a JavaScript callback Animation (depending on if an animation is
|
||||
placed on the given directive). Animations can be placed using vanilla CSS by following the naming conventions set in place by AngularJS
|
||||
or with JavaScript code when it's defined as a factory.
|
||||
|
||||
Animations are not available unless you include the {@link api/ngAnimate `ngAnimate` module} as a dependency within your application.
|
||||
|
||||
Below is a quick example of animations being enabled for `ngShow` and `ngHide`:
|
||||
|
||||
<example animations="true">
|
||||
<file name="index.html">
|
||||
<div ng-init="checked=true">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="checked" style="float:left; margin-right:10px;"> Is Visible...
|
||||
</label>
|
||||
<div class="check-element animate-show-hide" ng-show="checked" style="clear:both;">
|
||||
Visible...
|
||||
</div>
|
||||
</div>
|
||||
</file>
|
||||
<file name="animations.css">
|
||||
.animate-show-hide {
|
||||
padding:10px;
|
||||
border:1px solid black;
|
||||
background:white;
|
||||
}
|
||||
|
||||
.animate-show-hide.ng-hide-add, .animate-show-hide.ng-hide-remove {
|
||||
-webkit-transition:all linear 0.5s;
|
||||
-moz-transition:all linear 0.5s;
|
||||
-o-transition:all linear 0.5s;
|
||||
transition:all linear 0.5s;
|
||||
display:block!important;
|
||||
}
|
||||
|
||||
.animate-show-hide.ng-hide-add.ng-hide-add-active,
|
||||
.animate-show-hide.ng-hide-remove {
|
||||
opacity:0;
|
||||
}
|
||||
|
||||
.animate-show-hide.ng-hide-add,
|
||||
.animate-show-hide.ng-hide-remove.ng-hide-remove-active {
|
||||
opacity:1;
|
||||
}
|
||||
</file>
|
||||
</example>
|
||||
|
||||
## Installation
|
||||
|
||||
See the {@link api/ngAnimate API docs for `ngAnimate`} for instructions on installing the module.
|
||||
|
||||
You may also want to setup a separate CSS file for defining CSS-based animations.
|
||||
|
||||
## How they work
|
||||
|
||||
Animations in AngularJS are completely based on CSS classes. As long as you have a CSS class attached to a HTML element within
|
||||
your website, you can apply animations to it. Lets say for example that we have an HTML template with a repeater in it like so:
|
||||
|
||||
<pre>
|
||||
<div ng-repeat="item in items" class="repeated-item">
|
||||
{{ item.id }}
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
As you can see, the `.repeated-item` class is present on the element that will be repeated and this class will be
|
||||
used as a reference within our application's CSS and/or JavaScript animation code to tell AngularJS to perform an animation.
|
||||
|
||||
As ngRepeat does its thing, each time a new item is added into the list, ngRepeat will add
|
||||
a `ng-enter` class name to the element that is being added. When removed it will apply a `ng-leave` class name and when moved around
|
||||
it will apply a `ng-move` class name.
|
||||
|
||||
Taking a look at the following CSS code, we can see some transition and keyframe animation code set for each of those events that
|
||||
occur when ngRepeat triggers them:
|
||||
|
||||
<pre>
|
||||
/*
|
||||
We're using CSS transitions for when
|
||||
the enter and move events are triggered
|
||||
for the element that has the .repeated-item
|
||||
class
|
||||
*/
|
||||
.repeated-item.ng-enter, .repeated-item.ng-move {
|
||||
-webkit-transition:0.5s linear all;
|
||||
-moz-transition:0.5s linear all;
|
||||
-o-transition:0.5s linear all;
|
||||
transition:0.5s linear all;
|
||||
opacity:0;
|
||||
}
|
||||
|
||||
/*
|
||||
The ng-enter-active and ng-move-active
|
||||
are where the transition destination properties
|
||||
are set so that the animation knows what to
|
||||
animate.
|
||||
*/
|
||||
.repeated-item.ng-enter.ng-enter-active,
|
||||
.repeated-item.ng-move.ng-move-active {
|
||||
opacity:1;
|
||||
}
|
||||
|
||||
/*
|
||||
We're using CSS keyframe animations for when
|
||||
the leave event is triggered for the element
|
||||
that has the .repeated-item class
|
||||
*/
|
||||
.repeated-item.ng-leave {
|
||||
-webkit-animation:0.5s my_animation;
|
||||
-moz-animation:0.5s my_animation;
|
||||
-o-animation:0.5s my_animation;
|
||||
animation:0.5s my_animation;
|
||||
}
|
||||
|
||||
@keyframes my_animation {
|
||||
from { opacity:1; }
|
||||
to { opacity:0; }
|
||||
}
|
||||
|
||||
/*
|
||||
Unfortunately each browser vendor requires
|
||||
its own definition of keyframe animation code...
|
||||
*/
|
||||
@-webkit-keyframes my_animation {
|
||||
from { opacity:1; }
|
||||
to { opacity:0; }
|
||||
}
|
||||
|
||||
@-moz-keyframes my_animation {
|
||||
from { opacity:1; }
|
||||
to { opacity:0; }
|
||||
}
|
||||
|
||||
@-o-keyframes my_animation {
|
||||
from { opacity:1; }
|
||||
to { opacity:0; }
|
||||
}
|
||||
</pre>
|
||||
|
||||
The same approach to animation can be used using JavaScript code (**jQuery is used within to perform animations**):
|
||||
|
||||
<pre>
|
||||
myModule.animation('.repeated-item', function() {
|
||||
return {
|
||||
enter : function(element, done) {
|
||||
element.css('opacity',0);
|
||||
jQuery(element).animate({
|
||||
opacity: 1
|
||||
}, done);
|
||||
|
||||
// optional onDone or onCancel callback
|
||||
// function to handle any post-animation
|
||||
// cleanup operations
|
||||
return function(isCancelled) {
|
||||
if(isCancelled) {
|
||||
jQuery(element).stop();
|
||||
}
|
||||
}
|
||||
},
|
||||
leave : function(element, done) {
|
||||
element.css('opacity', 1);
|
||||
jQuery(element).animate({
|
||||
opacity: 0
|
||||
}, done);
|
||||
|
||||
// optional onDone or onCancel callback
|
||||
// function to handle any post-animation
|
||||
// cleanup operations
|
||||
return function(isCancelled) {
|
||||
if(isCancelled) {
|
||||
jQuery(element).stop();
|
||||
}
|
||||
}
|
||||
},
|
||||
move : function(element, done) {
|
||||
element.css('opacity', 0);
|
||||
jQuery(element).animate({
|
||||
opacity: 1
|
||||
}, done);
|
||||
|
||||
// optional onDone or onCancel callback
|
||||
// function to handle any post-animation
|
||||
// cleanup operations
|
||||
return function(isCancelled) {
|
||||
if(isCancelled) {
|
||||
jQuery(element).stop();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// you can also capture these animation events
|
||||
addClass : function(element, className, done) {},
|
||||
removeClass : function(element, className, done) {}
|
||||
}
|
||||
});
|
||||
</pre>
|
||||
|
||||
With these generated CSS class names present on the element at the time, AngularJS automatically
|
||||
figures out whether to perform a CSS and/or JavaScript animation. If both CSS and JavaScript animation
|
||||
code is present, and match the CSS class name on the element, then AngularJS will run both animations at the same time.
|
||||
|
||||
## Class and ngClass animation hooks
|
||||
|
||||
AngularJS also pays attention to CSS class changes on elements by triggering the **add** and **remove** hooks.
|
||||
This means that if a CSS class is added to or removed from an element then an animation can be executed in between
|
||||
before the CSS class addition or removal is finalized. (Keep in mind that AngularJS will only be
|
||||
able to capture class changes if an **expression** or the **ng-class** directive is used on the element.)
|
||||
|
||||
The example below shows how to perform animations during class changes:
|
||||
|
||||
<example animations="true">
|
||||
<file name="index.html">
|
||||
<p>
|
||||
<input type="button" value="set" ng-click="myCssVar='css-class'">
|
||||
<input type="button" value="clear" ng-click="myCssVar=''">
|
||||
<br>
|
||||
<span ng-class="myCssVar">CSS-Animated Text</span>
|
||||
</p>
|
||||
</file>
|
||||
<file name="style.css">
|
||||
.css-class-add, .css-class-remove {
|
||||
-webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
|
||||
-moz-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
|
||||
-o-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
|
||||
transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
|
||||
}
|
||||
|
||||
.css-class,
|
||||
.css-class-add.css-class-add-active {
|
||||
color: red;
|
||||
font-size:3em;
|
||||
}
|
||||
|
||||
.css-class-remove.css-class-remove-active {
|
||||
font-size:1.0em;
|
||||
color:black;
|
||||
}
|
||||
</file>
|
||||
</example>
|
||||
|
||||
Although the CSS is a little different then what we saw before, the idea is the same.
|
||||
|
||||
## Which directives support animations?
|
||||
|
||||
A handful of common AngularJS directives support and trigger animation hooks whenever any major event occurs during its life cycle.
|
||||
The table below explains in detail which animation events are triggered
|
||||
|
||||
| Directive | Supported Animations |
|
||||
|-------------------------------------------------------------------------------------|------------------------------------------|
|
||||
| {@link api/ng.directive:ngRepeat#usage_animations ngRepeat} | enter, leave, and move |
|
||||
| {@link api/ngRoute.directive:ngView#usage_animations ngView} | enter and leave |
|
||||
| {@link api/ng.directive:ngInclude#usage_animations ngInclude} | enter and leave |
|
||||
| {@link api/ng.directive:ngSwitch#usage_animations ngSwitch} | enter and leave |
|
||||
| {@link api/ng.directive:ngIf#usage_animations ngIf} | enter and leave |
|
||||
| {@link api/ng.directive:ngShow#usage_animations ngClass or {{class}}} | add and remove |
|
||||
| {@link api/ng.directive:ngShow#usage_animations ngShow & ngHide} | add and remove (the ng-hide class value) |
|
||||
|
||||
For a full breakdown of the steps involved during each animation event, refer to the {@link api/ngAnimate.$animate API docs}.
|
||||
|
||||
## How do I use animations in my own directives?
|
||||
|
||||
Animations within custom directives can also be established by injecting `$animate` directly into your directive and
|
||||
making calls to it when needed.
|
||||
|
||||
<pre>
|
||||
myModule.directive('my-directive', ['$animate', function($animate) {
|
||||
return function(element, scope, attrs) {
|
||||
element.bind('click', function() {
|
||||
if(element.hasClass('clicked')) {
|
||||
$animate.removeClass(element, 'clicked');
|
||||
} else {
|
||||
$animate.addClass(element, 'clicked');
|
||||
}
|
||||
});
|
||||
};
|
||||
}]);
|
||||
</pre>
|
||||
|
||||
## More about animations
|
||||
|
||||
For a full breakdown of each method available on `$animate`, see the {@link api/ngAnimate.$animate API documentation}.
|
||||
|
||||
To see a complete demo, see the {@link tutorial/step_12 animation step within the AngularJS phonecat tutorial}.
|
||||
@@ -51,12 +51,11 @@ initialization.
|
||||
|
||||
## Automatic Initialization
|
||||
|
||||
<img class="pull-right" style="padding-left: 3em;" src="img/guide/concepts-startup.png">
|
||||
|
||||
Angular initializes automatically upon `DOMContentLoaded` event or when the `angular.js` script is
|
||||
evaluated if at that time `document.readyState` is set to `'complete'`. At this point Angular looks
|
||||
for the {@link api/ng.directive:ngApp `ng-app`} directive which designates your application root.
|
||||
If the {@link api/ng.directive:ngApp `ng-app`} directive is found then Angular will:
|
||||
Angular initializes automatically upon `DOMContentLoaded` event, at which point Angular looks for
|
||||
the {@link api/ng.directive:ngApp `ng-app`} directive which
|
||||
designates your application root. If the {@link
|
||||
api/ng.directive:ngApp `ng-app`} directive is found then Angular
|
||||
will:
|
||||
|
||||
* load the {@link guide/module module} associated with the directive.
|
||||
* create the application {@link api/AUTO.$injector injector}
|
||||
@@ -113,18 +112,3 @@ This is the sequence that your code should follow:
|
||||
|
||||
2. Call {@link api/angular.bootstrap} to {@link compiler compile} the element into an
|
||||
executable, bi-directionally bound application.
|
||||
|
||||
## Deferred Bootstrap
|
||||
|
||||
This feature enables tools like Batarang and test runners to
|
||||
hook into angular's bootstrap process and sneak in more modules
|
||||
into the DI registry which can replace or augment DI services for
|
||||
the purpose of instrumentation or mocking out heavy dependencies.
|
||||
|
||||
If `window.name` contains prefix `NG_DEFER_BOOTSTRAP!` when
|
||||
{@link api/angular.bootstrap} is called, the bootstrap process will be paused
|
||||
until `angular.resumeBootstrap()` is called.
|
||||
|
||||
`angular.resumeBootstrap()` takes an optional array of modules that
|
||||
should be added to the original list of modules that the app was
|
||||
about to be bootstrapped with.
|
||||
|
||||
@@ -2,21 +2,12 @@
|
||||
@name Developer Guide: HTML Compiler
|
||||
@description
|
||||
|
||||
<div class="alert alert-warning">
|
||||
**Note:** this guide is targeted towards developers who are already familiar with AngularJS basics.
|
||||
|
||||
If you're just getting started, we recommend the {@link tutorial/ tutorial} first.
|
||||
If you just want to create custom directives, we recommend the {@link guide/directive directives guide}.
|
||||
If you want a deeper look into Angular's compilation process, you're in the right place.
|
||||
</div>
|
||||
|
||||
|
||||
# Overview
|
||||
|
||||
Angular's {@link api/ng.$compile HTML compiler} allows the developer to teach the
|
||||
browser new HTML syntax. The compiler allows you to attach behavior to any HTML element or attribute
|
||||
and even create new HTML elements or attributes with custom behavior. Angular calls these behavior
|
||||
extensions {@link api/ng.$compileProvider#methods_directive directives}.
|
||||
extensions {@link api/ng.$compileProvider#directive directives}.
|
||||
|
||||
HTML has a lot of constructs for formatting the HTML for static documents in a declarative fashion.
|
||||
For example if something needs to be centered, there is no need to provide instructions to the
|
||||
@@ -36,9 +27,9 @@ All of this compilation takes place in the web browser; no server side or pre-co
|
||||
involved.
|
||||
|
||||
|
||||
## Compiler
|
||||
# Compiler
|
||||
|
||||
Compiler is an Angular service which traverses the DOM looking for attributes. The compilation
|
||||
Compiler is an angular service which traverses the DOM looking for attributes. The compilation
|
||||
process happens in two phases.
|
||||
|
||||
1. **Compile:** traverse the DOM and collect all of the directives. The result is a linking
|
||||
@@ -53,7 +44,7 @@ for each item in a collection. Having a compile and link phase improves performa
|
||||
cloned template only needs to be compiled once, and then linked once for each clone instance.
|
||||
|
||||
|
||||
## Directive
|
||||
# Directive
|
||||
|
||||
A directive is a behavior which should be triggered when specific HTML constructs are encountered
|
||||
during the compilation process. The directives can be placed in element names, attributes, class
|
||||
@@ -68,7 +59,7 @@ api/ng.directive:ngBind `ng-bind`} directive.
|
||||
</pre>
|
||||
|
||||
A directive is just a function which executes when the compiler encounters it in the DOM. See {@link
|
||||
api/ng.$compileProvider#methods_directive directive API} for in-depth documentation on how
|
||||
api/ng.$compileProvider#directive directive API} for in-depth documentation on how
|
||||
to write directives.
|
||||
|
||||
Here is a directive which makes any element draggable. Notice the `draggable` attribute on the
|
||||
@@ -86,13 +77,13 @@ Here is a directive which makes any element draggable. Notice the `draggable` at
|
||||
backgroundColor: 'lightgrey',
|
||||
cursor: 'pointer'
|
||||
});
|
||||
element.on('mousedown', function(event) {
|
||||
element.bind('mousedown', function(event) {
|
||||
// Prevent default dragging of selected content
|
||||
event.preventDefault();
|
||||
startX = event.screenX - x;
|
||||
startY = event.screenY - y;
|
||||
$document.on('mousemove', mousemove);
|
||||
$document.on('mouseup', mouseup);
|
||||
$document.bind('mousemove', mousemove);
|
||||
$document.bind('mouseup', mouseup);
|
||||
});
|
||||
|
||||
function mousemove(event) {
|
||||
@@ -117,261 +108,35 @@ Here is a directive which makes any element draggable. Notice the `draggable` at
|
||||
</example>
|
||||
|
||||
|
||||
The presence of the `draggable` attribute on any element gives the element new behavior.
|
||||
We extended the vocabulary of the browser in a way which is natural to anyone who is familiar with the principles of HTML.
|
||||
The presence of the `draggable` attribute on any element gives the element new behavior. The beauty of
|
||||
this approach is that we have taught the browser a new trick. We have extended the vocabulary of
|
||||
what the browser understands in a way which is natural to anyone who is familiar with HTML
|
||||
principles.
|
||||
|
||||
|
||||
## Understanding View
|
||||
# Understanding View
|
||||
|
||||
Most other templating systems consume a static string template and
|
||||
There are many templating systems out there. Most of them consume a static string template and
|
||||
combine it with data, resulting in a new string. The resulting text is then `innerHTML`ed into
|
||||
an element.
|
||||
|
||||
<img src="img/One_Way_Data_Binding.png">
|
||||
|
||||
This means that any changes to the data need to be re-merged with the template and then
|
||||
`innerHTML`ed into the DOM. Some of the issues with this approach are:
|
||||
`innerHTML`ed into the DOM. Some of the issues with this approach are: reading user input and merging it with data,
|
||||
clobbering user input by overwriting it, managing the whole update process, and lack of behavior
|
||||
expressiveness.
|
||||
|
||||
1. reading user input and merging it with data
|
||||
2. clobbering user input by overwriting it
|
||||
3. managing the whole update process
|
||||
4. lack of behavior expressiveness
|
||||
|
||||
Angular is different. The Angular compiler consumes the DOM, not string templates.
|
||||
Angular is different. The Angular compiler consumes the DOM with directives, not string templates.
|
||||
The result is a linking function, which when combined with a scope model results in a live view. The
|
||||
view and scope model bindings are transparent. The developer does not need to make any special calls to update
|
||||
the view. And because `innerHTML` is not used, you won't accidentally clobber user input.
|
||||
view and scope model bindings are transparent. No action from the developer is needed to update
|
||||
the view. And because no `innerHTML` is used there are no issues of clobbering user input.
|
||||
Furthermore, Angular directives can contain not just text bindings, but behavioral constructs as
|
||||
well.
|
||||
|
||||
<img src="img/Two_Way_Data_Binding.png">
|
||||
|
||||
The Angular approach produces a stable DOM. The DOM element instance bound to a model
|
||||
The Angular approach produces a stable DOM. This means that the DOM element instance bound to a model
|
||||
item instance does not change for the lifetime of the binding. This means that the code can get
|
||||
hold of the elements and register event handlers and know that the reference will not be destroyed
|
||||
by template data merge.
|
||||
|
||||
|
||||
|
||||
## How directives are compiled
|
||||
|
||||
It's important to note that Angular operates on DOM nodes rather than strings. Usually, you don't
|
||||
notice this restriction because when a page loads, the web browser parses HTML into the DOM automatically.
|
||||
|
||||
However it's important to keep this in mind when calling `$compile` yourself, because passing it a string
|
||||
will fail. Instead, use `angular.element` to convert a string to DOM before passing elements into
|
||||
Angular's `$compile` service.
|
||||
|
||||
HTML compilation happens in three phases:
|
||||
|
||||
1. {@link api/ng.$compile `$compile`} traverses the DOM and matches directives.
|
||||
|
||||
If the compiler finds that an element matches a directive, then the directive is added to the list of
|
||||
directives that match the DOM element. A single element may match multiple directives.
|
||||
|
||||
2. Once all directives matching a DOM element have been identified, the compiler sorts the directives
|
||||
by their `priority`.
|
||||
|
||||
Each directive's `compile` functions are executed. Each `compile` function has a chance to
|
||||
modify the DOM. Each `compile` function returns a `link` function. These functions are composed into
|
||||
a "combined" link function, which invokes each directive's returned `link` function.
|
||||
|
||||
3. `$compile` links the template with the scope by calling the combined linking function from the previous step.
|
||||
This in turn will call the linking function of the individual directives, registering listeners on the elements
|
||||
and setting up {@link api/ng.$rootScope.Scope#methods_$watch `$watch`s} with the {@link api/ng.$rootScope.Scope `scope`}
|
||||
as each directive is configured to do.
|
||||
|
||||
The result of this is a live binding between the scope and the DOM. So at this point, a change in
|
||||
a model on the compiled scope will be reflected in the DOM.
|
||||
|
||||
Below is the corresponding code using the `$compile` service.
|
||||
This should help give you an idea of what Angular does internally.
|
||||
|
||||
<pre>
|
||||
var $compile = ...; // injected into your code
|
||||
var scope = ...;
|
||||
|
||||
var html = '<div ng-bind="exp"></div>';
|
||||
|
||||
// Step 1: parse HTML into DOM element
|
||||
var template = angular.element(html);
|
||||
|
||||
// Step 2: compile the template
|
||||
var linkFn = $compile(template);
|
||||
|
||||
// Step 3: link the compiled template with the scope.
|
||||
linkFn(scope);
|
||||
</pre>
|
||||
|
||||
### The difference between Compile and Link
|
||||
|
||||
At this point you may wonder why the compile process has separate compile and link phases. The
|
||||
short answer is that compile and link separation is needed any time a change in a model causes
|
||||
a change in the **structure** of the DOM.
|
||||
|
||||
It's rare for directives to have a **compile function**, since most directives are concerned with
|
||||
working with a specific DOM element instance rather than changing its overall structure.
|
||||
|
||||
Directives often have a **link function**. A link function allows the directive to register
|
||||
listeners to the specific cloned DOM element instance as well as to copy content into the DOM
|
||||
from the scope.
|
||||
|
||||
<div class="alert alert-success">
|
||||
**Best Practice:** Any operation which can be shared among the instance of directives should be
|
||||
moved to the compile function for performance reasons.
|
||||
</div>
|
||||
|
||||
#### An Example of "Compile" Versus "Link"
|
||||
|
||||
To understand, let's look at a real-world example with `ngRepeat`:
|
||||
|
||||
<pre>
|
||||
Hello {{user}}, you have these actions:
|
||||
<ul>
|
||||
<li ng-repeat="action in user.actions">
|
||||
{{action.description}}
|
||||
</li>
|
||||
</ul>
|
||||
</pre>
|
||||
|
||||
When the above example is compiled, the compiler visits every node and looks for directives.
|
||||
|
||||
`{{user}}` matches the {@link api/ng.$interpolate interpolation directive}
|
||||
and `ng-repeat` matches the {@link api/ng.directive:ngRepeat `ngRepeat` directive}.
|
||||
|
||||
But {@link api/ng.directive:ngRepeat ngRepeat} has a dilemma.
|
||||
|
||||
It needs to be able to clone new `<li>` elements for every `action` in `user.actions`.
|
||||
This initially seems trivial, but it becomes more complicated when you consider that `user.actions`
|
||||
might have items added to it later. This means that it needs to save a clean copy of the `<li>`
|
||||
element for cloning purposes.
|
||||
|
||||
As new `action`s are inserted, the template `<li>` element needs to be cloned and inserted into `ul`.
|
||||
But cloning the `<li>` element is not enough. It also needs to compile the `<li>` so that its
|
||||
directives, like `{{action.description}}`, evaluate against the right {@link api/ng.$rootScope.Scope scope}.
|
||||
|
||||
|
||||
A naive approach to solving this problem would be to simply insert a copy of the `<li>` element and
|
||||
then compile it.
|
||||
The problem with this approach is that compiling on every `<li>` element that we clone would duplicate
|
||||
a lot of the work. Specifically, we'd be traversing `<li>` each time before cloning it to find the
|
||||
directives. This would cause the compilation process to be slower, in turn making applications
|
||||
less responsive when inserting new nodes.
|
||||
|
||||
The solution is to break the compilation process into two phases:
|
||||
|
||||
the **compile phase** where all of the directives are identified and sorted by priority,
|
||||
and a **linking phase** where any work which "links" a specific instance of the
|
||||
{@link api/ng.$rootScope.Scope scope} and the specific instance of an `<li>` is performed.
|
||||
|
||||
<div class="alert alert-warning">
|
||||
**Note:** *Link* means setting up listeners on the DOM and setting up `$watch` on the Scope to
|
||||
keep the two in sync.
|
||||
</div>
|
||||
|
||||
{@link api/ng.directive:ngRepeat `ngRepeat`} works by preventing the compilation process from
|
||||
descending into the `<li>` element so it can make a clone of the original and handle inserting
|
||||
and removing DOM nodes itself.
|
||||
|
||||
Instead the {@link api/ng.directive:ngRepeat `ngRepeat`} directive compiles `<li>` separately.
|
||||
The result of the `<li>` element compilation is a linking function which contains all of the
|
||||
directives contained in the `<li>` element, ready to be attached to a specific clone of the `<li>`
|
||||
element.
|
||||
|
||||
At runtime the {@link api/ng.directive:ngRepeat `ngRepeat`} watches the expression and as items
|
||||
are added to the array it clones the `<li>` element, creates a new
|
||||
{@link api/ng.$rootScope.Scope scope} for the cloned `<li>` element and calls the link function
|
||||
on the cloned `<li>`.
|
||||
|
||||
|
||||
|
||||
### Understanding How Scopes Work with Transcluded Directives
|
||||
|
||||
One of the most common use cases for directives is to create reusable components.
|
||||
|
||||
Below is a pseudo code showing how a simplified dialog component may work.
|
||||
|
||||
<pre>
|
||||
<div>
|
||||
<button ng-click="show=true">show</button>
|
||||
|
||||
<dialog title="Hello {{username}}."
|
||||
visible="show"
|
||||
on-cancel="show = false"
|
||||
on-ok="show = false; doSomething()">
|
||||
Body goes here: {{username}} is {{title}}.
|
||||
</dialog>
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
Clicking on the "show" button will open the dialog. The dialog will have a title, which is
|
||||
data bound to `username`, and it will also have a body which we would like to transclude
|
||||
into the dialog.
|
||||
|
||||
Here is an example of what the template definition for the `dialog` widget may look like.
|
||||
|
||||
<pre>
|
||||
<div ng-show="visible">
|
||||
<h3>{{title}}</h3>
|
||||
<div class="body" ng-transclude></div>
|
||||
<div class="footer">
|
||||
<button ng-click="onOk()">Save changes</button>
|
||||
<button ng-click="onCancel()">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
This will not render properly, unless we do some scope magic.
|
||||
|
||||
The first issue we have to solve is that the dialog box template expects `title` to be defined.
|
||||
But we would like the template's scope property `title` to be the result of interpolating the
|
||||
`<dialog>` element's `title` attribute (i.e. `"Hello {{username}}"`. Furthermore, the buttons expect
|
||||
the `onOk` and `onCancel` functions to be present in the scope. This limits the usefulness of the
|
||||
widget. To solve the mapping issue we use the `locals` to create local variables which the template
|
||||
expects as follows:
|
||||
|
||||
<pre>
|
||||
scope: {
|
||||
title: '@', // the title uses the data-binding from the parent scope
|
||||
onOk: '&', // create a delegate onOk function
|
||||
onCancel: '&', // create a delegate onCancel function
|
||||
visible: '=' // set up visible to accept data-binding
|
||||
}
|
||||
</pre>
|
||||
|
||||
Creating local properties on widget scope creates two problems:
|
||||
|
||||
1. isolation - if the user forgets to set `title` attribute of the dialog widget the dialog
|
||||
template will bind to parent scope property. This is unpredictable and undesirable.
|
||||
|
||||
2. transclusion - the transcluded DOM can see the widget locals, which may overwrite the
|
||||
properties which the transclusion needs for data-binding. In our example the `title`
|
||||
property of the widget clobbers the `title` property of the transclusion.
|
||||
|
||||
|
||||
To solve the issue of lack of isolation, the directive declares a new `isolated` scope. An
|
||||
isolated scope does not prototypically inherit from the parent scope, and therefore we don't have
|
||||
to worry about accidentally clobbering any properties.
|
||||
|
||||
However `isolated` scope creates a new problem: if a transcluded DOM is a child of the widget
|
||||
isolated scope then it will not be able to bind to anything. For this reason the transcluded scope
|
||||
is a child of the original scope, before the widget created an isolated scope for its local
|
||||
variables. This makes the transcluded and widget isolated scope siblings.
|
||||
|
||||
This may seem to be unexpected complexity, but it gives the widget user and developer the least
|
||||
surprise.
|
||||
|
||||
Therefore the final directive definition looks something like this:
|
||||
|
||||
<pre>
|
||||
transclude: true,
|
||||
scope: {
|
||||
title: '@', // the title uses the data-binding from the parent scope
|
||||
onOk: '&', // create a delegate onOk function
|
||||
onCancel: '&', // create a delegate onCancel function
|
||||
visible: '=' // set up visible to accept data-binding
|
||||
},
|
||||
restrict: 'E',
|
||||
replace: true
|
||||
</pre>
|
||||
|
||||
|
||||
+395
-328
@@ -2,383 +2,450 @@
|
||||
@name Conceptual Overview
|
||||
@description
|
||||
|
||||
There are some concepts within Angular that you should understand before creating your first application.
|
||||
This section touches all important parts of Angular really quickly using a simple example.
|
||||
However, it won't explain all details.
|
||||
For a more in-depth explanation, have a look at the {@link tutorial/ tutorial}.
|
||||
# Overview
|
||||
|
||||
| Concept | Description |
|
||||
|------------------|------------------------------------------|
|
||||
|{@link concepts#template Template} | HTML with additional markup |
|
||||
|{@link concepts#directive Directives} | extend HTML with custom attributes and elements |
|
||||
|{@link concepts#model Model} | the data that is shown to the user and with which the user interacts |
|
||||
|{@link concepts#scope Scope} | context where the model is stored so that controllers, directives and expressions can access it |
|
||||
|{@link concepts#expression Expressions} | access variables and functions from the scope |
|
||||
|{@link concepts#compiler Compiler} | parses the template and instantiates directives and expressions |
|
||||
|{@link concepts#filter Filter} | formats the value of an expression for display to the user |
|
||||
|{@link concepts#view View} | what the user sees (the DOM) |
|
||||
|{@link concepts#databinding Data Binding} | sync data between the model and the view |
|
||||
|{@link concepts#controller Controller} | the business logic behind views |
|
||||
|{@link concepts#di Dependency Injection} | Creates and wires objects / functions |
|
||||
|{@link concepts#injector Injector} | dependency injection container |
|
||||
|{@link concepts#module Module} | configures the Injector |
|
||||
|{@link concepts#service Service} | reusable business logic independent of views |
|
||||
This document gives a quick overview of the main angular components and how they work together.
|
||||
These are:
|
||||
|
||||
* {@link concepts#startup startup} - bring up hello world
|
||||
* {@link concepts#runtime runtime} - overview of angular runtime
|
||||
* {@link concepts#scope scope} - the glue between the view and the controller
|
||||
* {@link concepts#controller controller} - application behavior
|
||||
* {@link concepts#model model} - your application data
|
||||
* {@link concepts#view view} - what the user sees
|
||||
* {@link concepts#directives directives} - extend HTML vocabulary
|
||||
* {@link concepts#filters filters} - format the data in user locale
|
||||
* {@link concepts#injector injector} - assembles your application
|
||||
* {@link concepts#module module} - configures the injector
|
||||
* {@link concepts#angular_namespace `$`} - angular namespace
|
||||
|
||||
# A first example: Data binding
|
||||
<a name="startup"></a>
|
||||
# Startup
|
||||
|
||||
In the following we will build a form to calculate the costs of an invoice in different currencies.
|
||||
This is how we get the ball rolling (refer to the diagram and example below):
|
||||
|
||||
Let's start with input fields for quantity and cost whose values are multiplied to produce the total of the invoice:
|
||||
<img class="pull-right" style="padding-left: 3em;" src="img/guide/concepts-startup.png">
|
||||
|
||||
1. The browser loads the HTML and parses it into a DOM
|
||||
2. The browser loads `angular.js` script
|
||||
3. Angular waits for `DOMContentLoaded` event
|
||||
4. Angular looks for {@link api/ng.directive:ngApp ng-app}
|
||||
{@link guide/directive directive}, which designates the application boundary
|
||||
5. The {@link guide/module Module} specified in {@link
|
||||
api/ng.directive:ngApp ng-app} (if any) is used to configure
|
||||
the {@link api/AUTO.$injector $injector}
|
||||
6. The {@link api/AUTO.$injector $injector} is used to create the {@link
|
||||
api/ng.$compile $compile} service as well as {@link
|
||||
api/ng.$rootScope $rootScope}
|
||||
7. The {@link api/ng.$compile $compile} service is used to compile the DOM and link
|
||||
it with {@link api/ng.$rootScope $rootScope}
|
||||
8. The {@link api/ng.directive:ngInit ng-init} {@link
|
||||
guide/directive directive} assigns `World` to the `name` property on the {@link guide/scope
|
||||
scope}
|
||||
9. The `{{name}}` {@link api/ng.$interpolate interpolates} the expression to
|
||||
`Hello World!`
|
||||
|
||||
<example>
|
||||
<file name="index.html">
|
||||
<div ng-init="qty=1;cost=2">
|
||||
<b>Invoice:</b>
|
||||
<div>
|
||||
Quantity: <input type="number" ng-model="qty" required >
|
||||
</div>
|
||||
<div>
|
||||
Costs: <input type="number" ng-model="cost" required >
|
||||
</div>
|
||||
<div>
|
||||
<b>Total:</b> {{qty * cost | currency}}
|
||||
</div>
|
||||
</div>
|
||||
<p ng-init=" name='World' ">Hello {{name}}!</p>
|
||||
</file>
|
||||
</example>
|
||||
|
||||
Try out the Live Preview above, and then let's walk through the example and describe what's going on.
|
||||
|
||||
<img class="pull-right" style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-databinding1.png">
|
||||
<a name="runtime"></a>
|
||||
# Runtime
|
||||
|
||||
This looks like normal HTML, with some new markup. In Angular, a file like this is called a
|
||||
<a name="template">"{@link templates template}"</a>. When Angular starts your application, it parses and
|
||||
processes this new markup from the template using the so called <a name="compiler">"{@link compiler compiler}"</a>.
|
||||
The loaded, transformed and rendered DOM is then called the <a name="view">"view"</a>.
|
||||
<img class="pull-right" style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-runtime.png">
|
||||
|
||||
The first kind of new markup are the so called <a name="directive">"{@link directive directives}"</a>.
|
||||
They apply special behavior to attributes or elements in the HTML. In the example above we use the
|
||||
{@link api/ng.directive:ngApp `ng-app`} attribute, which is linked to a directive that automatically
|
||||
initializes our application. Angular also defines a directive for the {@link api/ng.directive:input `input`}
|
||||
element that adds extra behavior to the element. E.g. it is able to automatically validate that the entered
|
||||
text is non empty by evaluating the `required` attribute.
|
||||
The {@link api/ng.directive:ngModel `ng-model`} directive stores/updates
|
||||
the value of the input field into/from a variable and shows the validation state of the input field by
|
||||
adding css classes. In the example we use these css classes to mark an empty input field with a red border.
|
||||
The diagram and the example below describe how Angular interacts with the browser's event loop.
|
||||
|
||||
<div class="alert alert-info">
|
||||
**Custom directives to access the DOM**: In Angular, the only place where an application touches the DOM is
|
||||
within directives. This is good as artifacts that access the DOM are hard to test.
|
||||
If you need to access the DOM directly you should write a custom directive for this. The
|
||||
{@link directive directives guide} explains how to do this.
|
||||
1. The browser's event-loop waits for an event to arrive. An event is a user interaction, timer event,
|
||||
or network event (response from a server).
|
||||
2. The event's callback gets executed. This enters the JavaScript context. The callback can
|
||||
modify the DOM structure.
|
||||
3. Once the callback executes, the browser leaves the JavaScript context and
|
||||
re-renders the view based on DOM changes.
|
||||
|
||||
Angular modifies the normal JavaScript flow by providing its own event processing loop. This
|
||||
splits the JavaScript into classical and Angular execution context. Only operations which are
|
||||
applied in Angular execution context will benefit from Angular data-binding, exception handling,
|
||||
property watching, etc... You can also use $apply() to enter Angular execution context from JavaScript. Keep in
|
||||
mind that in most places (controllers, services) $apply has already been called for you by the
|
||||
directive which is handling the event. An explicit call to $apply is needed only when
|
||||
implementing custom event callbacks, or when working with third-party library callbacks.
|
||||
|
||||
1. Enter Angular execution context by calling {@link guide/scope scope}`.`{@link
|
||||
api/ng.$rootScope.Scope#$apply $apply}`(stimulusFn)`. Where `stimulusFn` is
|
||||
the work you wish to do in Angular execution context.
|
||||
2. Angular executes the `stimulusFn()`, which typically modifies application state.
|
||||
3. Angular enters the {@link api/ng.$rootScope.Scope#$digest $digest} loop. The
|
||||
loop is made up of two smaller loops which process {@link
|
||||
api/ng.$rootScope.Scope#$evalAsync $evalAsync} queue and the {@link
|
||||
api/ng.$rootScope.Scope#$watch $watch} list. The {@link
|
||||
api/ng.$rootScope.Scope#$digest $digest} loop keeps iterating until the model
|
||||
stabilizes, which means that the {@link api/ng.$rootScope.Scope#$evalAsync
|
||||
$evalAsync} queue is empty and the {@link api/ng.$rootScope.Scope#$watch
|
||||
$watch} list does not detect any changes.
|
||||
4. The {@link api/ng.$rootScope.Scope#$evalAsync $evalAsync} queue is used to
|
||||
schedule work which needs to occur outside of current stack frame, but before the browser's
|
||||
view render. This is usually done with `setTimeout(0)`, but the `setTimeout(0)` approach
|
||||
suffers from slowness and may cause view flickering since the browser renders the view after
|
||||
each event.
|
||||
5. The {@link api/ng.$rootScope.Scope#$watch $watch} list is a set of expressions
|
||||
which may have changed since last iteration. If a change is detected then the `$watch`
|
||||
function is called which typically updates the DOM with the new value.
|
||||
6. Once the Angular {@link api/ng.$rootScope.Scope#$digest $digest} loop finishes
|
||||
the execution leaves the Angular and JavaScript context. This is followed by the browser
|
||||
re-rendering the DOM to reflect any changes.
|
||||
|
||||
|
||||
Here is the explanation of how the `Hello world` example achieves the data-binding effect when the
|
||||
user enters text into the text field.
|
||||
|
||||
1. During the compilation phase:
|
||||
1. the {@link api/ng.directive:ngModel ng-model} and {@link
|
||||
api/ng.directive:input input} {@link guide/directive
|
||||
directive} set up a `keydown` listener on the `<input>` control.
|
||||
2. the {@link api/ng.$interpolate {{name}} } interpolation
|
||||
sets up a {@link api/ng.$rootScope.Scope#$watch $watch} to be notified of
|
||||
`name` changes.
|
||||
2. During the runtime phase:
|
||||
1. Pressing an '`X`' key causes the browser to emit a `keydown` event on the input control.
|
||||
2. The {@link api/ng.directive:input input} directive
|
||||
captures the change to the input's value and calls {@link
|
||||
api/ng.$rootScope.Scope#$apply $apply}`("name = 'X';")` to update the
|
||||
application model inside the Angular execution context.
|
||||
3. Angular applies the `name = 'X';` to the model.
|
||||
4. The {@link api/ng.$rootScope.Scope#$digest $digest} loop begins
|
||||
5. The {@link api/ng.$rootScope.Scope#$watch $watch} list detects a change
|
||||
on the `name` property and notifies the {@link api/ng.$interpolate
|
||||
{{name}} } interpolation, which in turn updates the DOM.
|
||||
6. Angular exits the execution context, which in turn exits the `keydown` event and with it
|
||||
the JavaScript execution context.
|
||||
7. The browser re-renders the view with update text.
|
||||
|
||||
<example>
|
||||
<file name="index.html">
|
||||
<input ng-model="name">
|
||||
<p>Hello {{name}}!</p>
|
||||
</file>
|
||||
</example>
|
||||
|
||||
<a name="scope"></a>
|
||||
#Scope
|
||||
|
||||
The {@link guide/scope scope} is responsible for detecting changes to the model section and
|
||||
provides the execution context for expressions. The scopes are nested in a hierarchical structure
|
||||
which closely follow the DOM structure. (See individual directive documentation to see which
|
||||
directives cause a creation of new scopes.)
|
||||
|
||||
The following example demonstrates how the `name` {@link guide/expression expression} will evaluate
|
||||
into a different value depending on which scope it is evaluated in. The example is followed by
|
||||
a diagram depicting the scope boundaries.
|
||||
|
||||
<div class="show-scope">
|
||||
<example>
|
||||
<file name="index.html">
|
||||
<div ng-controller="GreetCtrl">
|
||||
Hello {{name}}!
|
||||
</div>
|
||||
<div ng-controller="ListCtrl">
|
||||
<ol>
|
||||
<li ng-repeat="name in names">{{name}}</li>
|
||||
</ol>
|
||||
</div>
|
||||
</file>
|
||||
<file name="script.js">
|
||||
function GreetCtrl($scope) {
|
||||
$scope.name = 'World';
|
||||
}
|
||||
|
||||
function ListCtrl($scope) {
|
||||
$scope.names = ['Igor', 'Misko', 'Vojta'];
|
||||
}
|
||||
</file>
|
||||
<file name="style.css">
|
||||
.show-scope .doc-example-live.ng-scope,
|
||||
.show-scope .doc-example-live .ng-scope {
|
||||
border: 1px solid red;
|
||||
margin: 3px;
|
||||
}
|
||||
</file>
|
||||
</example>
|
||||
</div>
|
||||
|
||||
The second kind of new markup are the double curly braces `{{ expression | filter }}`:
|
||||
When the compiler encounters this markup, it will replace it with the evaluated value of the markup.
|
||||
An <a name="expression">"{@link expression expression}"</a> in a template is a JavaScript-like code snippet that allows
|
||||
to read and write variables. Note that those variables are not global variables.
|
||||
Just like variables in a JavaScript function live in a scope,
|
||||
Angular provides a <a name="scope">"{@link scope scope}"</a> for the variables accessible to expressions.
|
||||
The values that are stored in variables on the scope are referred to as the <a name="model">"model"</a>
|
||||
in the rest of the documentation.
|
||||
Applied to the example above, the markup directs Angular to "take the data we got from the input widgets
|
||||
and multiply them together".
|
||||
|
||||
The example above also contains a <a name="filter">"{@link filter filter}"</a>.
|
||||
A filter formats the value of an expression for display to the user.
|
||||
In the example above, the filter {@link api/ng.filter:currency `currency`} formats a number
|
||||
into an output that looks like money.
|
||||
|
||||
The important thing in the example is that angular provides _live_ bindings:
|
||||
Whenever the input values change, the value of the expressions are automatically
|
||||
recalculated and the DOM is updated with their values.
|
||||
The concept behind this is <a name="databinding">"{@link databinding two-way data binding}"</a>.
|
||||
<img class="center" src="img/guide/concepts-scope.png">
|
||||
|
||||
|
||||
# Adding UI logic: Controllers
|
||||
<a name="controller"></a>
|
||||
# Controller
|
||||
|
||||
Let's add some more logic to the example that allows us to enter and calculate the costs in
|
||||
different currencies and also pay the invoice.
|
||||
<img class="pull-right" style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-controller.png">
|
||||
|
||||
<example module="invoice1">
|
||||
<file name="invoice1.js">
|
||||
angular.module('invoice1', [])
|
||||
.controller('InvoiceController', function() {
|
||||
this.qty = 1;
|
||||
this.cost = 2;
|
||||
this.inCurr = 'EUR';
|
||||
this.currencies = ['USD', 'EUR', 'CNY'];
|
||||
this.usdToForeignRates = {
|
||||
USD: 1,
|
||||
EUR: 0.74,
|
||||
CNY: 6.09
|
||||
};
|
||||
A controller is the code behind the view. Its job is to construct the model and publish it to the
|
||||
view along with callback methods. The view is a projection of the scope onto the template (the
|
||||
HTML). The scope is the glue which marshals the model to the view and forwards the events to the
|
||||
controller.
|
||||
|
||||
this.total = function total(outCurr) {
|
||||
return this.convertCurrency(this.qty * this.cost, this.inCurr, outCurr);
|
||||
};
|
||||
this.convertCurrency = function convertCurrency(amount, inCurr, outCurr) {
|
||||
return amount * this.usdToForeignRates[outCurr] * 1 / this.usdToForeignRates[inCurr];
|
||||
};
|
||||
this.pay = function pay() {
|
||||
window.alert("Thanks!");
|
||||
};
|
||||
});
|
||||
</file>
|
||||
The separation of the controller and the view is important because:
|
||||
|
||||
* The controller is written in JavaScript. JavaScript is imperative. Imperative is a good fit
|
||||
for specifying application behavior. The controller should not contain any rendering
|
||||
information (DOM references or HTML fragments).
|
||||
* The view template is written in HTML. HTML is declarative. Declarative is a good fit for
|
||||
specifying UI. The View should not contain any behavior.
|
||||
* Since the controller is unaware of the view, there could be many views for the same
|
||||
controller. This is important for re-skinning, device specific views (i.e. mobile vs desktop),
|
||||
and testability.
|
||||
|
||||
<example>
|
||||
<file name="index.html">
|
||||
<div ng-controller="InvoiceController as invoice">
|
||||
<b>Invoice:</b>
|
||||
<div>
|
||||
Quantity: <input type="number" ng-model="invoice.qty" required >
|
||||
</div>
|
||||
<div>
|
||||
Costs: <input type="number" ng-model="invoice.cost" required >
|
||||
<select ng-model="invoice.inCurr">
|
||||
<option ng-repeat="c in invoice.currencies">{{c}}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<b>Total:</b>
|
||||
<span ng-repeat="c in invoice.currencies">
|
||||
{{invoice.total(c) | currency:c}}
|
||||
</span>
|
||||
<button class="btn" ng-click="invoice.pay()">Pay</button>
|
||||
</div>
|
||||
</div>
|
||||
<div ng-controller="MyCtrl">
|
||||
Hello {{name}}!
|
||||
<button ng-click="action()">
|
||||
OK
|
||||
</button>
|
||||
</div>
|
||||
</file>
|
||||
<file name="script.js">
|
||||
function MyCtrl($scope) {
|
||||
$scope.action = function() {
|
||||
$scope.name = 'OK';
|
||||
}
|
||||
|
||||
$scope.name = 'World';
|
||||
}
|
||||
</file>
|
||||
</example>
|
||||
|
||||
What changed?
|
||||
|
||||
First, there is a new JavaScript file that contains a so called <a name="controller">"{@link controller controller}"</a>.
|
||||
More exactly, the file contains a constructor function that creates the actual controller instance.
|
||||
The purpose of controllers is to expose variables and functionality to expressions and directives.
|
||||
<a name="model"></a>
|
||||
# Model
|
||||
|
||||
Besides the new file that contains the controller code we also added a
|
||||
{@link api/ng.directive:ngController `ng-controller`} directive to the HTML.
|
||||
This directive tells angular that the new `InvoiceController` is responsible for the element with the directive
|
||||
and all of the element's children.
|
||||
The syntax `InvoiceController as invoice` tells Angular to instantiate the controller
|
||||
and save it in the variable `invoice` in the current scope.
|
||||
<img class="pull-right" style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-model.png">
|
||||
|
||||
We also changed all expressions in the page to read and write variables within that
|
||||
controller instance by prefixing them with `invoice.` . The possible currencies are defined in the controller
|
||||
and added to the template using {@link api/ng.directive:ngRepeat `ng-repeat`}.
|
||||
As the controller contains a `total` function
|
||||
we are also able to bind the result of that function to the DOM using `{{ invoice.total(...) }}`.
|
||||
The model is the data which is merged with the template to produce the view. To be able to
|
||||
render the model into the view, the model has to be able to be referenced from the scope. Unlike many
|
||||
other frameworks Angular makes no restrictions or requirements on the model. There are no classes
|
||||
to inherit from or special accessor methods for accessing or changing the model. The model can be
|
||||
primitive, object hash, or a full object Type. In short the model is a plain JavaScript object.
|
||||
|
||||
Again, this binding is live, i.e. the DOM will be automatically updated
|
||||
whenever the result of the function changes.
|
||||
The button to pay the invoice uses the directive {@link api/ng.directive:ngClick `ngClick`}. This will evaluate the
|
||||
corresponding expression whenever the button is clicked.
|
||||
|
||||
In the new JavaScript file we are also creating a {@link concepts#module module}
|
||||
at which we register the controller. We will talk about modules in the next section.
|
||||
<a name="view"></a>
|
||||
# View
|
||||
|
||||
The following graphic shows how everything works together after we introduced the controller:
|
||||
<img class="pull-right" style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-view.png">
|
||||
|
||||
<img style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-databinding2.png">
|
||||
The view is what the user sees. The view begins its life as a template, is merged with the
|
||||
model and finally rendered into the browser DOM. Angular takes a very different approach to
|
||||
rendering the view compared to most other templating systems.
|
||||
|
||||
# View independent business logic: Services
|
||||
* **Others** - Most templating systems begin as an HTML string with special templating markup.
|
||||
Often the template markup breaks the HTML syntax which means that the template can not be
|
||||
edited by an HTML editor. The template string is then parsed by the template engine, and
|
||||
merged with the data. The result of the merge is an HTML string. The HTML string is then
|
||||
written to the browser using the `.innerHTML`, which causes the browser to render the HTML.
|
||||
When the model changes the whole process needs to be repeated. The granularity of the template
|
||||
is the granularity of the DOM updates. The key here is that the templating system manipulates
|
||||
strings.
|
||||
* **Angular** - Angular is different, since its templating system works on DOM objects not on
|
||||
strings. The template is still written in an HTML string, but it is HTML (not HTML with
|
||||
template sprinkled in.) The browser parses the HTML into the DOM, and the DOM becomes the input to
|
||||
the template engine known as the {@link api/ng.$compile compiler}. The compiler
|
||||
looks for {@link guide/directive directives} which in turn set up {@link
|
||||
api/ng.$rootScope.Scope#$watch watches} on the model. The result is a
|
||||
continuously updating view which does not need template model re-merging. Your model becomes
|
||||
the single source-of-truth for your view.
|
||||
|
||||
Right now, the `InvoiceController` contains all logic of our example. When the application grows it
|
||||
is a good practise to move view independent logic from the controller into a so called
|
||||
<a name="service">"{@link dev_guide.services service}"</a>, so it can be reused by other parts
|
||||
of the application as well. Later on, we could also change that service to load the exchange rates
|
||||
from the web, e.g. by calling the Yahoo Finance API, without changing the controller.
|
||||
|
||||
Let's refactor our example and move the currency conversion into a service in another file:
|
||||
|
||||
<example module="invoice2">
|
||||
<file name="finance2.js">
|
||||
angular.module('finance2', [])
|
||||
.factory('currencyConverter', function() {
|
||||
var currencies = ['USD', 'EUR', 'CNY'],
|
||||
usdToForeignRates = {
|
||||
USD: 1,
|
||||
EUR: 0.74,
|
||||
CNY: 6.09
|
||||
};
|
||||
return {
|
||||
currencies: currencies,
|
||||
convert: convert
|
||||
};
|
||||
|
||||
function convert(amount, inCurr, outCurr) {
|
||||
return amount * usdToForeignRates[outCurr] * 1 / usdToForeignRates[inCurr];
|
||||
}
|
||||
});
|
||||
</file>
|
||||
<file name="invoice2.js">
|
||||
angular.module('invoice2', ['finance2'])
|
||||
.controller('InvoiceController', ['currencyConverter', function(currencyConverter) {
|
||||
this.qty = 1;
|
||||
this.cost = 2;
|
||||
this.inCurr = 'EUR';
|
||||
this.currencies = currencyConverter.currencies;
|
||||
|
||||
this.total = function total(outCurr) {
|
||||
return currencyConverter.convert(this.qty * this.cost, this.inCurr, outCurr);
|
||||
};
|
||||
this.pay = function pay() {
|
||||
window.alert("Thanks!");
|
||||
};
|
||||
}]);
|
||||
</file>
|
||||
<example>
|
||||
<file name="index.html">
|
||||
<div ng-controller="InvoiceController as invoice">
|
||||
<b>Invoice:</b>
|
||||
<div>
|
||||
Quantity: <input type="number" ng-model="invoice.qty" required >
|
||||
</div>
|
||||
<div>
|
||||
Costs: <input type="number" ng-model="invoice.cost" required >
|
||||
<select ng-model="invoice.inCurr">
|
||||
<option ng-repeat="c in invoice.currencies">{{c}}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<b>Total:</b>
|
||||
<span ng-repeat="c in invoice.currencies">
|
||||
{{invoice.total(c) | currency:c}}
|
||||
</span>
|
||||
<button class="btn" ng-click="invoice.pay()">Pay</button>
|
||||
</div>
|
||||
</div>
|
||||
<div ng-init="list = ['Chrome', 'Safari', 'Firefox', 'IE'] ">
|
||||
<input ng-model="list" ng-list> <br>
|
||||
<input ng-model="list" ng-list> <br>
|
||||
<pre>list={{list}}</pre> <br>
|
||||
<ol>
|
||||
<li ng-repeat="item in list">
|
||||
{{item}}
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</file>
|
||||
</example>
|
||||
|
||||
<img class="pull-right" style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-module-service.png">
|
||||
|
||||
What changed?
|
||||
We moved the `convertCurrency` function and the definition of the existing currencies
|
||||
into the new file `finance.js`. But how does the controller
|
||||
get a hold of the now separated function?
|
||||
<a name="directives"></a>
|
||||
# Directives
|
||||
|
||||
This is where <a name="di">"{@link di Dependency Injection}"</a> comes into play.
|
||||
Dependency Injection (DI) is a software design pattern that
|
||||
deals with how objects and functions get created and how they get a hold of their dependencies.
|
||||
Everything within Angular (directives, filters, controllers,
|
||||
services, ...) is created and wired using dependency injection. Within Angular,
|
||||
the DI container is called the <a name="injector">"{@link di injector}"</a>.
|
||||
A directive is a behavior or DOM transformation which is triggered by the presence of a custom attribute,
|
||||
element name, class name or comment. A directive allows you to extend the HTML vocabulary in a
|
||||
declarative fashion. Following is an example which enables data-binding for the `contenteditable`
|
||||
in HTML.
|
||||
|
||||
To use DI, there needs to be a place where all the things that should work together are registered.
|
||||
In Angular, this is the purpose of the so called <a name="module">"{@link module modules}"</a>.
|
||||
When Angular starts, it will use the configuration of the module with the name defined by the `ng-app` directive,
|
||||
including the configuration of all modules that this module depends on.
|
||||
|
||||
In the example above:
|
||||
The template contains the directive `ng-app="invoice"`. This tells Angular
|
||||
to use the `invoice` module as the main module for the application.
|
||||
The code snippet `angular.module('invoice', ['finance'])` specifies that the `invoice` module depends on the
|
||||
`finance` module. By this, Angular uses the `InvoiceController` as well as the `currencyConverter` service.
|
||||
|
||||
Now that Angular knows of all the parts of the application, it needs to create them.
|
||||
In the previous section we saw that controllers are created using a factory function.
|
||||
For services there are multiple ways to define their factory
|
||||
(see the {@link dev_guide.services service guide}).
|
||||
In the example above, we are using a function that returns the `currencyConverter` function as the factory
|
||||
for the service.
|
||||
|
||||
Back to the initial question: How does the `InvoiceController` get a reference to the `currencyConverter` function?
|
||||
In Angular, this is done by simply defining arguments on the constructor function. With this, the injector
|
||||
is able to create the objects in the right order and pass the previously created objects into the
|
||||
factories of the objects that depend on them.
|
||||
In our example, the `InvoiceController` has an argument named `currencyConverter`. By this, Angular knows about the
|
||||
dependency between the controller and the service and calls the controller with the service instance as argument.
|
||||
|
||||
The last thing that changed in the example between the previous section and this section is that we
|
||||
now pass an array to the `module.controller` function, instead of a plain function. The array first
|
||||
contains the names of the service dependencies that the controller needs. The last entry
|
||||
in the array is the controller constructor function.
|
||||
Angular uses this array syntax to define the dependencies so that the DI also works after minifying
|
||||
the code, which will most probably rename the argument name of the controller constructor function
|
||||
to something shorter like `a`.
|
||||
|
||||
# Accessing the backend
|
||||
|
||||
Let's finish our example by fetching the exchange rates from the Yahoo Finance API.
|
||||
The following example shows how this is done with Angular:
|
||||
|
||||
<example module="invoice3">
|
||||
<file name="invoice3.js">
|
||||
angular.module('invoice3', ['finance3'])
|
||||
.controller('InvoiceController', ['currencyConverter', function(currencyConverter) {
|
||||
this.qty = 1;
|
||||
this.cost = 2;
|
||||
this.inCurr = 'EUR';
|
||||
this.currencies = currencyConverter.currencies;
|
||||
|
||||
this.total = function total(outCurr) {
|
||||
return currencyConverter.convert(this.qty * this.cost, this.inCurr, outCurr);
|
||||
};
|
||||
this.pay = function pay() {
|
||||
window.alert("Thanks!");
|
||||
};
|
||||
}]);
|
||||
</file>
|
||||
<file name="finance3.js">
|
||||
angular.module('finance3', [])
|
||||
.factory('currencyConverter', ['$http', function($http) {
|
||||
var YAHOO_FINANCE_URL_PATTERN =
|
||||
'http://query.yahooapis.com/v1/public/yql?q=select * from '+
|
||||
'yahoo.finance.xchange where pair in ("PAIRS")&format=json&'+
|
||||
'env=store://datatables.org/alltableswithkeys&callback=JSON_CALLBACK',
|
||||
currencies = ['USD', 'EUR', 'CNY'],
|
||||
usdToForeignRates = {};
|
||||
refresh();
|
||||
return {
|
||||
currencies: currencies,
|
||||
convert: convert,
|
||||
refresh: refresh
|
||||
};
|
||||
|
||||
function convert(amount, inCurr, outCurr) {
|
||||
return amount * usdToForeignRates[outCurr] * 1 / usdToForeignRates[inCurr];
|
||||
}
|
||||
|
||||
function refresh() {
|
||||
var url = YAHOO_FINANCE_URL_PATTERN.
|
||||
replace('PAIRS', 'USD' + currencies.join('","USD'));
|
||||
return $http.jsonp(url).success(function(data) {
|
||||
var newUsdToForeignRates = {};
|
||||
angular.forEach(data.query.results.rate, function(rate) {
|
||||
var currency = rate.id.substring(3,6);
|
||||
newUsdToForeignRates[currency] = window.parseFloat(rate.Rate);
|
||||
<example module="directive">
|
||||
<file name="script.js">
|
||||
angular.module('directive', []).directive('contenteditable', function() {
|
||||
return {
|
||||
require: 'ngModel',
|
||||
link: function(scope, elm, attrs, ctrl) {
|
||||
// view -> model
|
||||
elm.bind('blur', function() {
|
||||
scope.$apply(function() {
|
||||
ctrl.$setViewValue(elm.html());
|
||||
});
|
||||
usdToForeignRates = newUsdToForeignRates;
|
||||
});
|
||||
|
||||
// model -> view
|
||||
ctrl.$render = function(value) {
|
||||
elm.html(value);
|
||||
};
|
||||
|
||||
// load init value from DOM
|
||||
ctrl.$setViewValue(elm.html());
|
||||
}
|
||||
}]);
|
||||
};
|
||||
});
|
||||
</file>
|
||||
<file name="index.html">
|
||||
<div ng-controller="InvoiceController as invoice">
|
||||
<b>Invoice:</b>
|
||||
<div>
|
||||
Quantity: <input type="number" ng-model="invoice.qty" required >
|
||||
</div>
|
||||
<div>
|
||||
Costs: <input type="number" ng-model="invoice.cost" required >
|
||||
<select ng-model="invoice.inCurr">
|
||||
<option ng-repeat="c in invoice.currencies">{{c}}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<b>Total:</b>
|
||||
<span ng-repeat="c in invoice.currencies">
|
||||
{{invoice.total(c) | currency:c}}
|
||||
</span>
|
||||
<button class="btn" ng-click="invoice.pay()">Pay</button>
|
||||
</div>
|
||||
</div>
|
||||
<div contentEditable="true" ng-model="content">Edit Me</div>
|
||||
<pre>model = {{content}}</pre>
|
||||
</file>
|
||||
<file name="style.css">
|
||||
div[contentEditable] {
|
||||
cursor: pointer;
|
||||
background-color: #D0D0D0;
|
||||
margin-bottom: 1em;
|
||||
padding: 1em;
|
||||
}
|
||||
</file>
|
||||
</example>
|
||||
|
||||
What changed?
|
||||
Our `currencyConverter` service of the `finance` module now uses the
|
||||
{@link api/ng.$http $http} service, a builtin service provided by Angular
|
||||
for accessing the backend. It is a wrapper around [`XMLHttpRequest`](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest)
|
||||
and [JSONP](http://en.wikipedia.org/wiki/JSONP) transports. Details can be found in the api docs of that service.
|
||||
<a name="filters"></a>
|
||||
# Filters
|
||||
|
||||
{@link api/ng.$filter Filters} perform data transformation. Typically
|
||||
they are used in conjunction with the locale to format the data in locale specific output.
|
||||
They follow the spirit of UNIX filters and use similar syntax `|` (pipe).
|
||||
|
||||
<example>
|
||||
<file name="index.html">
|
||||
<div ng-init="list = ['Chrome', 'Safari', 'Firefox', 'IE'] ">
|
||||
Number formatting: {{ 1234567890 | number }} <br>
|
||||
array filtering <input ng-model="predicate">
|
||||
{{ list | filter:predicate | json }}
|
||||
</div>
|
||||
</file>
|
||||
</example>
|
||||
|
||||
|
||||
<a name="module"></a>
|
||||
<a name="injector"></a>
|
||||
# Modules and the Injector
|
||||
|
||||
<img class="pull-right" style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-module-injector.png">
|
||||
|
||||
The {@link api/AUTO.$injector injector} is a service locator. There is a single
|
||||
{@link api/AUTO.$injector injector} per Angular {@link
|
||||
api/ng.directive:ngApp application}. The {@link
|
||||
api/AUTO.$injector injector} provides a way to look up an object instance by its
|
||||
name. The injector keeps an internal cache of all objects so that repeated calls to get the same
|
||||
object name result in the same instance. If the object does not exist, then the {@link
|
||||
api/AUTO.$injector injector} asks the instance factory to create a new instance.
|
||||
|
||||
A {@link api/angular.Module module} is a way to configure the injector's instance factory, known
|
||||
as a {@link api/AUTO.$provide provider}.
|
||||
|
||||
<pre>
|
||||
// Create a module
|
||||
var myModule = angular.module('myModule', [])
|
||||
|
||||
// Configure the injector
|
||||
myModule.factory('serviceA', function() {
|
||||
return {
|
||||
// instead of {}, put your object creation here
|
||||
};
|
||||
});
|
||||
|
||||
// create an injector and configure it from 'myModule'
|
||||
var $injector = angular.injector(['myModule']);
|
||||
|
||||
// retrieve an object from the injector by name
|
||||
var serviceA = $injector.get('serviceA');
|
||||
|
||||
// always true because of instance cache
|
||||
$injector.get('serviceA') === $injector.get('serviceA');
|
||||
</pre>
|
||||
|
||||
|
||||
But the real magic of the {@link api/AUTO.$injector injector} is that it can be
|
||||
used to {@link api/AUTO.$injector#invoke call} methods and {@link
|
||||
api/AUTO.$injector#instantiate instantiate} types. This subtle feature is what
|
||||
allows the methods and types to ask for their dependencies instead of having to look for them.
|
||||
|
||||
<pre>
|
||||
// You write functions such as this one.
|
||||
function doSomething(serviceA, serviceB) {
|
||||
// do something here.
|
||||
}
|
||||
|
||||
// Angular provides the injector for your application
|
||||
var $injector = ...;
|
||||
|
||||
///////////////////////////////////////////////
|
||||
// the old-school way of getting dependencies.
|
||||
var serviceA = $injector.get('serviceA');
|
||||
var serviceB = $injector.get('serviceB');
|
||||
|
||||
// now call the function
|
||||
doSomething(serviceA, serviceB);
|
||||
|
||||
///////////////////////////////////////////////
|
||||
// the cool way of getting dependencies.
|
||||
// the $injector will supply the arguments to the function automatically
|
||||
$injector.invoke(doSomething); // This is how the framework calls your functions
|
||||
</pre>
|
||||
|
||||
Notice that the only thing you needed to write was the function, and list the dependencies in the
|
||||
function arguments. When angular calls the function, it will use the {@link
|
||||
api/AUTO.$injector#invoke call} which will automatically fill the function
|
||||
arguments.
|
||||
|
||||
Examine the `ClockCtrl` below, and notice how it lists the dependencies in the constructor. When the
|
||||
{@link api/ng.directive:ngController ng-controller} instantiates
|
||||
the controller it automatically provides the dependencies. There is no need to create
|
||||
dependencies, look for dependencies, or even get a reference to the injector.
|
||||
|
||||
<example module="timeExampleModule">
|
||||
<file name="index.html">
|
||||
<div ng-controller="ClockCtrl">
|
||||
Current time is: {{ time.now }}
|
||||
</div>
|
||||
</file>
|
||||
<file name="script.js">
|
||||
angular.module('timeExampleModule', []).
|
||||
// Declare new object called time,
|
||||
// which will be available for injection
|
||||
factory('time', function($timeout) {
|
||||
var time = {};
|
||||
|
||||
(function tick() {
|
||||
time.now = new Date().toString();
|
||||
$timeout(tick, 1000);
|
||||
})();
|
||||
return time;
|
||||
});
|
||||
|
||||
// Notice that you can simply ask for time
|
||||
// and it will be provided. No need to look for it.
|
||||
function ClockCtrl($scope, time) {
|
||||
$scope.time = time;
|
||||
}
|
||||
</file>
|
||||
</example>
|
||||
|
||||
|
||||
<a name="angular_namespace"></a>
|
||||
# Angular Namespace
|
||||
|
||||
To prevent accidental name collision, Angular prefixes names of objects which could potentially
|
||||
collide with `$`. Please do not use the `$` prefix in your code as it may accidentally collide
|
||||
with Angular code.
|
||||
|
||||
@@ -3,10 +3,6 @@
|
||||
@name Developer Guide: E2E Testing
|
||||
@description
|
||||
|
||||
**If you're starting a new Angular project, you may want to look into
|
||||
using {@link https://github.com/angular/protractor Protractor}, as it is going to
|
||||
replace the current method of E2E Testing in the near future.**
|
||||
|
||||
As applications grow in size and complexity, it becomes unrealistic to rely on manual testing to
|
||||
verify the correctness of new features, catch bugs and notice regressions.
|
||||
|
||||
@@ -41,11 +37,6 @@ it('should filter results', function() {
|
||||
});
|
||||
});
|
||||
</pre>
|
||||
|
||||
Note that
|
||||
[`input('user')`](https://github.com/angular/angular.js/blob/master/docs/content/guide/dev_guide.e2e-testing.ngdoc#L119)
|
||||
finds the `<input>` element with `ng-model="user"` not `name="user"`.
|
||||
|
||||
This scenario describes the requirements of a Buzz Client, specifically, that it should be able to
|
||||
filter the stream of the user. It starts by entering a value in the input field with ng-model="user", clicking
|
||||
the only button on the page, and then it verifies that there are 10 items listed. It then enters
|
||||
@@ -182,6 +173,11 @@ Executes the `method` passing in `key` and `value` on the element matching the g
|
||||
`selector`, where `method` can be any of the following jQuery methods: `attr`, `prop`, `css`. The
|
||||
`label` is used for test output.
|
||||
|
||||
JavaScript is a dynamically typed language which comes with great power of expression, but it also
|
||||
come with almost no-help from the compiler. For this reason we feel very strongly that any code
|
||||
written in JavaScript needs to come with a strong set of tests. We have built many features into
|
||||
angular which makes testing your angular applications easy. So there is no excuse for not testing.
|
||||
|
||||
# Matchers
|
||||
|
||||
Matchers are used in combination with the `expect(...)` function as described above and can
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
@ngdoc overview
|
||||
@name Developer Guide: About MVC in Angular
|
||||
@description
|
||||
|
||||
While Model-View-Controller (MVC) has acquired different shades of meaning over the years since it
|
||||
first appeared, Angular incorporates the basic principles behind the original {@link
|
||||
http://en.wikipedia.org/wiki/Model–view–controller MVC} software design pattern into its way of
|
||||
building client-side web applications.
|
||||
|
||||
The MVC pattern summarized:
|
||||
|
||||
* Separate applications into distinct presentation, data, and logic components
|
||||
* Encourage loose coupling between these components
|
||||
|
||||
Along with {@link dev_guide.services services} and {@link di dependency injection}, MVC
|
||||
makes angular applications better structured, easier to maintain and more testable.
|
||||
|
||||
The following topics explain how angular incorporates the MVC pattern into the angular way of
|
||||
developing web applications:
|
||||
|
||||
* {@link dev_guide.mvc.understanding_model Understanding the Model Component}
|
||||
* {@link dev_guide.mvc.understanding_controller Understanding the Controller Component}
|
||||
* {@link dev_guide.mvc.understanding_view Understanding the View Component}
|
||||
|
||||
+24
-18
@@ -1,5 +1,5 @@
|
||||
@ngdoc overview
|
||||
@name Controllers
|
||||
@name Developer Guide: About MVC in Angular: Understanding the Controller Component
|
||||
@description
|
||||
|
||||
# Understanding Controllers
|
||||
@@ -63,7 +63,7 @@ of the Controller on the `$scope` service provided by Angular. See the guide on
|
||||
# Adding Behavior to a Scope Object
|
||||
|
||||
In order to react to events or execute computation in the view we must provide behavior to the
|
||||
scope. We add behavior to the scope by attaching methods to the `$scope` object. These methods are
|
||||
scope. We add behavior the scope by attaching methods to the `$scope` object. These methods are
|
||||
then available to be called from the template/view.
|
||||
|
||||
The following example uses a Controller to add a method to the scope, which doubles a number:
|
||||
@@ -85,7 +85,7 @@ expression in the template:
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
As discussed in the {@link concepts Concepts} section of this guide, any
|
||||
As discussed in the {@link dev_guide.mvc.understanding_model Model} section of this guide, any
|
||||
objects (or primitives) assigned to the scope become model properties. Any methods assigned to
|
||||
the scope are available in the template/view, and can be invoked via angular expressions
|
||||
and `ng` event handler directives (e.g. {@link api/ng.directive:ngClick ngClick}).
|
||||
@@ -105,11 +105,11 @@ Do not use Controllers for:
|
||||
- Any kind of DOM manipulation — Controllers should contain only business logic. DOM
|
||||
manipulation (the presentation logic of an application) is well known for being hard to test.
|
||||
Putting any presentation logic into Controllers significantly affects testability of the business
|
||||
logic. Angular offers {@link databinding databinding} for automatic DOM manipulation. If
|
||||
logic. Angular offers {@link dev_guide.templates.databinding databinding} for automatic DOM manipulation. If
|
||||
you have to perform your own manual DOM manipulation, encapsulate the presentation logic in
|
||||
{@link guide/directive directives}.
|
||||
- Input formatting — Use {@link forms angular form controls} instead.
|
||||
- Output filtering — Use {@link filter angular filters} instead.
|
||||
- Output filtering — Use {@link dev_guide.templates.filters angular filters} instead.
|
||||
- Sharing stateless or stateful code across Controllers — Use {@link dev_guide.services angular
|
||||
services} instead.
|
||||
- Managing the life-cycle of other components (for example, to create service instances).
|
||||
@@ -117,8 +117,8 @@ services} instead.
|
||||
|
||||
# Associating Controllers with Angular Scope Objects
|
||||
|
||||
You can associate Controllers with scope objects implicitly via the {@link api/ng.directive:ngController ngController
|
||||
directive} or {@link api/ngRoute.$route $route service}.
|
||||
You can associate controllers with scope objects implicitly via the {@link api/ng.directive:ngController ngController
|
||||
directive} or {@link api/ng.$route $route service}.
|
||||
|
||||
|
||||
## Simple Spicy Controller Example
|
||||
@@ -126,7 +126,7 @@ directive} or {@link api/ngRoute.$route $route service}.
|
||||
To illustrate further how Controller components work in Angular, let's create a little app with the
|
||||
following components:
|
||||
|
||||
- A {@link templates template} with two buttons and a simple message
|
||||
- A {@link dev_guide.templates template} with two buttons and a simple message
|
||||
- A model consisting of a string named `spice`
|
||||
- A Controller with two functions that set the value of `spice`
|
||||
|
||||
@@ -145,7 +145,7 @@ string "very". Depending on which button is clicked, the `spice` model is set to
|
||||
var myApp = angular.module('spicyApp1', []);
|
||||
|
||||
myApp.controller('SpicyCtrl', ['$scope', function($scope){
|
||||
$scope.spice = 'very';
|
||||
$scope.spicy = 'very';
|
||||
|
||||
$scope.chiliSpicy = function() {
|
||||
$scope.spice = 'chili';
|
||||
@@ -200,7 +200,7 @@ previous example.
|
||||
|
||||
Notice that the `SpicyCtrl` Controller now defines just one method called `spicy`, which takes one
|
||||
argument called `spice`. The template then refers to this Controller method and passes in a string
|
||||
constant `'chili'` in the binding for the first button and a model property `customSpice` (bound to an
|
||||
constant `'chili'` in the binding for the first button and a model property `spice` (bound to an
|
||||
input box) in the second button.
|
||||
|
||||
## Scope Inheritance Example
|
||||
@@ -221,7 +221,7 @@ more information about scope inheritance.
|
||||
<div ng-controller="ChildCtrl">
|
||||
<p>Good {{timeOfDay}}, {{name}}!</p>
|
||||
|
||||
<div ng-controller="GrandChildCtrl">
|
||||
<div ng-controller="BabyCtrl">
|
||||
<p>Good {{timeOfDay}}, {{name}}!</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -242,7 +242,7 @@ more information about scope inheritance.
|
||||
myApp.controller('ChildCtrl', ['$scope', function($scope){
|
||||
$scope.name = 'Mattie';
|
||||
}]);
|
||||
myApp.controller('GrandChildCtrl', ['$scope', function($scope){
|
||||
myApp.controller('BabyCtrl', ['$scope', function($scope){
|
||||
$scope.timeOfDay = 'evening';
|
||||
$scope.name = 'Gingerbreak Baby';
|
||||
}]);
|
||||
@@ -257,7 +257,7 @@ scopes being created for our view:
|
||||
- The `MainCtrl` scope, which contains `timeOfDay` and `name` properties
|
||||
- The `ChildCtrl` scope, which inherits the `timeOfDay` property but overrides (hides) the `name`
|
||||
property from the previous
|
||||
- The `GrandChildCtrl` scope, which overrides (hides) both the `timeOfDay` property defined in `MainCtrl`
|
||||
- The `BabyCtrl` scope, which overrides (hides) both the `timeOfDay` property defined in `MainCtrl`
|
||||
and the `name` property defined in `ChildCtrl`
|
||||
|
||||
Inheritance works with methods in the same way as it does with properties. So in our previous
|
||||
@@ -312,7 +312,7 @@ in your test that exists in the DOM:
|
||||
|
||||
<pre>
|
||||
describe('state', function() {
|
||||
var mainScope, childScope, grandChildScope;
|
||||
var mainScope, childScope, babyScope;
|
||||
|
||||
beforeEach(module('myApp'));
|
||||
|
||||
@@ -321,8 +321,8 @@ describe('state', function() {
|
||||
$controller('MainCtrl', {$scope: mainScope});
|
||||
childScope = mainScope.$new();
|
||||
$controller('ChildCtrl', {$scope: childScope});
|
||||
grandChildScope = childScope.$new();
|
||||
$controller('GrandChildCtrl', {$scope: grandChildScope});
|
||||
babyScope = childScope.$new();
|
||||
$controller('BabyCtrl', {$scope: babyScope});
|
||||
}));
|
||||
|
||||
it('should have over and selected', function() {
|
||||
@@ -330,11 +330,17 @@ describe('state', function() {
|
||||
expect(mainScope.name).toBe('Nikki');
|
||||
expect(childScope.timeOfDay).toBe('morning');
|
||||
expect(childScope.name).toBe('Mattie');
|
||||
expect(grandChildScope.timeOfDay).toBe('evening');
|
||||
expect(grandChildScope.name).toBe('Gingerbreak Baby');
|
||||
expect(babyScope.timeOfDay).toBe('evening');
|
||||
expect(babyScope.name).toBe('Gingerbreak Baby');
|
||||
});
|
||||
});
|
||||
</pre>
|
||||
|
||||
|
||||
## Related Topics
|
||||
|
||||
* {@link dev_guide.mvc About MVC in Angular}
|
||||
* {@link dev_guide.mvc.understanding_model Understanding the Model Component}
|
||||
* {@link dev_guide.mvc.understanding_view Understanding the View Component}
|
||||
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
@ngdoc overview
|
||||
@name Developer Guide: About MVC in Angular: Understanding the Model Component
|
||||
@description
|
||||
|
||||
Depending on the context of the discussion in the Angular documentation, the term _model_ can refer to
|
||||
either a single object representing one entity (for example, a model called "phones" with its value
|
||||
being an array of phones) or the entire data model for the application (all entities).
|
||||
|
||||
In Angular, a model is any data that is reachable as a property of an angular {@link
|
||||
scope Scope} object. The name of the property is the model identifier and the value is
|
||||
any JavaScript object (including arrays and primitives).
|
||||
|
||||
The only requirement for a JavaScript object to be a model in Angular is that the object must be
|
||||
referenced by an Angular scope as a property of that scope object. This property reference can be
|
||||
created explicitly or implicitly.
|
||||
|
||||
You can create models by explicitly creating scope properties referencing JavaScript objects in the
|
||||
following ways:
|
||||
|
||||
* Make a direct property assignment to the scope object in JavaScript code; this most commonly
|
||||
occurs in controllers:
|
||||
|
||||
function MyCtrl($scope) {
|
||||
// create property 'foo' on the MyCtrl's scope
|
||||
// and assign it an initial value 'bar'
|
||||
$scope.foo = 'bar';
|
||||
}
|
||||
|
||||
* Use an {@link expression angular expression} with an assignment operator in templates:
|
||||
|
||||
<button ng-click="{{foo='bar'}}">Click me</button>
|
||||
|
||||
* Use {@link api/ng.directive:ngInit ngInit directive} in templates (for toy/example apps
|
||||
only, not recommended for real applications):
|
||||
|
||||
<body ng-init=" foo = 'bar' ">
|
||||
|
||||
Angular creates models implicitly (by creating a scope property and assigning it a suitable value)
|
||||
when processing the following template constructs:
|
||||
|
||||
* Form input, select, textarea and other form elements:
|
||||
|
||||
<input ng-model="query" value="fluffy cloud">
|
||||
|
||||
The code above creates a model called "query" on the current scope with the value set to "fluffy
|
||||
cloud".
|
||||
|
||||
* An iterator declaration in {@link api/ng.directive:ngRepeat ngRepeater}:
|
||||
|
||||
<p ng-repeat="phone in phones"></p>
|
||||
|
||||
The code above creates one child scope for each item in the "phones" array and creates a "phone"
|
||||
object (model) on each of these scopes with its value set to the value of "phone" in the array.
|
||||
|
||||
In Angular, a JavaScript object stops being a model when:
|
||||
|
||||
* No Angular scope contains a property that references the object.
|
||||
|
||||
* All Angular scopes that contain a property referencing the object become stale and eligible for
|
||||
garbage collection.
|
||||
|
||||
The following illustration shows a simple data model created implicitly from a simple template:
|
||||
|
||||
<img src="img/guide/about_model_final.png">
|
||||
|
||||
|
||||
## Related Topics
|
||||
|
||||
* {@link dev_guide.mvc About MVC in Angular}
|
||||
* {@link dev_guide.mvc.understanding_controller Understanding the Controller Component}
|
||||
* {@link dev_guide.mvc.understanding_view Understanding the View Component}
|
||||
@@ -0,0 +1,22 @@
|
||||
@ngdoc overview
|
||||
@name Developer Guide: About MVC in Angular: Understanding the View Component
|
||||
@description
|
||||
|
||||
In Angular, the view is the DOM loaded and rendered in the browser, after Angular has transformed
|
||||
the DOM based on information in the template, controller and model.
|
||||
|
||||
<img src="img/guide/about_view_final.png">
|
||||
|
||||
In the Angular implementation of MVC, the view has knowledge of both the model and the controller.
|
||||
The view knows about the model where two-way data-binding occurs. The view has knowledge of the
|
||||
controller through Angular directives, such as {@link api/ng.directive:ngController
|
||||
ngController} and {@link api/ng.directive:ngView ngView}, and through bindings of this form:
|
||||
`{{someControllerFunction()}}`. In these ways, the view can call functions in an associated
|
||||
controller function.
|
||||
|
||||
|
||||
## Related Topics
|
||||
|
||||
* {@link dev_guide.mvc About MVC in Angular}
|
||||
* {@link dev_guide.mvc.understanding_model Understanding the Model Component}
|
||||
* {@link dev_guide.mvc.understanding_controller Understanding the Controller Component}
|
||||
@@ -217,19 +217,19 @@ it('should show example', inject(
|
||||
$locationProvider.hashPrefix('!');
|
||||
},
|
||||
function($location) {
|
||||
// open http://example.com/base/index.html#!/a
|
||||
$location.absUrl() == 'http://example.com/base/index.html#!/a'
|
||||
// open http://host.com/base/index.html#!/a
|
||||
$location.absUrl() == 'http://host.com/base/index.html#!/a'
|
||||
$location.path() == '/a'
|
||||
|
||||
$location.path('/foo')
|
||||
$location.absUrl() == 'http://example.com/base/index.html#!/foo'
|
||||
$location.absUrl() == 'http://host.com/base/index.html#!/foo'
|
||||
|
||||
$location.search() == {}
|
||||
$location.search({a: 'b', c: true});
|
||||
$location.absUrl() == 'http://example.com/base/index.html#!/foo?a=b&c'
|
||||
$location.absUrl() == 'http://host.com/base/index.html#!/foo?a=b&c'
|
||||
|
||||
$location.path('/new').search('x=y');
|
||||
$location.absUrl() == 'http://example.com/base/index.html#!/new?x=y'
|
||||
$location.absUrl() == 'http://host.com/base/index.html#!/new?x=y'
|
||||
}
|
||||
));
|
||||
</pre>
|
||||
@@ -267,31 +267,31 @@ it('should show example', inject(
|
||||
},
|
||||
function($location) {
|
||||
// in browser with HTML5 history support:
|
||||
// open http://example.com/#!/a -> rewrite to http://example.com/a
|
||||
// (replacing the http://example.com/#!/a history record)
|
||||
// open http://host.com/#!/a -> rewrite to http://host.com/a
|
||||
// (replacing the http://host.com/#!/a history record)
|
||||
$location.path() == '/a'
|
||||
|
||||
$location.path('/foo');
|
||||
$location.absUrl() == 'http://example.com/foo'
|
||||
$location.absUrl() == 'http://host.com/foo'
|
||||
|
||||
$location.search() == {}
|
||||
$location.search({a: 'b', c: true});
|
||||
$location.absUrl() == 'http://example.com/foo?a=b&c'
|
||||
$location.absUrl() == 'http://host.com/foo?a=b&c'
|
||||
|
||||
$location.path('/new').search('x=y');
|
||||
$location.url() == 'new?x=y'
|
||||
$location.absUrl() == 'http://example.com/new?x=y'
|
||||
$location.absUrl() == 'http://host.com/new?x=y'
|
||||
|
||||
// in browser without html5 history support:
|
||||
// open http://example.com/new?x=y -> redirect to http://example.com/#!/new?x=y
|
||||
// (again replacing the http://example.com/new?x=y history item)
|
||||
// open http://host.com/new?x=y -> redirect to http://host.com/#!/new?x=y
|
||||
// (again replacing the http://host.com/new?x=y history item)
|
||||
$location.path() == '/new'
|
||||
$location.search() == {x: 'y'}
|
||||
|
||||
$location.path('/foo/bar');
|
||||
$location.path() == '/foo/bar'
|
||||
$location.url() == '/foo/bar?x=y'
|
||||
$location.absUrl() == 'http://example.com/#!/foo/bar?x=y'
|
||||
$location.absUrl() == 'http://host.com/#!/foo/bar?x=y'
|
||||
}
|
||||
));
|
||||
</pre>
|
||||
@@ -391,8 +391,8 @@ In this examples we use `<base href="/base/index.html" />`
|
||||
$location.path() = {{$location.path()}}<br>
|
||||
$location.search() = {{$location.search()}}<br>
|
||||
$location.hash() = {{$location.hash()}}<br>
|
||||
<a href="http://www.example.com/base/first?a=b">/base/first?a=b</a> |
|
||||
<a href="http://www.example.com/base/sec/ond?flag#hash">sec/ond?flag#hash</a> |
|
||||
<a href="http://www.host.com/base/first?a=b">/base/first?a=b</a> |
|
||||
<a href="http://www.host.com/base/sec/ond?flag#hash">sec/ond?flag#hash</a> |
|
||||
<a href="/other-base/another?search">external</a>
|
||||
</div>
|
||||
|
||||
@@ -405,8 +405,8 @@ In this examples we use `<base href="/base/index.html" />`
|
||||
$location.path() = {{$location.path()}}<br>
|
||||
$location.search() = {{$location.search()}}<br>
|
||||
$location.hash() = {{$location.hash()}}<br>
|
||||
<a href="http://www.example.com/base/first?a=b">/base/first?a=b</a> |
|
||||
<a href="http://www.example.com/base/sec/ond?flag#hash">sec/ond?flag#hash</a> |
|
||||
<a href="http://www.host.com/base/first?a=b">/base/first?a=b</a> |
|
||||
<a href="http://www.host.com/base/sec/ond?flag#hash">sec/ond?flag#hash</a> |
|
||||
<a href="/other-base/another?search">external</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -433,8 +433,8 @@ In this examples we use `<base href="/base/index.html" />`
|
||||
}
|
||||
|
||||
var browsers = {
|
||||
html5: new FakeBrowser('http://www.example.com/base/path?a=b#h', '/base/index.html'),
|
||||
hashbang: new FakeBrowser('http://www.example.com/base/index.html#!/path?a=b#h', '/base/index.html')
|
||||
html5: new FakeBrowser('http://www.host.com/base/path?a=b#h', '/base/index.html'),
|
||||
hashbang: new FakeBrowser('http://www.host.com/base/index.html#!/path?a=b#h', '/base/index.html')
|
||||
};
|
||||
|
||||
function Html5Cntl($scope, $location) {
|
||||
@@ -447,22 +447,20 @@ In this examples we use `<base href="/base/index.html" />`
|
||||
|
||||
function initEnv(name) {
|
||||
var root = angular.element(document.getElementById(name + '-mode'));
|
||||
// We must kill a link to the injector for this element otherwise angular will
|
||||
// complain that it has been bootstrapped already.
|
||||
root.data('$injector', null);
|
||||
angular.bootstrap(root, [function($compileProvider, $locationProvider, $provide){
|
||||
$locationProvider.html5Mode(true).hashPrefix('!');
|
||||
|
||||
$provide.value('$browser', browsers[name]);
|
||||
$provide.value('$document', root);
|
||||
$provide.value('$sniffer', {history: name == 'html5'});
|
||||
|
||||
$compileProvider.directive('ngAddressBar', function() {
|
||||
return function(scope, elm, attrs) {
|
||||
var browser = browsers[attrs.browser],
|
||||
input = angular.element('<input type="text" style="width: 400px">').val(browser.url()),
|
||||
input = angular.element('<input type="text">').val(browser.url()),
|
||||
delay;
|
||||
|
||||
input.on('keypress keyup keydown', function() {
|
||||
input.bind('keypress keyup keydown', function() {
|
||||
if (!delay) {
|
||||
delay = setTimeout(fireUrlChange, 250);
|
||||
}
|
||||
@@ -481,7 +479,7 @@ In this examples we use `<base href="/base/index.html" />`
|
||||
};
|
||||
});
|
||||
}]);
|
||||
root.on('click', function(e) {
|
||||
root.bind('click', function(e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user