Compare commits
584 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fef0cfc837 | |||
| 5de845506b | |||
| 38ea542662 | |||
| 2db66f5b69 | |||
| 55fe6d6331 | |||
| f4c08fee85 | |||
| 71bc451f95 | |||
| 7e4e696ec3 | |||
| 6da44a4410 | |||
| a81195c6ca | |||
| 102a3201c1 | |||
| 59244a7776 | |||
| 293cb1fc5d | |||
| 81395ac298 | |||
| ba66c4f3cc | |||
| 4ea57e7e96 | |||
| 6e420ff28d | |||
| 5393814756 | |||
| fab59e7515 | |||
| 553c252d5c | |||
| e145a8df72 | |||
| b49d0cc6e7 | |||
| 97b171ecb2 | |||
| 245de33c00 | |||
| 8d4d437e8c | |||
| 7287dbf71d | |||
| da88449f25 | |||
| eaf1f8546d | |||
| 20d926cc45 | |||
| 9ae9c1c0da | |||
| 8a5972461c | |||
| 35d635cbcb | |||
| db2a4c04d6 | |||
| 0d62257c5f | |||
| f911b84aef | |||
| 32c09c1d19 | |||
| 26064375ca | |||
| 7a294369ab | |||
| fbab287ea2 | |||
| 254dcee93d | |||
| 69e5c369d7 | |||
| c0ccbb7b6a | |||
| b87713687e | |||
| 950ffb5a84 | |||
| 259003056d | |||
| fedc4194d9 | |||
| 16862705e1 | |||
| c694c96e4c | |||
| 5ac8a6e74a | |||
| 0e5106ec2c | |||
| 9091b77fe6 | |||
| 849f998be3 | |||
| 8bc77b68b3 | |||
| 95bd046881 | |||
| bfce9126e1 | |||
| bf2264e2aa | |||
| 5ced7b20ff | |||
| 114cf9e418 | |||
| 1b61b73f28 | |||
| d657d63a21 | |||
| c5bb3a9098 | |||
| 77edce5ded | |||
| f37cd4e4ef | |||
| 2acc91098b | |||
| 5b1c89931e | |||
| 99a2ad381b | |||
| 300263abec | |||
| b0bcf18892 | |||
| ea3b6310c9 | |||
| 764a3beecc | |||
| a603330e7a | |||
| 1f842b1c63 | |||
| 3b09f1bf4e | |||
| 561ddc9ff1 | |||
| 512ecf8f1b | |||
| 6636f1d03f | |||
| 7cccb8b777 | |||
| a275d539f9 | |||
| 17fa2468bc | |||
| fb2ae5660e | |||
| 2c4b3573cc | |||
| b2363e3102 | |||
| edfca4c769 | |||
| a9b5a1087d | |||
| 87b18b9fbe | |||
| ad128e09ff | |||
| 187b4adbd2 | |||
| 375c47d0c0 | |||
| 8fd47a1cd5 | |||
| e48c28fe92 | |||
| 10d3e1e447 | |||
| 93d1c95c61 | |||
| 01a34f513b | |||
| 916e53ce14 | |||
| b91b3119a4 | |||
| 0d60f8d367 | |||
| ca69dc6f17 | |||
| 5b7f1bcc00 | |||
| 9ab594a66c | |||
| 6c82a497c6 | |||
| df804406fb | |||
| dadce485a7 | |||
| 344cdce136 | |||
| f0347d5efa | |||
| 1c27e5fc37 | |||
| 5fb298b90f | |||
| 483325a7b5 | |||
| a86cb7d794 | |||
| c7e60153a5 | |||
| c0416866f5 | |||
| 8ba452544e | |||
| 8f7f0d26ed | |||
| 98d825e10d | |||
| 57b0d91fd8 | |||
| 9226b36572 | |||
| 39635fd0d7 | |||
| cad307fa1f | |||
| 78bc84c497 | |||
| 1f2750136e | |||
| 5b93e5fcfc | |||
| 770fd5a917 | |||
| 4b29186696 | |||
| 7b5be9ee29 | |||
| eeb261bcd5 | |||
| ef88a8a020 | |||
| 86ab885fd9 | |||
| de07ddeac6 | |||
| dc149de936 | |||
| 320f6d1214 | |||
| 1517d6d2f2 | |||
| 6bb17af2e3 | |||
| 505ead7e58 | |||
| 1da4e89385 | |||
| 83f37d78ba | |||
| d4ac25496a | |||
| e84da2283c | |||
| 3dd9572754 | |||
| 922cb7e42f | |||
| 103cb513d9 | |||
| c24e4e4ed5 | |||
| 1b46a7dcdf | |||
| 8d28d65b36 | |||
| fbb125a3af | |||
| ca7336391a | |||
| 771bccc35c | |||
| c794b96bdc | |||
| f108a2a994 | |||
| 7cbf61cabb | |||
| dfdb72559f | |||
| d69793d93c | |||
| b068c8b605 | |||
| ec16352579 | |||
| aa4ba23350 | |||
| 25e639b474 | |||
| ee8e4a946e | |||
| a41a2a1d2c | |||
| eadd8d08d3 | |||
| 602a1142e8 | |||
| 0b7fef3d94 | |||
| 809d47ec77 | |||
| f3444d495d | |||
| 612c882b83 | |||
| f2a6be3129 | |||
| 465663ed77 | |||
| 1102ffaaf8 | |||
| 98f6a82390 | |||
| a43c6e1828 | |||
| 0db301f863 | |||
| 8e6d3875c6 | |||
| b9d77d46ff | |||
| 96f94d4347 | |||
| 63831f118f | |||
| ebe280eede | |||
| 95d6cdc7c7 | |||
| 9223215add | |||
| 309cfd109f | |||
| cfc6175aab | |||
| dc39f368c3 | |||
| c0f3400573 | |||
| 822d7e5ae9 | |||
| 5874db84ab | |||
| e9e8d49216 | |||
| 550fc21ce5 | |||
| a8aba8957b | |||
| ca0ac64997 | |||
| 7678501bc9 | |||
| dec5eb6e83 | |||
| 2eff326781 | |||
| 50ce5746a7 | |||
| 1537f80267 | |||
| 021d3aa21a | |||
| e8c8c5459e | |||
| 1c20aed318 | |||
| 4c4d24a338 | |||
| 8c7b9b8de4 | |||
| f39ac571c4 | |||
| 84f36701bc | |||
| 6d4ce240de | |||
| 229a155aef | |||
| 73250089cd | |||
| a72bc4e69f | |||
| 0812061274 | |||
| d07101dec0 | |||
| 2206b99359 | |||
| 989f6f2056 | |||
| 4cb5113546 | |||
| 66c14ce84a | |||
| d224f03ef4 | |||
| fde61423cf | |||
| c29d21f4cd | |||
| 7a19a80af2 | |||
| c7e42223a2 | |||
| 220e7bf2d4 | |||
| 8d6eed21d2 | |||
| 7c34e1f1a7 | |||
| bf82c8a708 | |||
| d5f2084883 | |||
| 9bffccd935 | |||
| 6b18a564dd | |||
| 27b7fa3914 | |||
| d7ecab775c | |||
| e89139dc9d | |||
| 26169075c8 | |||
| bf01ab2a13 | |||
| 3248233f5e | |||
| 3a8bbb721d | |||
| 729fb13c9e | |||
| 9e16aaf3a9 | |||
| d3fbc25be2 | |||
| 0d034a98ec | |||
| 0c8a88ba09 | |||
| 6b5baaddb0 | |||
| 9aab5bfc03 | |||
| 18c41af065 | |||
| 33443966c8 | |||
| 8794a173f9 | |||
| 41e648a47f | |||
| 5d9d6a59d2 | |||
| 4e73c80b17 | |||
| 27873acbf0 | |||
| 4f48898728 | |||
| 0df6e20e6a | |||
| 074ad03072 | |||
| a20e76ea80 | |||
| d59678a080 | |||
| c34602007c | |||
| 8ae296823b | |||
| 2586e3a2ac | |||
| 5020d2e8f7 | |||
| 1300c74b32 | |||
| 214c65d334 | |||
| b3750e5201 | |||
| 4aac37e7be | |||
| fd09586b08 | |||
| 713f9758e2 | |||
| 794e5e6098 | |||
| f4f1f43d51 | |||
| 73daa79e91 | |||
| e71e7b6cae | |||
| c914cd99b3 | |||
| e9881991ca | |||
| c9245cf759 | |||
| 99720fb5ab | |||
| 332e935048 | |||
| 30c8207e0f | |||
| 3d6dff44f3 | |||
| 6b049c74cc | |||
| c99dd224a5 | |||
| 1b1413a9d4 | |||
| 4c4537e65e | |||
| 62761428ef | |||
| 04d7317cdd | |||
| 2cd87dbb93 | |||
| 348a77145d | |||
| 24fe1632b0 | |||
| 832be4123d | |||
| ffe5115355 | |||
| 61b2515c0d | |||
| f296e2ee12 | |||
| f4a121f6c2 | |||
| b72ea59019 | |||
| 3b5480e9fc | |||
| a4078fcae4 | |||
| 39c82f3fb7 | |||
| 1293cc88cd | |||
| cad717b117 | |||
| c2d447e378 | |||
| 75515852ea | |||
| 5fe1f39f02 | |||
| 2bce71e9dc | |||
| c8e03e34b2 | |||
| 267b217376 | |||
| 2f45133393 | |||
| 4a6a3ba7fb | |||
| 0c9abc32c0 | |||
| a9cc6efb3c | |||
| d7d3ef12a6 | |||
| 1a98b4fe02 | |||
| a5859aaf63 | |||
| dacdcc6d96 | |||
| 7cd79b6f8f | |||
| fa5ca115ac | |||
| 48b86a4eae | |||
| f827d64c2e | |||
| 4d7e1cef37 | |||
| 58b01fac1e | |||
| 84ad0a037c | |||
| 2a37690f70 | |||
| 45304a9d68 | |||
| 0478bb4a60 | |||
| 3193a3a5af | |||
| 6082e2ad16 | |||
| 39bae62f53 | |||
| d7a73e41ed | |||
| e6c35e1b6b | |||
| 0b6ba9c940 | |||
| cc1f7539d4 | |||
| 9ca685bfbd | |||
| 1b74e5ed0a | |||
| 3fbc25718e | |||
| b488bbf4bf | |||
| 696928dbc6 | |||
| cbcfaa2c8d | |||
| cafde93a40 | |||
| 1523fc7e6d | |||
| a3f70172ef | |||
| 868a2c401f | |||
| 05fbed5710 | |||
| 21dac2a3da | |||
| 481508d0e7 | |||
| 12e4d3ac4d | |||
| 4f937bda18 | |||
| b6f3d4007a | |||
| 774b2adb89 | |||
| ad6767949c | |||
| 2407891ddf | |||
| 666137d635 | |||
| 846ebb4073 | |||
| e23a6a320e | |||
| f8b11f3584 | |||
| 4c02d0bea5 | |||
| 47ec6f5d7f | |||
| 1fb47e08a0 | |||
| f8b50cd410 | |||
| 1de7411c8b | |||
| 7c8a1bfbac | |||
| 713c8e629d | |||
| 33e1bdc543 | |||
| 49f90e559e | |||
| a48a99377c | |||
| f7fad29fd9 | |||
| 896e34689d | |||
| 0b28de1e55 | |||
| 84d9a57416 | |||
| ecdb9a5688 | |||
| c6f406f03b | |||
| c663b39826 | |||
| af9e897ecd | |||
| a8f21d4c48 | |||
| 6fcf544528 | |||
| 4ee35287f0 | |||
| 3655d3ffbe | |||
| ec3ba47c4c | |||
| 2123772a65 | |||
| cb1efd818b | |||
| f5575782c4 | |||
| d85505d019 | |||
| daa83f2864 | |||
| 7c7477ce45 | |||
| 6f0503514f | |||
| 5c6f9f8e81 | |||
| 64403ff36f | |||
| 9878fee299 | |||
| 8849d70af8 | |||
| 102f986555 | |||
| 457cf0a702 | |||
| 8c121b94e7 | |||
| 24a87d90f2 | |||
| 0b35521d8f | |||
| 4a938213df | |||
| 6a5a8970a0 | |||
| 69a687e04e | |||
| b2dc078943 | |||
| 9565cca15b | |||
| cd508678cd | |||
| 0f77bd6d0a | |||
| 9b6fc8a4cf | |||
| 389d4879da | |||
| a564160511 | |||
| 06f2ba899f | |||
| 9f828a07dc | |||
| 655da39c01 | |||
| 2f7c57233a | |||
| 1192ae44f1 | |||
| f7c8bcb329 | |||
| f7d28cd377 | |||
| 2e641ac49f | |||
| 1ca22a3dc8 | |||
| bd4ffaba53 | |||
| c7e815f63b | |||
| 6483dea08c | |||
| cceb455fb1 | |||
| 3018ff7130 | |||
| c086f831fb | |||
| fab2d3c92f | |||
| 4f84f6b3e4 | |||
| cf5e463abd | |||
| f288b8f010 | |||
| b7e4e92014 | |||
| 31c450bcee | |||
| a9fcb0d0fc | |||
| a3846ab837 | |||
| 1953b0bed9 | |||
| 2b73027136 | |||
| 1079105443 | |||
| d119e36302 | |||
| 98b2f8ef18 | |||
| e7ab857ddb | |||
| 46cba2e05d | |||
| 72894f0dd2 | |||
| 760f49de10 | |||
| 686b13bf60 | |||
| 56cc7bcc98 | |||
| b4eed8ad94 | |||
| 08793a690a | |||
| ef4bf8c77c | |||
| b6ab826c4b | |||
| 71f974b459 | |||
| a68624444a | |||
| 945fc1a4bc | |||
| ec900cabfc | |||
| f99fe799e2 | |||
| e7338d3f27 | |||
| 2dfbc083c5 | |||
| 27613fd500 | |||
| e645f7cae1 | |||
| ad275b2265 | |||
| 600e6218fe | |||
| 5218c7bbdc | |||
| 5cc5cc13b9 | |||
| d5c7ef0f78 | |||
| 84fd3a18a3 | |||
| fcf4393680 | |||
| 16301bed28 | |||
| 95be253fe5 | |||
| bf4b0dbd46 | |||
| 95d119ebb2 | |||
| e609239fab | |||
| 4224cd5182 | |||
| 906fdad0f9 | |||
| a8c1d9c978 | |||
| 8829a2a86d | |||
| 84467d8697 | |||
| 0e85ca9ddb | |||
| e7face4728 | |||
| a29bff1c98 | |||
| 95522cc11f | |||
| c5f69e3f64 | |||
| dd24c78373 | |||
| 36d37c0e38 | |||
| 24699ee8f0 | |||
| aa6a0e3fc6 | |||
| 8761ddc0e3 | |||
| 058842ad04 | |||
| 431bad0183 | |||
| 5850e61c82 | |||
| d2e4e49986 | |||
| 0da6cc9118 | |||
| cc60ba1f35 | |||
| 64d58a5b52 | |||
| 3bf4390339 | |||
| e7ac7aa43b | |||
| 37781ed145 | |||
| 19ba6510d0 | |||
| bc5ceee275 | |||
| 106af49258 | |||
| d5eedf38db | |||
| c0c0b2b674 | |||
| ce1f1f97f0 | |||
| 8205158e47 | |||
| 6609e3da76 | |||
| ef210e5e11 | |||
| fd61e222c3 | |||
| 074b0675a1 | |||
| 5ed721b9b5 | |||
| c22ab5d2e2 | |||
| 339a1658cd | |||
| 29432ffe37 | |||
| caed2dfe4f | |||
| 7f4edaff6e | |||
| 6dcfccb32c | |||
| e2173f9101 | |||
| 7a78aed160 | |||
| 7aef2d54e0 | |||
| ce37ae2868 | |||
| 95f0bf9b52 | |||
| 8a0be355a9 | |||
| 849a1489c7 | |||
| f54f0f98a0 | |||
| 766b3d5c87 | |||
| 4f735b0605 | |||
| 319dd1a449 | |||
| 88a14b4e25 | |||
| 451bde1244 | |||
| 4f827f587b | |||
| 131410b61b | |||
| ca6b7d0fa2 | |||
| 40dc806e03 | |||
| 5e9835b4f2 | |||
| e0209169bf | |||
| b07afa0465 | |||
| c3b5e16d84 | |||
| 7f444a205e | |||
| 82213efff2 | |||
| ec59be67bc | |||
| 79e519feda | |||
| 7cf5544a9f | |||
| 030a9b8d33 | |||
| 310f129c1d | |||
| 0fc64ad8a1 | |||
| 12d1f5700d | |||
| 60e80509a8 | |||
| 3c12d36e73 | |||
| fd6bac7de5 | |||
| 6d525f06c0 | |||
| d7e6f1b192 | |||
| 5b9ff6cf48 | |||
| f09b6aa5b5 | |||
| 8b395ff325 | |||
| 6c9131ef10 | |||
| 99c5027bf2 | |||
| 90e60d2d54 | |||
| 928d000db7 | |||
| 42ec95ebae | |||
| 1028cfaa30 | |||
| 756c52d6c1 | |||
| c3e1a41d6f | |||
| 8dd4f14a04 | |||
| 7ba30fd2e7 | |||
| 5adea0ba64 | |||
| 2262ca6697 | |||
| cd74f74468 | |||
| fced1c0c16 | |||
| 1cdcddb5cc | |||
| 0e4d7cacad | |||
| 6a9ccacd62 | |||
| e591ddcb30 | |||
| cd0af8a771 | |||
| 51a7f9dc4a | |||
| 61eb426ab4 | |||
| 8ea8da4f11 | |||
| 07ee29c563 | |||
| 9f5d0cf79f | |||
| 1413328e6a | |||
| 7d09bd30f9 | |||
| dde1b29497 | |||
| 4ae3184c59 | |||
| ed53100a0d | |||
| 6df598d9f5 | |||
| 4aa9df7a7a | |||
| 7d5d62dafe | |||
| 524650a40e | |||
| 02a45826f1 | |||
| e324c14907 | |||
| e1cfb1957f | |||
| 2a3586381f | |||
| 834d316829 | |||
| c61be8d0e6 | |||
| 465212835f | |||
| b3acddea37 | |||
| 308598795a | |||
| 2cd09c9f0e | |||
| 34fee06ca7 | |||
| c7a46d4b8a | |||
| de065f1961 | |||
| c3ab915d2e | |||
| f4a4f42abb | |||
| b2c84ccde3 | |||
| 2b344dbd20 | |||
| cde840fdf8 | |||
| f9656dab2d | |||
| a0d759c613 | |||
| 0d421f093d | |||
| 5f937e54df |
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"disallowKeywords": ["with"],
|
||||
"disallowTrailingWhitespace": true,
|
||||
"requireRightStickedOperators": ["!"],
|
||||
"requireLeftStickedOperators": [","]
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// This is an incomplete TODO list of checks we want to start enforcing
|
||||
//
|
||||
// The goal is to enable these checks one by one by moving them to .jscs.json along with commits
|
||||
// that correct the existing code base issues and make the new check pass.
|
||||
|
||||
{
|
||||
"requireCurlyBraces": ["if", "else", "for", "while", "do", "try", "catch"],
|
||||
"requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch", "return", "try", "catch"],
|
||||
"disallowLeftStickedOperators": ["?", "+", "-", "/", "*", "=", "==", "===", "!=", "!==", ">", ">=", "<", "<="],
|
||||
"disallowRightStickedOperators": ["?", "+", "/", "*", ":", "=", "==", "===", "!=", "!==", ">", ">=", "<", "<="],
|
||||
"disallowImplicitTypeConversion": ["string"],
|
||||
"disallowMultipleLineBreaks": true,
|
||||
"disallowKeywordsOnNewLine": ["else"],
|
||||
"requireLineFeedAtFileEnd": true,
|
||||
"validateJSDoc": {
|
||||
"checkParamNames": true,
|
||||
"requireParamTypes": true
|
||||
}
|
||||
}
|
||||
@@ -2,15 +2,19 @@ language: node_js
|
||||
node_js:
|
||||
- 0.10
|
||||
|
||||
branches:
|
||||
except:
|
||||
- /^g3_.*$/
|
||||
|
||||
env:
|
||||
matrix:
|
||||
- JOB=unit
|
||||
- JOB=e2e
|
||||
- JOB=e2e TEST_TARGET=jqlite
|
||||
- JOB=e2e TEST_TARGET=jquery
|
||||
- JOB=e2e TEST_TARGET=doce2e
|
||||
global:
|
||||
- SAUCE_USERNAME=angular-ci
|
||||
- SAUCE_ACCESS_KEY=9b988f434ff8-fbca-8aa4-4ae3-35442987
|
||||
- BROWSER_STACK_USERNAME=VojtaJina
|
||||
- BROWSER_STACK_ACCESS_KEY=HAfHZaypxAc3PEUrUU9a
|
||||
- LOGS_DIR=/tmp/angular-build/logs
|
||||
- BROWSER_PROVIDER_READY_FILE=/tmp/sauce-connect-ready
|
||||
|
||||
@@ -18,9 +22,7 @@ before_script:
|
||||
- mkdir -p $LOGS_DIR
|
||||
- ./lib/sauce/sauce_connect_setup.sh
|
||||
- npm install -g grunt-cli
|
||||
- grunt bower
|
||||
- grunt bower
|
||||
- grunt package-without-bower
|
||||
- grunt package
|
||||
- ./scripts/travis/wait_for_browser_provider.sh
|
||||
|
||||
script:
|
||||
@@ -28,3 +30,11 @@ script:
|
||||
|
||||
after_script:
|
||||
- ./scripts/travis/print_logs.sh
|
||||
|
||||
notifications:
|
||||
webhooks:
|
||||
urls:
|
||||
- https://webhooks.gitter.im/e/d2120f3f2bb39a4531b2
|
||||
on_success: change # options: [always|never|change] default: always
|
||||
on_failure: always # options: [always|never|change] default: always
|
||||
on_start: false # default: false
|
||||
|
||||
@@ -1,3 +1,400 @@
|
||||
<a name="1.2.16"></a>
|
||||
# 1.2.16 badger-enumeration (2014-04-03)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$animate:**
|
||||
- ensure the CSS driver properly works with SVG elements
|
||||
([38ea5426](https://github.com/angular/angular.js/commit/38ea542662b2b74703d583e3a637d65369fc26eb),
|
||||
[#6030](https://github.com/angular/angular.js/issues/6030))
|
||||
- prevent cancellation timestamp from being too far in the future
|
||||
([35d635cb](https://github.com/angular/angular.js/commit/35d635cbcbdc20f304781655f3563111afa6567f),
|
||||
[#6748](https://github.com/angular/angular.js/issues/6748))
|
||||
- run CSS animations before JS animations to avoid style inheritance
|
||||
([0e5106ec](https://github.com/angular/angular.js/commit/0e5106ec2ccc8596c589b89074d3b27d27bf395a),
|
||||
[#6675](https://github.com/angular/angular.js/issues/6675))
|
||||
- **$parse:** mark constant unary minus expressions as constant
|
||||
([6e420ff2](https://github.com/angular/angular.js/commit/6e420ff28d9b3e76ac2c3598bf3797540ef8a1d3),
|
||||
[#6932](https://github.com/angular/angular.js/issues/6932))
|
||||
- **Scope:**
|
||||
- revert the __proto__ cleanup as that could cause regressions
|
||||
([2db66f5b](https://github.com/angular/angular.js/commit/2db66f5b695a06cff62a52e55e55d1a0a25eec2f))
|
||||
- more scope clean up on $destroy to minimize leaks
|
||||
([7e4e696e](https://github.com/angular/angular.js/commit/7e4e696ec3adf9d6fc77a7aa7e0909a9675fd43a),
|
||||
[#6794](https://github.com/angular/angular.js/issues/6794), [#6856](https://github.com/angular/angular.js/issues/6856), [#6968](https://github.com/angular/angular.js/issues/6968))
|
||||
- aggressively clean up scope on $destroy to minimize leaks
|
||||
([8d4d437e](https://github.com/angular/angular.js/commit/8d4d437e8cd8d7cebab5d9ae5c8bcfeef2118ce9),
|
||||
[#6794](https://github.com/angular/angular.js/issues/6794), [#6856](https://github.com/angular/angular.js/issues/6856))
|
||||
- **filter.ngdoc:** Check if "input" variable is defined
|
||||
([a275d539](https://github.com/angular/angular.js/commit/a275d539f9631d6ec64d03814b3b09420e6cf1ee),
|
||||
[#6819](https://github.com/angular/angular.js/issues/6819))
|
||||
- **input:** don't perform HTML5 validation on updated model-value
|
||||
([b2363e31](https://github.com/angular/angular.js/commit/b2363e31023df8240113f68b4e01d942f8009b60),
|
||||
[#6796](https://github.com/angular/angular.js/issues/6796), [#6806](https://github.com/angular/angular.js/issues/6806))
|
||||
- **ngClass:** handle ngClassOdd/Even affecting the same classes
|
||||
([55fe6d63](https://github.com/angular/angular.js/commit/55fe6d6331e501325c2658df8995dcc083fc4ffb),
|
||||
[#5271](https://github.com/angular/angular.js/issues/5271))
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- **$http:** add xhr statusText to completeRequest callback
|
||||
([32c09c1d](https://github.com/angular/angular.js/commit/32c09c1d195fcb98f6e29fc7e554a867f4762301),
|
||||
[#2335](https://github.com/angular/angular.js/issues/2335), [#2665](https://github.com/angular/angular.js/issues/2665), [#6713](https://github.com/angular/angular.js/issues/6713))
|
||||
|
||||
|
||||
<a name="v1.2.15"></a>
|
||||
# v1.2.15 beer-underestimating (2014-03-21)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$$RAFProvider:** check for webkitCancelRequestAnimationFrame
|
||||
([e84da228](https://github.com/angular/angular.js/commit/e84da2283c4e195be557f7b06c8783fe502acbbb),
|
||||
[#6526](https://github.com/angular/angular.js/issues/6526))
|
||||
- **$$rAF:** always fallback to a $timeout incase native rAF isn't supported
|
||||
([ee8e4a94](https://github.com/angular/angular.js/commit/ee8e4a946ed8f943e00846b88d8d51c0b2cd1fab),
|
||||
[#6654](https://github.com/angular/angular.js/issues/6654))
|
||||
- **$compile:** support templates with thead and tfoot root elements
|
||||
([ca0ac649](https://github.com/angular/angular.js/commit/ca0ac649971ae4fb50419b38f92a98d2226eb696),
|
||||
[#6289](https://github.com/angular/angular.js/issues/6289))
|
||||
- **$http:**
|
||||
- allow sending Blob data using $http
|
||||
([fbb125a3](https://github.com/angular/angular.js/commit/fbb125a3af164e52af2f8119175b04cbbed2f331),
|
||||
[#5012](https://github.com/angular/angular.js/issues/5012))
|
||||
- don't covert 0 status codes to 404 for non-file protocols
|
||||
([f108a2a9](https://github.com/angular/angular.js/commit/f108a2a994149ecc011e29f327bcb8e11adf72d9),
|
||||
[#6074](https://github.com/angular/angular.js/issues/6074), [#6155](https://github.com/angular/angular.js/issues/6155))
|
||||
- **$rootScope:**
|
||||
- ng-repeat can't handle NaN values. #4605
|
||||
([e48c28fe](https://github.com/angular/angular.js/commit/e48c28fe9292efe7af6205b2be116d2350990c73),
|
||||
[#4605](https://github.com/angular/angular.js/issues/4605))
|
||||
- $watchCollection should call listener with oldValue
|
||||
([3dd95727](https://github.com/angular/angular.js/commit/3dd9572754c7bafec30dd625f5c611346959c969),
|
||||
[#2621](https://github.com/angular/angular.js/issues/2621), [#5661](https://github.com/angular/angular.js/issues/5661), [#5688](https://github.com/angular/angular.js/issues/5688), [#6736](https://github.com/angular/angular.js/issues/6736))
|
||||
- **angular.bootstrap:** only allow angular to load once
|
||||
([0d60f8d3](https://github.com/angular/angular.js/commit/0d60f8d367e38224696749b0f7de04bd60649815),
|
||||
[#5863](https://github.com/angular/angular.js/issues/5863), [#5587](https://github.com/angular/angular.js/issues/5587))
|
||||
- **jqLite:** traverse `host` property for DocumentFragment in inheritedData()
|
||||
([98d825e1](https://github.com/angular/angular.js/commit/98d825e10d3bf76f47e69abba857a8933c8cb7d9),
|
||||
[#6637](https://github.com/angular/angular.js/issues/6637))
|
||||
- **ngAnimate:** setting classNameFilter disables animation inside ng-if
|
||||
([a41a2a1d](https://github.com/angular/angular.js/commit/a41a2a1d2ce20f86ac2709592e4ada527160e580),
|
||||
[#6539](https://github.com/angular/angular.js/issues/6539))
|
||||
- **ngCookie:** convert non-string values to string
|
||||
([93d1c95c](https://github.com/angular/angular.js/commit/93d1c95c61dbfa565333bb64527a103242175af7),
|
||||
[#6151](https://github.com/angular/angular.js/issues/6151), [#6220](https://github.com/angular/angular.js/issues/6220))
|
||||
- **ngTouch:** update workaround for desktop Webkit quirk
|
||||
([01a34f51](https://github.com/angular/angular.js/commit/01a34f513bb567ed6d4c81d00d7c2a777c0dae01),
|
||||
[#6302](https://github.com/angular/angular.js/issues/6302))
|
||||
- **orderBy:** support string predicates containing non-ident characters
|
||||
([10d3e1e4](https://github.com/angular/angular.js/commit/10d3e1e4472ab9f5cf4418b6438ec2e0f2b0b288),
|
||||
[#6143](https://github.com/angular/angular.js/issues/6143), [#6144](https://github.com/angular/angular.js/issues/6144))
|
||||
- **select:** avoid checking option element selected properties in render
|
||||
([dc149de9](https://github.com/angular/angular.js/commit/dc149de9364c66b988f169f67cad39577ba43434),
|
||||
[#2448](https://github.com/angular/angular.js/issues/2448), [#5994](https://github.com/angular/angular.js/issues/5994), [#6769](https://github.com/angular/angular.js/issues/6769))
|
||||
|
||||
|
||||
|
||||
<a name="1.2.14"></a>
|
||||
# 1.2.14 feisty-cryokinesis (2014-03-01)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$animate:**
|
||||
- delegate down to addClass/removeClass if setClass is not found
|
||||
([18c41af0](https://github.com/angular/angular.js/commit/18c41af065006a804a3d38eecca7ae184103ece9),
|
||||
[#6463](https://github.com/angular/angular.js/issues/6463))
|
||||
- ensure all comment nodes are removed during a leave animation
|
||||
([f4f1f43d](https://github.com/angular/angular.js/commit/f4f1f43d5140385bbf070510975f72b65196e08a),
|
||||
[#6403](https://github.com/angular/angular.js/issues/6403))
|
||||
- only block keyframes if a stagger is set to occur
|
||||
([e71e7b6c](https://github.com/angular/angular.js/commit/e71e7b6cae57f25c5837dda98551c8e0a5cb720d),
|
||||
[#4225](https://github.com/angular/angular.js/issues/4225))
|
||||
- ensure that animateable directives cancel expired leave animations
|
||||
([e9881991](https://github.com/angular/angular.js/commit/e9881991ca0a5019d3a4215477738ed247898ba0),
|
||||
[#5886](https://github.com/angular/angular.js/issues/5886))
|
||||
- ensure all animated elements are taken care of during the closing timeout
|
||||
([99720fb5](https://github.com/angular/angular.js/commit/99720fb5ab7259af37f708bc4eeda7cbbe790a69),
|
||||
[#6395](https://github.com/angular/angular.js/issues/6395))
|
||||
- fix for TypeError Cannot call method 'querySelectorAll' in cancelChildAnimations
|
||||
([c914cd99](https://github.com/angular/angular.js/commit/c914cd99b3aaf932e3c0e2a585eead7b76621f1b),
|
||||
[#6205](https://github.com/angular/angular.js/issues/6205))
|
||||
- **$http:**
|
||||
- do not add trailing question
|
||||
([c8e03e34](https://github.com/angular/angular.js/commit/c8e03e34b27a8449d8e1bfe0e3801d6a67ae2c49),
|
||||
[#6342](https://github.com/angular/angular.js/issues/6342))
|
||||
- send GET requests by default
|
||||
([267b2173](https://github.com/angular/angular.js/commit/267b217376ed466e9f260ecfdfa15a8227c103ff),
|
||||
[#5985](https://github.com/angular/angular.js/issues/5985), [#6401](https://github.com/angular/angular.js/issues/6401))
|
||||
- **$parse:** reduce false-positives in isElement tests
|
||||
([5fe1f39f](https://github.com/angular/angular.js/commit/5fe1f39f027c6f2c6a530975dd5389d788d3c0eb),
|
||||
[#4805](https://github.com/angular/angular.js/issues/4805), [#5675](https://github.com/angular/angular.js/issues/5675))
|
||||
- **input:** use ValidityState to determine validity
|
||||
([c2d447e3](https://github.com/angular/angular.js/commit/c2d447e378dd72d1b955f476bd5bf249625b4dab),
|
||||
[#4293](https://github.com/angular/angular.js/issues/4293), [#2144](https://github.com/angular/angular.js/issues/2144), [#4857](https://github.com/angular/angular.js/issues/4857), [#5120](https://github.com/angular/angular.js/issues/5120), [#4945](https://github.com/angular/angular.js/issues/4945), [#5500](https://github.com/angular/angular.js/issues/5500), [#5944](https://github.com/angular/angular.js/issues/5944))
|
||||
- **isElement:** reduce false-positives in isElement tests
|
||||
([75515852](https://github.com/angular/angular.js/commit/75515852ea9742d3d84a0f463c2a2c61ef2b7323))
|
||||
- **jqLite:**
|
||||
- properly toggle multiple classes
|
||||
([4e73c80b](https://github.com/angular/angular.js/commit/4e73c80b17bd237a8491782bcf9e19f1889e12ed),
|
||||
[#4467](https://github.com/angular/angular.js/issues/4467), [#6448](https://github.com/angular/angular.js/issues/6448))
|
||||
- make jqLite('<iframe src="someurl">').contents() return iframe document, as in jQuery
|
||||
([05fbed57](https://github.com/angular/angular.js/commit/05fbed5710b702c111c1425a9e241c40d13b0a54),
|
||||
[#6320](https://github.com/angular/angular.js/issues/6320), [#6323](https://github.com/angular/angular.js/issues/6323))
|
||||
- **numberFilter:** convert all non-finite/non-numbers/non-numeric strings to the empty string
|
||||
([cceb455f](https://github.com/angular/angular.js/commit/cceb455fb167571e26341ded6b595dafd4d92bc6),
|
||||
[#6188](https://github.com/angular/angular.js/issues/6188), [#6261](https://github.com/angular/angular.js/issues/6261))
|
||||
- **$parse:** support trailing commas in object & array literals
|
||||
([6b049c74](https://github.com/angular/angular.js/commit/6b049c74ccc9ee19688bb9bbe504c300e61776dc))
|
||||
- **ngHref:** bind ng-href to xlink:href for SVGAElement
|
||||
([2bce71e9](https://github.com/angular/angular.js/commit/2bce71e9dc10c8588f9eb599a0cd2e831440fc48),
|
||||
[#5904](https://github.com/angular/angular.js/issues/5904))
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- **$animate:** animate dirty, pristine, valid, invalid for form/fields
|
||||
([33443966](https://github.com/angular/angular.js/commit/33443966c8e8cac85a863bb181d4a4aff00baab4),
|
||||
[#5378](https://github.com/angular/angular.js/issues/5378))
|
||||
|
||||
|
||||
## Performance Improvements
|
||||
|
||||
- **$animate:** use rAF instead of timeouts to issue animation callbacks
|
||||
([4c4537e6](https://github.com/angular/angular.js/commit/4c4537e65e6cf911c9659b562d89e3330ce3ffae))
|
||||
- **$cacheFactory:** skip LRU bookkeeping for caches with unbound capacity
|
||||
([a4078fca](https://github.com/angular/angular.js/commit/a4078fcae4a33295675d769a1cd067837029da2f),
|
||||
[#6193](https://github.com/angular/angular.js/issues/6193), [#6226](https://github.com/angular/angular.js/issues/6226))
|
||||
|
||||
|
||||
|
||||
<a name="1.2.13"></a>
|
||||
# 1.2.13 romantic-transclusion (2014-02-14)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$animate:** ensure $animate doesn't break natural CSS transitions
|
||||
([4f84f6b3](https://github.com/angular/angular.js/commit/4f84f6b3e4210ae1eb14728a46d43dd961700a0c),
|
||||
[#6019](https://github.com/angular/angular.js/issues/6019))
|
||||
- **$compile:**
|
||||
- ensure element transclusion directives are linked with comment element
|
||||
([e7338d3f](https://github.com/angular/angular.js/commit/e7338d3f27e8824196136a18e1c3e0fcf51a0e28),
|
||||
[#6006](https://github.com/angular/angular.js/issues/6006), [#6101](https://github.com/angular/angular.js/issues/6101))
|
||||
- support templates with table content root nodes
|
||||
([e7338d3f](https://github.com/angular/angular.js/commit/31c450bcee53d0a3827b7e0a611e9013b2496506),
|
||||
[#2848](https://github.com/angular/angular.js/issues/2848), [#1459](https://github.com/angular/angular.js/issues/1459), [#3647](https://github.com/angular/angular.js/issues/3647), [#3241](https://github.com/angular/angular.js/issues/3241))
|
||||
- **input:**
|
||||
- don't apply textInput to `<input type="file">`
|
||||
([a9fcb0d0](https://github.com/angular/angular.js/commit/a9fcb0d0fc6456f80501b8820d02b04d7c15b6d6),
|
||||
[#6247](https://github.com/angular/angular.js/issues/6247), [#6231](https://github.com/angular/angular.js/issues/6231))
|
||||
- setViewValue on compositionend
|
||||
([2b730271](https://github.com/angular/angular.js/commit/2b7302713674506fdbcdc396c38f18dcb90dee8c),
|
||||
[#6058](https://github.com/angular/angular.js/issues/6058), [#5433](https://github.com/angular/angular.js/issues/5433))
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- **filterFilter:** support deeply nested predicate objects
|
||||
([b4eed8ad](https://github.com/angular/angular.js/commit/b4eed8ad94ce9719540462c1ee969dfd3c6b2355),
|
||||
[#6215](https://github.com/angular/angular.js/issues/6215))
|
||||
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
- **$animate:**
|
||||
- due to [4f84f6b3](https://github.com/angular/angular.js/commit/4f84f6b3e4210ae1eb14728a46d43dd961700a0c),
|
||||
ngClass and {{ class }} will now call the `setClass`
|
||||
animation callback instead of addClass / removeClass when both a
|
||||
addClass/removeClass operation is being executed on the element during the animation.
|
||||
|
||||
Please include the setClass animation callback as well as addClass and removeClass within
|
||||
your JS animations to work with ngClass and {{ class }} directives.
|
||||
|
||||
|
||||
- due to [cf5e463a](https://github.com/angular/angular.js/commit/cf5e463abd2c23f62e9c2e6361e6c53048c8910e),
|
||||
Both the `$animate:before` and `$animate:after` DOM events must be now
|
||||
registered prior to the $animate operation taking place. The `$animate:close` event
|
||||
can be registered anytime afterwards.
|
||||
|
||||
DOM callbacks used to fired for each and every animation operation that occurs within the
|
||||
$animate service provided in the ngAnimate module. This may end up slowing down an
|
||||
application if 100s of elements are being inserted into the page. Therefore after this
|
||||
change callbacks are only fired if registered on the element being animated.
|
||||
|
||||
|
||||
<a name="1.2.12"></a>
|
||||
# 1.2.12 cauliflower-eradication (2014-02-07)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$compile:** retain CSS classes added in cloneAttachFn on asynchronous directives
|
||||
([5ed721b9](https://github.com/angular/angular.js/commit/5ed721b9b5e95ae08450e1ae9d5202e7f3f79295),
|
||||
[#5439](https://github.com/angular/angular.js/issues/5439), [#5617](https://github.com/angular/angular.js/issues/5617))
|
||||
- **$http:**
|
||||
- ignore xhr.responseType setter exception if value is "json"
|
||||
([24699ee8](https://github.com/angular/angular.js/commit/24699ee8f04c1f1459be1d36207e654421d58ff0),
|
||||
[#6115](https://github.com/angular/angular.js/issues/6115), [#6122](https://github.com/angular/angular.js/issues/6122))
|
||||
- update httpBackend to use ActiveXObject on IE8 if necessary
|
||||
([ef210e5e](https://github.com/angular/angular.js/commit/ef210e5e119db4f5bfc9d2428b19f9b335c4f976),
|
||||
[#5677](https://github.com/angular/angular.js/issues/5677), [#5679](https://github.com/angular/angular.js/issues/5679))
|
||||
- **$locale:** minor grammar amends for the locale `locale_lt`
|
||||
([95be253f](https://github.com/angular/angular.js/commit/95be253fe55d35336d425d3d600a36158fc3519d),
|
||||
[#6164](https://github.com/angular/angular.js/issues/6164))
|
||||
- **$q:** make $q.reject support `finally` and `catch`
|
||||
([074b0675](https://github.com/angular/angular.js/commit/074b0675a1f97dce07f520f1ae6198ed3c604000),
|
||||
[#6048](https://github.com/angular/angular.js/issues/6048), [#6076](https://github.com/angular/angular.js/issues/6076))
|
||||
- **docs:** clarify doc for "args" in $broadcast and $emit
|
||||
([caed2dfe](https://github.com/angular/angular.js/commit/caed2dfe4feeac5d19ecea2dbb1456b7fde21e6d),
|
||||
[#6047](https://github.com/angular/angular.js/issues/6047))
|
||||
- **filterFilter:** don't interpret dots in predicate object fields as paths
|
||||
([339a1658](https://github.com/angular/angular.js/commit/339a1658cd9bfa5e322a01c45aa0a1df67e3a842),
|
||||
[#6005](https://github.com/angular/angular.js/issues/6005), [#6009](https://github.com/angular/angular.js/issues/6009))
|
||||
- **http:** make jshint happy
|
||||
([6609e3da](https://github.com/angular/angular.js/commit/6609e3da76dd898cfe85f75f23ab2e39fee65fe5))
|
||||
- **jqLite:** trim HTML string in jqLite constructor
|
||||
([36d37c0e](https://github.com/angular/angular.js/commit/36d37c0e3880c774d20c014ade60d2331beefa15),
|
||||
[#6053](https://github.com/angular/angular.js/issues/6053))
|
||||
- **mocks:**
|
||||
- rename mock.animate to ngAnimateMock and ensure it contains all test helper code for ngAnimate
|
||||
([4224cd51](https://github.com/angular/angular.js/commit/4224cd5182bc93e4a210f75e0a4e4de7f3c544e8),
|
||||
[#5822](https://github.com/angular/angular.js/issues/5822), [#5917](https://github.com/angular/angular.js/issues/5917))
|
||||
- remove usage of $animate.flushNext in favour of queing
|
||||
([906fdad0](https://github.com/angular/angular.js/commit/906fdad0f95465842e336e057ea97d0633712189))
|
||||
- always call functions injected with `inject` with `this` set to the current spec
|
||||
([3bf43903](https://github.com/angular/angular.js/commit/3bf43903397c703aa2e9ba1e1a48dbc9e8286ee2),
|
||||
[#6102](https://github.com/angular/angular.js/issues/6102))
|
||||
- refactor currentSpec to work w/ Jasmine 2
|
||||
([95f0bf9b](https://github.com/angular/angular.js/commit/95f0bf9b526fda8964527c6d4aef1ad50a47f1f3),
|
||||
[#5662](https://github.com/angular/angular.js/issues/5662))
|
||||
- **ngMock:** return false from mock $interval.cancel() when no argument is supplied
|
||||
([dd24c783](https://github.com/angular/angular.js/commit/dd24c78373b5d24ecb3b9d19e61e1b3b6c74d155),
|
||||
[#6103](https://github.com/angular/angular.js/issues/6103))
|
||||
- **ngResource:**
|
||||
- don't filter "$"-prefixed properties from ngResource requests/responses
|
||||
([d2e4e499](https://github.com/angular/angular.js/commit/d2e4e499862aeca157dbe7a7422c465e7c79205e),
|
||||
[#5666](https://github.com/angular/angular.js/issues/5666), [#6080](https://github.com/angular/angular.js/issues/6080), [#6033](https://github.com/angular/angular.js/issues/6033))
|
||||
- don't append number to '$' in url param value when encoding URI
|
||||
([ce1f1f97](https://github.com/angular/angular.js/commit/ce1f1f97f0ebf77941b2bdaf5e8352d33786524d),
|
||||
[#6003](https://github.com/angular/angular.js/issues/6003), [#6004](https://github.com/angular/angular.js/issues/6004))
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
The animation mock module has been renamed from `mock.animate` to `ngAnimateMock`. In addition to the rename, animations will not block within test code even when ngAnimateMock is used. However, all function calls to $animate will be recorded into `$animate.queue` and are available within test code to assert animation calls. In addition, `$animate.triggerReflow()` is now only available when `ngAnimateMock` is used.
|
||||
|
||||
|
||||
<a name="1.2.11"></a>
|
||||
# 1.2.11 cryptocurrency-hyperdeflation (2014-02-03)
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$compile:** retain CSS classes added in cloneAttachFn on asynchronous directives
|
||||
([5ed721b9](https://github.com/angular/angular.js/commit/5ed721b9b5e95ae08450e1ae9d5202e7f3f79295),
|
||||
[#5439](https://github.com/angular/angular.js/issues/5439), [#5617](https://github.com/angular/angular.js/issues/5617))
|
||||
- **$http:** update httpBackend to use ActiveXObject on IE8 if necessary
|
||||
([ef210e5e](https://github.com/angular/angular.js/commit/ef210e5e119db4f5bfc9d2428b19f9b335c4f976),
|
||||
[#5677](https://github.com/angular/angular.js/issues/5677), [#5679](https://github.com/angular/angular.js/issues/5679))
|
||||
- **$q:** make $q.reject support `finally` and `catch`
|
||||
([074b0675](https://github.com/angular/angular.js/commit/074b0675a1f97dce07f520f1ae6198ed3c604000),
|
||||
[#6048](https://github.com/angular/angular.js/issues/6048), [#6076](https://github.com/angular/angular.js/issues/6076))
|
||||
- **filterFilter:** don't interpret dots in predicate object fields as paths
|
||||
([339a1658](https://github.com/angular/angular.js/commit/339a1658cd9bfa5e322a01c45aa0a1df67e3a842),
|
||||
[#6005](https://github.com/angular/angular.js/issues/6005), [#6009](https://github.com/angular/angular.js/issues/6009))
|
||||
- **mocks:** refactor currentSpec to work w/ Jasmine 2
|
||||
([95f0bf9b](https://github.com/angular/angular.js/commit/95f0bf9b526fda8964527c6d4aef1ad50a47f1f3),
|
||||
[#5662](https://github.com/angular/angular.js/issues/5662))
|
||||
- **ngResource:** don't append number to '$' in url param value when encoding URI
|
||||
([ce1f1f97](https://github.com/angular/angular.js/commit/ce1f1f97f0ebf77941b2bdaf5e8352d33786524d),
|
||||
[#6003](https://github.com/angular/angular.js/issues/6003), [#6004](https://github.com/angular/angular.js/issues/6004))
|
||||
|
||||
<a name="1.2.10"></a>
|
||||
# 1.2.10 augmented-serendipity (2014-01-24)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$parse:** do not use locals to resolve object properties
|
||||
([f09b6aa5](https://github.com/angular/angular.js/commit/f09b6aa5b58c090e3b8f8811fb7735e38d4b7623),
|
||||
[#5838](https://github.com/angular/angular.js/issues/5838), [#5862](https://github.com/angular/angular.js/issues/5862))
|
||||
- **a:** don't call preventDefault on click when a SVGAElement has an xlink:href attribute
|
||||
([e0209169](https://github.com/angular/angular.js/commit/e0209169bf1463465ad07484421620748a4d3908),
|
||||
[#5896](https://github.com/angular/angular.js/issues/5896), [#5897](https://github.com/angular/angular.js/issues/5897))
|
||||
- **input:** use Chromium's email validation regexp
|
||||
([79e519fe](https://github.com/angular/angular.js/commit/79e519fedaec54390a8bdacfb1926bfce57a1eb6),
|
||||
[#5899](https://github.com/angular/angular.js/issues/5899), [#5924](https://github.com/angular/angular.js/issues/5924))
|
||||
- **ngRoute:** pipe preceding route param no longer masks ? or * operator
|
||||
([fd6bac7d](https://github.com/angular/angular.js/commit/fd6bac7de56f728a89782dc80c78f7d5c21bbc65),
|
||||
[#5920](https://github.com/angular/angular.js/issues/5920))
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- **$animate:** provide support for a close callback
|
||||
([ca6b7d0f](https://github.com/angular/angular.js/commit/ca6b7d0fa2e355ebd764230260758cee9a4ebe1e),
|
||||
[#5685](https://github.com/angular/angular.js/issues/5685), [#5053](https://github.com/angular/angular.js/issues/5053), [#4993](https://github.com/angular/angular.js/issues/4993))
|
||||
|
||||
|
||||
<a name="1.2.9"></a>
|
||||
# 1.2.9 enchanted-articulacy (2014-01-15)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$animate:**
|
||||
- ensure the final closing timeout respects staggering animations
|
||||
([ed53100a](https://github.com/angular/angular.js/commit/ed53100a0dbc9119d5dfc8b7248845d4f6989df2))
|
||||
- prevent race conditions for class-based animations when animating on the same CSS class
|
||||
([4aa9df7a](https://github.com/angular/angular.js/commit/4aa9df7a7ae533531dfae1e3eb9646245d6b5ff4),
|
||||
[#5588](https://github.com/angular/angular.js/issues/5588))
|
||||
- correctly detect and handle CSS transition changes during class addition and removal
|
||||
([7d5d62da](https://github.com/angular/angular.js/commit/7d5d62dafe11620082c79da35958f8014eeb008c))
|
||||
- avoid accidentally matching substrings when resolving the presence of className tokens
|
||||
([524650a4](https://github.com/angular/angular.js/commit/524650a40ed20f01571e5466475749874ee67288))
|
||||
- **$http:** ensure default headers PUT and POST are different objects
|
||||
([e1cfb195](https://github.com/angular/angular.js/commit/e1cfb1957feaf89408bccf48fae6f529e57a82fe),
|
||||
[#5742](https://github.com/angular/angular.js/issues/5742), [#5747](https://github.com/angular/angular.js/issues/5747), [#5764](https://github.com/angular/angular.js/issues/5764))
|
||||
- **$rootScope:** prevent infinite $digest by checking if asyncQueue is empty when decrementing ttl
|
||||
([2cd09c9f](https://github.com/angular/angular.js/commit/2cd09c9f0e7766bcd191662841b7b1ffc3b6dc3f),
|
||||
[#2622](https://github.com/angular/angular.js/issues/2622))
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- **$animate:**
|
||||
- provide support for DOM callbacks
|
||||
([dde1b294](https://github.com/angular/angular.js/commit/dde1b2949727c297e214c99960141bfad438d7a4))
|
||||
- use requestAnimationFrame instead of a timeout to issue a reflow
|
||||
([4ae3184c](https://github.com/angular/angular.js/commit/4ae3184c5915aac9aa00889aa2153c8e84c14966),
|
||||
[#4278](https://github.com/angular/angular.js/issues/4278), [#4225](https://github.com/angular/angular.js/issues/4225))
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
- **$http:** due to [e1cfb195](https://github.com/angular/angular.js/commit/e1cfb1957feaf89408bccf48fae6f529e57a82fe),
|
||||
it is now necessary to separately specify default HTTP headers for PUT, POST and PATCH requests, as these no longer share a single object.
|
||||
|
||||
To migrate your code, follow the example below:
|
||||
|
||||
Before:
|
||||
|
||||
// Will apply to POST, PUT and PATCH methods
|
||||
$httpProvider.defaults.headers.post = {
|
||||
"X-MY-CSRF-HEADER": "..."
|
||||
};
|
||||
|
||||
After:
|
||||
|
||||
// POST, PUT and PATCH default headers must be specified separately,
|
||||
// as they do not share data.
|
||||
$httpProvider.defaults.headers.post =
|
||||
$httpProvider.defaults.headers.put =
|
||||
$httpProviders.defaults.headers.patch = {
|
||||
"X-MY-CSRF-HEADER": "..."
|
||||
};
|
||||
|
||||
<a name="1.2.8"></a>
|
||||
# 1.2.8 interdimensional-cartography (2014-01-10)
|
||||
|
||||
@@ -2140,7 +2537,7 @@ _Note: This release also contains all bug fixes available in [1.0.5](#1.0.5)._
|
||||
- **ngClass:** keep track of old ngClass value manually
|
||||
([5f5d4fea](https://github.com/angular/angular.js/commit/5f5d4feadbfa9d8ecc8150041dfd2bca2b2e9fea),
|
||||
[#1637](https://github.com/angular/angular.js/issues/1637))
|
||||
- **ngSwitch:** make ngSwitch compatible with controller backwards-compatiblity module
|
||||
- **ngSwitch:** make ngSwitch compatible with controller backwards-compatibility module
|
||||
([9b7c1d0f](https://github.com/angular/angular.js/commit/9b7c1d0f7ce442d4ad2ec587e66d2d335e64fa4e))
|
||||
- **Filters:**
|
||||
- **date:** invert timezone sign and always display sign
|
||||
@@ -3496,7 +3893,7 @@ behavior and migrate your controllers one at a time: <https://gist.github.com/16
|
||||
|
||||
|
||||
## Bug Fixes:
|
||||
- [ng:view]: ignore stale xhr callbacks - fixes issues caused by race-conditions which occured when
|
||||
- [ng:view]: ignore stale xhr callbacks - fixes issues caused by race-conditions which occurred when
|
||||
user navigated to a new route before the current route finished loading
|
||||
(issue [#619](https://github.com/angular/angular.js/issues/619))
|
||||
- [ng:form] should always be a block level (css) element
|
||||
@@ -3813,7 +4210,7 @@ behavior and migrate your controllers one at a time: <https://gist.github.com/16
|
||||
- [jqLite]
|
||||
- added `show()`, `hide()` and `eq()` methods to jqlite
|
||||
([commit](https://github.com/angular/angular.js/commit/7a3fdda9650a06792d9278a8cef06d544d49300f))
|
||||
- added $defer.cancel to support cancelation of tasks defered via the [$defer] service
|
||||
- added $defer.cancel to support cancellation of tasks defered via the [$defer] service
|
||||
- [date] filter
|
||||
- added support for `full`, `long`, `medium` and `short` date-time format flags
|
||||
([commit](https://github.com/angular/angular.js/commit/3af1e7ca2ee8c2acd69e5bcbb3ffc1bf51239285))
|
||||
|
||||
@@ -3,12 +3,25 @@
|
||||
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:
|
||||
|
||||
## Got a Question or Problem?
|
||||
- [Code of Conduct](#coc)
|
||||
- [Question or Problem?](#question)
|
||||
- [Issues and Bugs](#issue)
|
||||
- [Feature Requests](#feature)
|
||||
- [Submission Guidelines](#submit)
|
||||
- [Coding Rules](#rules)
|
||||
- [Commit Message Guidelines](#commit)
|
||||
- [Signing the CLA](#cla)
|
||||
- [Further Info](#info)
|
||||
|
||||
## <a name="coc"></a> Code of Conduct
|
||||
Help us keep Angular open and inclusive. Please read and follow our [Code of Conduct][coc].
|
||||
|
||||
## <a name="question"></a> 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?
|
||||
## <a name="issue"></a> 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.
|
||||
@@ -19,7 +32,7 @@ approach is to submit a patch to the I18N project directly, instead of submittin
|
||||
|
||||
**Please see the Submission Guidelines below**.
|
||||
|
||||
## Want a Feature?
|
||||
## <a name="feature"></a> 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:
|
||||
|
||||
@@ -30,19 +43,19 @@ project.
|
||||
* **Small Changes** can be crafted and submitted to [GitHub Repository][github] as a Pull Request.
|
||||
|
||||
|
||||
## Want a Doc Fix?
|
||||
## <a name="docs"></a> Want a Doc Fix?
|
||||
If you want to help improve the docs, it's a good idea to let others know what you're working on to
|
||||
minimize duplication of effort. Before starting, check out the issue queue for [Milestone:Docs Only](https://github.com/angular/angular.js/issues?milestone=24&state=open).
|
||||
Comment on an issue to let others know what you're working on, or create a new issue if your work
|
||||
doesn't fit within the scope of any of the existing doc fix projects.
|
||||
|
||||
For large fixes, please build and test the documentation before submitting the PR to be sure you haven't
|
||||
accidentally introduced any layout or formatting issues.You should also make sure that your commit message
|
||||
accidentally introduced any layout or formatting issues. You should also make sure that your commit message
|
||||
is labeled "docs:" and follows the **Git Commit Guidelines** outlined below.
|
||||
|
||||
If you're just making a small change, don't worry about filing an issue first. Use the friendly blue "Improve this doc" button at the top right of the doc page to fork the repository in-place and make a quick change on the fly.
|
||||
|
||||
## Submission Guidelines
|
||||
## <a name="submit"></a> Submission Guidelines
|
||||
|
||||
### Submitting an Issue
|
||||
Before you submit your issue search the archive, maybe your question was already answered.
|
||||
@@ -79,16 +92,19 @@ Before you submit your pull request consider the following guidelines:
|
||||
git checkout -b my-fix-branch master
|
||||
```
|
||||
|
||||
* Create your patch, including appropriate test cases.
|
||||
* Follow our Coding Rules
|
||||
* 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`):
|
||||
* Create your patch, **including appropriate test cases**.
|
||||
* Follow our [Coding Rules](#coding-rules).
|
||||
* Run the full Angular test suite, as described in the [developer documentation][dev-doc],
|
||||
and ensure that all tests pass.
|
||||
* Commit your changes using a descriptive commit message that follows our
|
||||
[commit message conventions](#commit-message-format) and passes our commit message presubmit hook
|
||||
`validate-commit-msg.js`. Adherence to the [commit message conventions](#commit-message-format)
|
||||
is required because release notes are automatically generated from these messages.
|
||||
|
||||
```shell
|
||||
git commit -a
|
||||
```
|
||||
Note: the optional commit `-a` command line option will automatically "add" and "rm" edited files.
|
||||
|
||||
* Build your changes locally to ensure all the tests pass
|
||||
|
||||
@@ -96,15 +112,17 @@ Before you submit your pull request consider the following guidelines:
|
||||
grunt test
|
||||
```
|
||||
|
||||
* Push your branch to Github:
|
||||
* Push your branch to GitHub:
|
||||
|
||||
```shell
|
||||
git push origin my-fix-branch
|
||||
```
|
||||
|
||||
* In Github, send a pull request to `angular:master`.
|
||||
* 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:
|
||||
* In GitHub, send a pull request to `angular:master`.
|
||||
* If we suggest changes then
|
||||
* Make the required updates.
|
||||
* Re-run the Angular test suite to ensure tests are still passing.
|
||||
* Rebase your branch and force push to your GitHub repository (this will update your Pull Request):
|
||||
|
||||
```shell
|
||||
git rebase master -i
|
||||
@@ -113,10 +131,12 @@ Before you submit your pull request consider the following guidelines:
|
||||
|
||||
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
|
||||
#### After your pull request is merged
|
||||
|
||||
After your pull request is merged, you can safely delete your branch and pull the changes
|
||||
from the main (upstream) repository:
|
||||
|
||||
* Delete the remote branch on Github:
|
||||
* Delete the remote branch on GitHub either through the GitHub web UI or your local shell as follows:
|
||||
|
||||
```shell
|
||||
git push origin --delete my-fix-branch
|
||||
@@ -140,15 +160,7 @@ from the main (upstream) repository:
|
||||
git pull --ff upstream master
|
||||
```
|
||||
|
||||
### GitHub Pull Request Helper
|
||||
|
||||
We track Pull Requests by attaching labels and assigning to milestones. For some reason GitHub
|
||||
does not provide a good UI for managing labels on Pull Requests (unlike Issues). We have developed
|
||||
a simple Chrome Extension that enables you to view (and manage if you have permission) the labels
|
||||
on Pull Requests. You can get the extension from the Chrome WebStore -
|
||||
[GitHub PR Helper][github-pr-helper]
|
||||
|
||||
## Coding Rules
|
||||
## <a name="rules"></a> 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].
|
||||
@@ -168,7 +180,7 @@ To ensure consistency throughout the source code, keep these rules in mind as yo
|
||||
* 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
|
||||
## <a name="commit"></a> 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,
|
||||
@@ -225,7 +237,7 @@ reference GitHub issues that this commit **Closes**.
|
||||
|
||||
A detailed explanation can be found in this [document][commit-message-format].
|
||||
|
||||
## Signing the CLA
|
||||
## <a name="cla"></a> 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!
|
||||
@@ -234,30 +246,29 @@ changes to be accepted, the CLA must be signed. It's a quick process, we promise
|
||||
* For corporations we'll need you to
|
||||
[print, sign and one of scan+email, fax or mail the form][corporate-cla].
|
||||
|
||||
## Further Information
|
||||
## <a name="info"></a> Further Information
|
||||
You can find out more detailed information about contributing in the
|
||||
[AngularJS documentation][contributing].
|
||||
|
||||
|
||||
|
||||
[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
|
||||
[coc]: https://github.com/angular/code-of-conduct/blob/master/CODE_OF_CONDUCT.md
|
||||
[commit-message-format]: https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#
|
||||
[github-pr-helper]: https://chrome.google.com/webstore/detail/github-pr-helper/mokbklfnaddkkbolfldepnkfmanfhpen
|
||||
|
||||
[contribute]: http://docs.angularjs.org/misc/contribute
|
||||
[contributing]: http://docs.angularjs.org/misc/contribute
|
||||
[corporate-cla]: http://code.google.com/legal/corporate-cla-v1.0.html
|
||||
[github]: https://github.com/angular/angular.js
|
||||
[groups]: https://groups.google.com/forum/?fromgroups#!forum/angular
|
||||
[individual-cla]: http://code.google.com/legal/individual-cla-v1.0.html
|
||||
[irc]: http://webchat.freenode.net/?channels=angularjs&uio=d4
|
||||
[js-style-guide]: http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml
|
||||
[jsfiddle]: http://jsfiddle.net/
|
||||
[list]: https://groups.google.com/forum/?fromgroups#!forum/angular
|
||||
[ngDocs]: https://github.com/angular/angular.js/wiki/Writing-AngularJS-Documentation
|
||||
[plunker]: http://plnkr.co/edit
|
||||
[stackoverflow]: http://stackoverflow.com/questions/tagged/angularjs
|
||||
[unit-testing]: http://docs.angularjs.org/guide/dev_guide.unit-testing
|
||||
|
||||
[](https://github.com/igrigorik/ga-beacon)
|
||||
|
||||
@@ -1,26 +1,18 @@
|
||||
var files = require('./angularFiles').files;
|
||||
var util = require('./lib/grunt/utils.js');
|
||||
var versionInfo = require('./lib/versions/version-info');
|
||||
var path = require('path');
|
||||
|
||||
module.exports = function(grunt) {
|
||||
//grunt plugins
|
||||
grunt.loadNpmTasks('grunt-bump');
|
||||
grunt.loadNpmTasks('grunt-contrib-clean');
|
||||
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');
|
||||
require('load-grunt-tasks')(grunt);
|
||||
|
||||
grunt.loadTasks('lib/grunt');
|
||||
|
||||
var NG_VERSION = util.getVersion();
|
||||
var NG_VERSION = versionInfo.currentVersion;
|
||||
NG_VERSION.cdn = versionInfo.cdnVersion;
|
||||
var dist = 'angular-'+ NG_VERSION.full;
|
||||
|
||||
|
||||
//global beforeEach
|
||||
util.init();
|
||||
|
||||
@@ -32,7 +24,7 @@ module.exports = function(grunt) {
|
||||
parallel: {
|
||||
travis: {
|
||||
tasks: [
|
||||
util.parallelTask(['test:unit', 'test:docgen', 'test:promises-aplus', 'tests:docs'], {stream: true}),
|
||||
util.parallelTask(['test:unit', 'test:promises-aplus', 'tests:docs'], {stream: true}),
|
||||
util.parallelTask(['test:e2e'])
|
||||
]
|
||||
}
|
||||
@@ -87,9 +79,7 @@ module.exports = function(grunt) {
|
||||
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'
|
||||
modules: 'karma-modules.conf.js'
|
||||
},
|
||||
|
||||
|
||||
@@ -101,8 +91,10 @@ module.exports = function(grunt) {
|
||||
},
|
||||
|
||||
|
||||
runprotractor: {
|
||||
normal: 'protractor-conf.js'
|
||||
protractor: {
|
||||
normal: 'protractor-conf.js',
|
||||
travis: 'protractor-travis-conf.js',
|
||||
jenkins: 'protractor-jenkins-conf.js'
|
||||
},
|
||||
|
||||
|
||||
@@ -147,6 +139,13 @@ module.exports = function(grunt) {
|
||||
}
|
||||
},
|
||||
|
||||
jscs: {
|
||||
src: ['src/**/*.js', 'test/**/*.js'],
|
||||
options: {
|
||||
config: ".jscs.json"
|
||||
}
|
||||
},
|
||||
|
||||
build: {
|
||||
scenario: {
|
||||
dest: 'build/angular-scenario.js',
|
||||
@@ -219,14 +218,6 @@ module.exports = function(grunt) {
|
||||
},
|
||||
|
||||
|
||||
docs: {
|
||||
process: ['build/docs/*.html', 'build/docs/.htaccess']
|
||||
},
|
||||
|
||||
"jasmine_node": {
|
||||
projectRoot: 'docs/spec'
|
||||
},
|
||||
|
||||
"ddescribe-iit": {
|
||||
files: [
|
||||
'test/**/*.js',
|
||||
@@ -288,22 +279,21 @@ 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', 'webdriver', 'runprotractor:normal']);
|
||||
grunt.registerTask('test', 'Run unit, docs and e2e tests with Karma', ['jshint', 'jscs', 'package','test:unit','test:promises-aplus', 'tests:docs', 'test:protractor']);
|
||||
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']);
|
||||
// This should eventually replace test:e2e
|
||||
grunt.registerTask('test:protractor', 'Run the end to end tests with Protractor and keep a test server running in the background', ['webdriver', 'connect:testserver', 'runprotractor:normal']);
|
||||
grunt.registerTask('test:docgen', ['jasmine_node']);
|
||||
grunt.registerTask('test:protractor', 'Run the end to end tests with Protractor and keep a test server running in the background', ['webdriver', 'connect:testserver', 'protractor:normal']);
|
||||
grunt.registerTask('test:travis-protractor', 'Run the end to end tests with Protractor for Travis CI builds', ['connect:testserver', 'protractor:travis']);
|
||||
grunt.registerTask('test:ci-protractor', 'Run the end to end tests with Protractor for Jenkins CI builds', ['webdriver', 'connect:testserver', 'protractor:jenkins']);
|
||||
grunt.registerTask('test:e2e', 'Alias for test:protractor', ['test:protractor']);
|
||||
grunt.registerTask('test:promises-aplus',['build:promises-aplus-adapter','shell:promises-aplus-tests']);
|
||||
|
||||
grunt.registerTask('minify', ['bower','clean', 'build', 'minall']);
|
||||
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']);
|
||||
grunt.registerTask('ci-checks', ['ddescribe-iit', 'merge-conflict', 'jshint', 'jscs']);
|
||||
grunt.registerTask('default', ['package']);
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2010-2012 Google, Inc. http://angularjs.org
|
||||
Copyright (c) 2010-2014 Google, Inc. http://angularjs.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -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 [](https://travis-ci.org/angular/angular.js)
|
||||
=========
|
||||
|
||||
AngularJS lets you write client-side web applications as if you had a smarter browser. It lets you
|
||||
@@ -7,7 +7,7 @@ syntax to express your application’s components clearly and succinctly. It au
|
||||
synchronizes data from your UI (view) with your JavaScript objects (model) through 2-way data
|
||||
binding. To help you structure your application better and make it easy to test, AngularJS teaches
|
||||
the browser how to do dependency injection and inversion of control. Oh yeah and it also helps with
|
||||
server-side communication, taming async callbacks with promises and deferreds; and make client-side
|
||||
server-side communication, taming async callbacks with promises and deferreds; and makes client-side
|
||||
navigation and deeplinking with hashbang urls or HTML5 pushState a piece of cake. The best of all:
|
||||
it makes development fun!
|
||||
|
||||
|
||||
@@ -1,63 +1,134 @@
|
||||
# Triage new issues/PRs on github
|
||||
|
||||
This document shows the steps the Angular team is using to triage issues.
|
||||
The labels are used later on for planning releases.
|
||||
|
||||
## Tips ##
|
||||
|
||||
* install [github pr helper extension](https://github.com/petebacondarwin/github-pr-helper) and become 356% more productive
|
||||
* Label "resolution:*"
|
||||
* these tags can be used for labeling a closed issue/PR with a reason why it was closed. (we can add reasons as we need them, right there are only a few rejection reasons. it doesn't make sense to label issues that were fixed or prs that were merged)
|
||||
The labels are used later on for [planning releases](#assigning-work).
|
||||
|
||||
|
||||
## Automatic processing ##
|
||||
## Automatic processing
|
||||
|
||||
We have automatic tools (e.g. Mary Poppins) that automatically add comments / labels to issues and PRs.
|
||||
The following is done automatically and should not be done manually:
|
||||
We have tools (e.g. [Mary Poppins]) that automatically add comments and labels to issues and PRs.
|
||||
The following is done automatically so you don't have to worry about it:
|
||||
|
||||
* Label "cla: yes" or "cla: no" for pull requests
|
||||
* Label `cla: yes` or `cla: no` for pull requests
|
||||
* Label `GH: *`
|
||||
* `PR` - issue is a PR
|
||||
* `issue` - otherwise
|
||||
|
||||
## Process ##
|
||||
|
||||
1. Open list of [non triaged issues](https://github.com/angular/angular.js/issues?direction=desc&milestone=none&page=1&sort=created&state=open)
|
||||
## Triaging Process
|
||||
|
||||
This process based on the idea of minimizing user pain
|
||||
[from this blog post](http://www.lostgarden.com/2008/05/improving-bug-triage-with-user-pain.html).
|
||||
|
||||
1. Open the list of [non triaged issues](https://github.com/angular/angular.js/issues?direction=desc&milestone=none&page=1&sort=created&state=open)
|
||||
* Sort by submit date, with the newest issues first
|
||||
* You don't have to do issues in order; feel free to pick and choose issues as you please.
|
||||
* You can triage older issues as well
|
||||
* Triage to your heart's content
|
||||
1. Assign yourself: Pick an issue that is not assigned to anyone and assign it to you
|
||||
1. Assign milestone:
|
||||
* "Docs only" milestone - for documentation PR -> **Done**.
|
||||
* Current/next milestone - regressions
|
||||
* 1.2.x - everything else
|
||||
1. Label "GH: *" (to be automated via Mary Poppins)
|
||||
* PR - issue is a PR
|
||||
* issue - otherwise
|
||||
|
||||
1. Understandable? - verify if the description of the request is clear.
|
||||
* If not, [close it][] according to the instructions below and go to the last step.
|
||||
1. Duplicate?
|
||||
* If you've seen this issue before [close it][], and go to the last step.
|
||||
* Check if there are comments that link to a dupe. If so verify that this is indeed a dupe, [close it][], and go to the last step.
|
||||
1. Bugs:
|
||||
* Label "Type: Bug"
|
||||
* Label "Type: Regression" - if the bug is a regression
|
||||
* Duplicate? - Check if there are comments pointing out that this is a dupe, if they do exist verify that this is indeed a dupe and close it and go to the last step
|
||||
* Reproducible? - Steps to reproduce the bug are clear, if not ask for clarification (ideally plunker or fiddle)
|
||||
* Reproducible on master? - http://code.angularjs.org/snapshot/
|
||||
* Label `Type: Bug`
|
||||
* Reproducible? - Steps to reproduce the bug are clear. If they are not,
|
||||
* Reproducible on master? - <http://code.angularjs.org/snapshot/>
|
||||
|
||||
1. Non bugs:
|
||||
* Label "Type: Feature" or "Type: Chore" or "Type: Perf"
|
||||
* Label "needs: breaking change" - if needed
|
||||
* Label "needs: public api" - if a new public api is needed
|
||||
* Understandable? - verify if the description of the request is clear. if not ask for clarification
|
||||
* Goals of angular core? - Often new features should be implemented as a third-party module rather than an addition to the core.
|
||||
* Label `Type: Feature`, `Type: Chore`, or `Type: Perf`
|
||||
* Belongs in core? – Often new features should be implemented as a third-party module rather than an addition to the core.
|
||||
If this doesn't belong, [close it][], and go to the last step.
|
||||
* Label `needs: breaking change` - if needed
|
||||
* Label `needs: public api` - if the issue requires introduction of a new public API
|
||||
1. Label `browser: *` - if the issue **only** affects a certain browser
|
||||
1. Label `frequency: *` – How often does this issue come up? How many developers does this affect?
|
||||
* low - obscure issue affecting a handful of developers
|
||||
* moderate - impacts a common usage pattern
|
||||
* high - impacts most or all Angular apps
|
||||
1. Label `severity: *` - How bad is the issue?
|
||||
* security issue
|
||||
* regression
|
||||
* memory leak
|
||||
* broken expected use - it's hard or impossible for a developer using Angular to accomplish something that Angular should be able to do
|
||||
* confusing - unexpected or inconsistent behavior; hard-to-debug
|
||||
* inconvenience - causes ugly/boilerplate code in apps
|
||||
1. Label `component: *`
|
||||
* In rare cases, it's ok to have multiple components.
|
||||
1. Label `PRs plz!` - These issues are good targets for PRs from the open source community. Apply to issues where the problem and solution are well defined in the comments, and it's not too complex.
|
||||
1. Label `origin: google` for issues from Google
|
||||
|
||||
1. Label "component: *"
|
||||
* In rare cases, it's ok to have multiple components.
|
||||
1. Label "impact: *"
|
||||
* small - obscure issue affecting one or handful of developers
|
||||
* medium - impacts some usage patterns
|
||||
* large - impacts most or all of angular apps
|
||||
1. Label "complexity: *"
|
||||
* small - trivial change
|
||||
* medium - non-trivial but straightforward change
|
||||
* large - changes to many components in angular or any changes to $compile, ngRepeat or other "fun" components
|
||||
1. Label "PRs welcome" for "GH: issue"
|
||||
* if complexity is small or medium and the problem as well as solution are well captured in the issue
|
||||
1. Label "origin: google" for issues from Google
|
||||
1. Label "high priority" for security issues, major performance regressions or memory leaks
|
||||
1. Assign a milestone:
|
||||
* Backlog - triaged fixes and features, should be the default choice
|
||||
* Current 1.x.y milestone (e.g. 1.3.0-beta-2) - regressions and urgent bugs only
|
||||
|
||||
|
||||
1. Unassign yourself from the issue
|
||||
|
||||
|
||||
## Tips
|
||||
|
||||
* Label `resolution: *`
|
||||
* these tags can be used for labeling a closed issue/PR with a reason why it was closed.
|
||||
* Right now there are only a few rejection reasons, but we can add more as needed. Feel free to suggest one to a core team member. We don't use this label for issues that were fixed or PRs that were merged.
|
||||
|
||||
|
||||
## Closing an Issue or PR
|
||||
|
||||
We're grateful to anyone who takes the time to submit an issue, even if we ultimately decide not to act on it.
|
||||
Be kind and respectful as you close issues. Be sure to follow the [code of conduct][].
|
||||
|
||||
1. Always thank the person who submitted it.
|
||||
1. If it's a duplicate, link to the older or more descriptive issue that supersedes the one you are closing.
|
||||
1. Let them know if there's some way for them to follow-up.
|
||||
* When the issue is unclear or reproducible, note that you'll reopen it if they can clarify or provide a better example. Mention [plunker] or [fiddle] for examples. Watch your notifications and follow-up if they do provide clarification. :)
|
||||
* If appropriate, suggest implementing a feature as a third-party module.
|
||||
|
||||
If in doubt, ask a core team member what to do.
|
||||
[Brian](https://github.com/btford) is probably the person to ask.
|
||||
You can mention him in the relevant thread like this: `@btford`.
|
||||
|
||||
**Example:**
|
||||
|
||||
> Thanks for submitting this issue!
|
||||
> Unfortunately, we don't think this functionality belongs in core.
|
||||
> The good news is that you could easily implement this as a third-party module and publish it on Bower and/or npm.
|
||||
|
||||
|
||||
## Assigning Work
|
||||
|
||||
These criteria are then used to calculate a "user pain" score.
|
||||
Work is assigned weekly to core team members starting with the highest pain, descending down to the lowest.
|
||||
|
||||
```
|
||||
pain = severity × frequency
|
||||
```
|
||||
|
||||
**severity:**
|
||||
|
||||
- security issue (6)
|
||||
- regression (5)
|
||||
- memory leak (4)
|
||||
- broken expected use (3)
|
||||
- confusing (2)
|
||||
- inconvenience (1)
|
||||
|
||||
**frequency:**
|
||||
|
||||
- low (1)
|
||||
- moderate (2)
|
||||
- high (3)
|
||||
|
||||
**Note:** Security issues, regressions, and memory leaks should almost always be set to `frequency: high`.
|
||||
|
||||
|
||||
[](https://github.com/igrigorik/ga-beacon)
|
||||
|
||||
|
||||
[close it]: #closing-an-issue-or-pr
|
||||
[code of conduct]: https://github.com/angular/code-of-conduct/blob/master/CODE_OF_CONDUCT.md
|
||||
[Mary Poppins]: https://github.com/btford/mary-poppins
|
||||
[plunker]: http://plnkr.co/
|
||||
[fiddle]: http://jsfiddle.net/
|
||||
|
||||
@@ -11,6 +11,7 @@ angularFiles = {
|
||||
|
||||
'src/ng/anchorScroll.js',
|
||||
'src/ng/animate.js',
|
||||
'src/ng/asyncCallback.js',
|
||||
'src/ng/browser.js',
|
||||
'src/ng/cacheFactory.js',
|
||||
'src/ng/compile.js',
|
||||
@@ -26,6 +27,7 @@ angularFiles = {
|
||||
'src/ng/log.js',
|
||||
'src/ng/parse.js',
|
||||
'src/ng/q.js',
|
||||
'src/ng/raf.js',
|
||||
'src/ng/rootScope.js',
|
||||
'src/ng/sanitizeUri.js',
|
||||
'src/ng/sce.js',
|
||||
@@ -142,8 +144,6 @@ angularFiles = {
|
||||
'@angularSrcModules',
|
||||
'@angularScenario',
|
||||
'@angularTest',
|
||||
'example/personalLog/*.js',
|
||||
'example/personalLog/test/*.js'
|
||||
],
|
||||
|
||||
'karmaExclude': [
|
||||
@@ -178,9 +178,6 @@ angularFiles = {
|
||||
'@angularSrcModules',
|
||||
'@angularScenario',
|
||||
'@angularTest',
|
||||
'example/personalLog/*.js',
|
||||
|
||||
'example/personalLog/test/*.js'
|
||||
],
|
||||
|
||||
'karmaJqueryExclude': [
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
"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",
|
||||
"lunr.js": "0.4.3",
|
||||
"open-sans-fontface": "1.0.4",
|
||||
"google-code-prettify": "1.0.1",
|
||||
"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"
|
||||
"ng-closure-runner": "https://raw.github.com/angular/ng-closure-runner/v0.2.3/assets/ng-closure-runner.zip",
|
||||
"bootstrap": "3.1.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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/
|
||||
@@ -9,3 +9,8 @@
|
||||
ng\:form {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.ng-animate-block-transitions {
|
||||
transition:0s all!important;
|
||||
-webkit-transition:0s all!important;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<h1>Oops!</h1>
|
||||
|
||||
<p>The page you requested does not exist. Perhaps you were looking for something else...</p>
|
||||
|
||||
<div ng-controller="Error404SearchCtrl">
|
||||
|
||||
<dl ng-repeat="(key, value) in results" ng-show="value.length" style="float: left; margin-right:20px">
|
||||
<dt>{{ key }}</dt>
|
||||
<dd ng-repeat="item in value"><a ng-href="{{ item.path }}">{{ item.name }}</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
@@ -0,0 +1,678 @@
|
||||
html, body {
|
||||
position:relative;
|
||||
height:100%;
|
||||
}
|
||||
|
||||
#wrapper {
|
||||
min-height:100%;
|
||||
position:relative;
|
||||
padding-bottom:120px;
|
||||
}
|
||||
|
||||
.footer {
|
||||
border-top:20px solid white;
|
||||
position:absolute;
|
||||
bottom:0;
|
||||
left:0;
|
||||
right:0;
|
||||
z-index:100;
|
||||
padding-top: 2em;
|
||||
background-color: #333;
|
||||
color: white;
|
||||
padding-bottom: 2em;
|
||||
}
|
||||
|
||||
.header-fixed {
|
||||
position:fixed;
|
||||
z-index:1000;
|
||||
top:0;
|
||||
left:0;
|
||||
right:0;
|
||||
}
|
||||
|
||||
.header-branding {
|
||||
min-height:41px!important;
|
||||
}
|
||||
|
||||
.docs-navbar-primary {
|
||||
border-radius:0!important;
|
||||
margin-bottom:0!important;
|
||||
}
|
||||
|
||||
/* Logo */
|
||||
/*.dropdown-menu {
|
||||
display:none;
|
||||
}
|
||||
*/
|
||||
h1,h2,h3,h4,h5,h6 {
|
||||
font-family: "Open Sans";
|
||||
}
|
||||
|
||||
.subnav-body {
|
||||
margin:70px 0 20px;
|
||||
}
|
||||
|
||||
.header .brand {
|
||||
padding-top: 6px;
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
.header .brand img {
|
||||
margin-top:5px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.docs-search {
|
||||
margin:10px 0;
|
||||
padding:4px 0 4px 20px;
|
||||
background:white;
|
||||
border-radius:20px;
|
||||
vertical-align:middle;
|
||||
}
|
||||
|
||||
.docs-search > .search-query {
|
||||
font-size:14px;
|
||||
border:0;
|
||||
width:80%;
|
||||
color:#555;
|
||||
}
|
||||
|
||||
.docs-search > .search-icon {
|
||||
font-size:15px;
|
||||
margin-right:10px;
|
||||
}
|
||||
|
||||
.docs-search > .search-query:focus {
|
||||
outline:0;
|
||||
}
|
||||
|
||||
/* end: Logo */
|
||||
|
||||
|
||||
.spacer {
|
||||
height: 1em;
|
||||
}
|
||||
|
||||
|
||||
.icon-cog {
|
||||
line-height: 13px;
|
||||
}
|
||||
|
||||
.naked-list,
|
||||
.naked-list ul,
|
||||
.naked-list li {
|
||||
list-style:none;
|
||||
margin:0;
|
||||
padding:0;
|
||||
}
|
||||
|
||||
.nav-index-section a {
|
||||
font-weight:bold;
|
||||
font-family: "Open Sans";
|
||||
color:black!important;
|
||||
margin-top:10px;
|
||||
display:block;
|
||||
}
|
||||
|
||||
.nav-index-group {
|
||||
margin-bottom:20px!important;
|
||||
}
|
||||
|
||||
.nav-index-group-heading {
|
||||
color:#6F0101;
|
||||
font-weight:bold;
|
||||
font-size:1.2em;
|
||||
padding:0;
|
||||
margin:0;
|
||||
border-bottom:1px soild #aaa;
|
||||
margin-bottom:5px;
|
||||
}
|
||||
|
||||
.nav-breadcrumb {
|
||||
margin:4px 0;
|
||||
padding:0;
|
||||
}
|
||||
|
||||
.nav-breadcrumb-entry {
|
||||
font-family: "Open Sans";
|
||||
padding:0;
|
||||
margin:0;
|
||||
font-size:18px;
|
||||
display:inline-block;
|
||||
vertical-align:middle;
|
||||
}
|
||||
|
||||
.nav-breadcrumb-entry > .divider {
|
||||
color:#555;
|
||||
display:inline-block;
|
||||
padding-left:8px;
|
||||
}
|
||||
|
||||
.nav-breadcrumb-entry > span,
|
||||
.nav-breadcrumb-entry > a {
|
||||
color:#6F0101;
|
||||
}
|
||||
|
||||
.step-list > li:nth-child(1) {
|
||||
padding-left:20px;
|
||||
}
|
||||
|
||||
.step-list > li:nth-child(2) {
|
||||
padding-left:40px;
|
||||
}
|
||||
|
||||
.step-list > li:nth-child(3) {
|
||||
padding-left:60px;
|
||||
}
|
||||
|
||||
.api-profile-header-heading {
|
||||
margin:0;
|
||||
padding:0;
|
||||
}
|
||||
|
||||
.api-profile-header-structure,
|
||||
.api-profile-header-structure a {
|
||||
font-family: "Open Sans";
|
||||
font-weight:bold;
|
||||
color:#999;
|
||||
}
|
||||
|
||||
.api-profile-section {
|
||||
margin-top:30px;
|
||||
padding-top:30px;
|
||||
border-top:1px solid #aaa;
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 15px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 5px;
|
||||
display: block;
|
||||
white-space: pre-wrap;
|
||||
word-break: normal;
|
||||
}
|
||||
|
||||
.aside-nav a,
|
||||
.aside-nav a:link,
|
||||
.aside-nav a:visited,
|
||||
.aside-nav a:active {
|
||||
color:#999;
|
||||
}
|
||||
.aside-nav a:hover {
|
||||
color:black;
|
||||
}
|
||||
|
||||
.api-profile-description > p:first-child {
|
||||
margin:15px 0;
|
||||
font-size:18px;
|
||||
}
|
||||
|
||||
p > code,
|
||||
code.highlighted {
|
||||
background:#f4f4f4;
|
||||
border-radius:5px;
|
||||
padding:2px 5px;
|
||||
color:maroon;
|
||||
}
|
||||
|
||||
.docs-version-jump {
|
||||
min-width:100%;
|
||||
max-width:100%;
|
||||
}
|
||||
|
||||
.picker {
|
||||
position: relative;
|
||||
width: auto;
|
||||
display: inline-block;
|
||||
margin: 0 0 2px 1.2%;
|
||||
overflow: hidden;
|
||||
border: 1px solid #e5e5e5;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
-ms-border-radius: 4px;
|
||||
-o-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
font-family: "Open Sans";
|
||||
font-weight: 600;
|
||||
height: auto;
|
||||
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ffffff), color-stop(100%, #f2f2f2));
|
||||
background-image: -webkit-linear-gradient(#ffffff, #f2f2f2);
|
||||
background-image: -moz-linear-gradient(#ffffff, #f2f2f2);
|
||||
background-image: -o-linear-gradient(#ffffff, #f2f2f2);
|
||||
background-image: linear-gradient(#ffffff, #f2f2f2);
|
||||
}
|
||||
|
||||
.picker select {
|
||||
position: relative;
|
||||
display: block;
|
||||
min-width: 100%;
|
||||
width: 120%;
|
||||
height: 34px;
|
||||
padding: 6px 30px 6px 15px;
|
||||
color: #555555;
|
||||
border: none;
|
||||
background: transparent;
|
||||
outline: none;
|
||||
-webkit-appearance: none;
|
||||
z-index: 99;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.picker:after {
|
||||
content:"";
|
||||
position: absolute;
|
||||
right: 8%;
|
||||
top: 50%;
|
||||
z-index: 0;
|
||||
color: #999;
|
||||
width: 0;
|
||||
margin-top:-2px;
|
||||
height: 0;
|
||||
border-top: 6px solid;
|
||||
border-right: 6px solid transparent;
|
||||
border-left: 6px solid transparent;
|
||||
}
|
||||
|
||||
iframe.example {
|
||||
width: 100%;
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
.search-results-frame {
|
||||
clear:both;
|
||||
display:table;
|
||||
width:100%;
|
||||
}
|
||||
|
||||
.search-results.ng-hide {
|
||||
display:none;
|
||||
}
|
||||
|
||||
.search-results-container {
|
||||
padding-bottom:1em;
|
||||
border-top:1px solid #111;
|
||||
background:#181818;
|
||||
box-shadow:inset 0 0 10px #111;
|
||||
}
|
||||
|
||||
.search-results-container .search-results-group {
|
||||
vertical-align:top;
|
||||
padding:10px 10px;
|
||||
display:inline-block;
|
||||
}
|
||||
|
||||
.search-results-group-heading {
|
||||
font-family: "Open Sans";
|
||||
padding-left:10px;
|
||||
color:white;
|
||||
}
|
||||
|
||||
.search-results-frame > .search-results-group:first-child > .search-results {
|
||||
border-right:1px solid #050505;
|
||||
}
|
||||
|
||||
.search-results-group.col-group-api { width:30%; }
|
||||
.search-results-group.col-group-guide { width:30%; }
|
||||
.search-results-group.col-group-tutorial { width:25%; }
|
||||
.search-results-group.col-group-misc,
|
||||
.search-results-group.col-group-error { float:right; clear:both; width:15% }
|
||||
|
||||
|
||||
.search-results-group.col-group-api .search-result {
|
||||
width:48%;
|
||||
display:inline-block;
|
||||
}
|
||||
|
||||
.search-close {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
margin-left: -100px;
|
||||
color: white;
|
||||
text-align: center;
|
||||
padding: 5px;
|
||||
background: #333;
|
||||
border-top-right-radius: 5px;
|
||||
border-top-left-radius: 5px;
|
||||
width: 200px;
|
||||
box-shadow:0 0 10px #111;
|
||||
}
|
||||
|
||||
.variables-matrix {
|
||||
border:1px solid #ddd;
|
||||
width:100%;
|
||||
margin:10px 0;
|
||||
}
|
||||
|
||||
.variables-matrix td,
|
||||
.variables-matrix th {
|
||||
padding:10px;
|
||||
}
|
||||
|
||||
.variables-matrix td {
|
||||
border-top:1px solid #eee;
|
||||
}
|
||||
|
||||
.variables-matrix td + td,
|
||||
.variables-matrix th + th {
|
||||
border-left:1px solid #eee;
|
||||
}
|
||||
|
||||
.variables-matrix tr:nth-child(even) td {
|
||||
background:#f5f5f5;
|
||||
}
|
||||
|
||||
.variables-matrix th {
|
||||
background:#f1f1f1;
|
||||
}
|
||||
|
||||
.sup-header {
|
||||
padding-top:10px;
|
||||
padding-bottom:5px;
|
||||
background:rgba(245,245,245,0.88);
|
||||
box-shadow:0 0 2px #999;
|
||||
}
|
||||
|
||||
.main-body-grid {
|
||||
margin-top:120px;
|
||||
position:relative;
|
||||
}
|
||||
|
||||
.main-body-grid > .grid-left,
|
||||
.main-body-grid > .grid-right {
|
||||
padding:20px 0;
|
||||
}
|
||||
|
||||
.main-body-grid > .grid-left {
|
||||
position:fixed;
|
||||
top:120px;
|
||||
bottom:0;
|
||||
padding-bottom:120px;
|
||||
overflow:auto;
|
||||
}
|
||||
|
||||
.main-header-grid > .grid-left,
|
||||
.main-body-grid > .grid-left {
|
||||
width:260px;
|
||||
}
|
||||
|
||||
.main-header-grid > .grid-right,
|
||||
.main-body-grid > .grid-right {
|
||||
margin-left:270px;
|
||||
position:relative;
|
||||
}
|
||||
|
||||
.main-header-grid > .grid-left {
|
||||
float:left;
|
||||
}
|
||||
|
||||
.main-body-grid .side-navigation {
|
||||
position:relative;
|
||||
}
|
||||
|
||||
.main-body-grid .side-navigation.ng-hide {
|
||||
display:block!important;
|
||||
}
|
||||
|
||||
.variables-matrix td {
|
||||
vertical-align:top;
|
||||
padding:5px;
|
||||
}
|
||||
|
||||
.type-hint {
|
||||
display:inline-block;
|
||||
background: gray;
|
||||
}
|
||||
|
||||
.variables-matrix .type-hint {
|
||||
text-align:center;
|
||||
min-width:60px;
|
||||
margin:1px 5px;
|
||||
}
|
||||
|
||||
.type-hint + .type-hint {
|
||||
margin-top:5px;
|
||||
}
|
||||
|
||||
.type-hint-expression {
|
||||
background:purple;
|
||||
}
|
||||
|
||||
.type-hint-date {
|
||||
background:pink;
|
||||
}
|
||||
|
||||
.type-hint-string {
|
||||
background:#3a87ad;
|
||||
}
|
||||
|
||||
.type-hint-function {
|
||||
background:green;
|
||||
}
|
||||
|
||||
.type-hint-object {
|
||||
background:#999;
|
||||
}
|
||||
|
||||
.type-hint-array {
|
||||
background:#F90;;
|
||||
}
|
||||
|
||||
.type-hint-boolean {
|
||||
background:rgb(18, 131, 39);
|
||||
}
|
||||
|
||||
.type-hint-number {
|
||||
background:rgb(189, 63, 66);
|
||||
}
|
||||
|
||||
.type-hint-regexp {
|
||||
background: rgb(90, 84, 189);
|
||||
}
|
||||
|
||||
.type-hint-domelement {
|
||||
background: rgb(95, 158, 160);
|
||||
}
|
||||
|
||||
.runnable-example-frame {
|
||||
width:100%;
|
||||
height:300px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius:5px;
|
||||
}
|
||||
|
||||
.runnable-example-tabs {
|
||||
margin-top:10px;
|
||||
margin-bottom:20px;
|
||||
}
|
||||
|
||||
.tutorial-nav {
|
||||
display:block;
|
||||
}
|
||||
|
||||
h1 + ul, h1 + ul > li,
|
||||
h2 + ul, h2 + ul > li,
|
||||
ul.tutorial-nav, ul.tutorial-nav > li,
|
||||
.usage > ul, .usage > ul > li,
|
||||
ul.methods, ul.methods > li,
|
||||
ul.events, ul.events > li {
|
||||
list-style:none;
|
||||
padding:0;
|
||||
}
|
||||
|
||||
h2 {
|
||||
border-top:1px solid #eee;
|
||||
margin-top:30px;
|
||||
padding-top:30px;
|
||||
}
|
||||
|
||||
h4 {
|
||||
margin-top:20px;
|
||||
padding-top:20px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
color:#428bca;
|
||||
position: relative;
|
||||
width: auto;
|
||||
display: inline-block;
|
||||
margin: 0 0 2px;
|
||||
overflow: hidden;
|
||||
border: 1px solid #e5e5e5;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
-ms-border-radius: 4px;
|
||||
-o-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
font-family: "Open Sans";
|
||||
font-weight: 600;
|
||||
height: auto;
|
||||
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ffffff), color-stop(100%, #f2f2f2));
|
||||
background-image: -webkit-linear-gradient(#ffffff, #f2f2f2);
|
||||
background-image: -moz-linear-gradient(#ffffff, #f2f2f2);
|
||||
background-image: -o-linear-gradient(#ffffff, #f2f2f2);
|
||||
background-image: linear-gradient(#ffffff, #f2f2f2);
|
||||
}
|
||||
|
||||
.btn + .btn {
|
||||
margin-left:10px;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
color:black!important;
|
||||
border: 1px solid #ddd!important;
|
||||
background:white!important;
|
||||
}
|
||||
|
||||
.view-source, .improve-docs {
|
||||
position:relative;
|
||||
z-index:100;
|
||||
}
|
||||
|
||||
.view-source {
|
||||
margin-right:10px;
|
||||
}
|
||||
|
||||
.improve-docs {
|
||||
float:right;
|
||||
}
|
||||
|
||||
.return-arguments,
|
||||
.return-arguments th,
|
||||
.return-arguments th + th,
|
||||
.return-arguments td,
|
||||
.return-arguments td + td {
|
||||
border-radius:0;
|
||||
border:0;
|
||||
}
|
||||
|
||||
.return-arguments td:first-child {
|
||||
width:100px;
|
||||
}
|
||||
|
||||
ul.methods > li,
|
||||
ul.events > li {
|
||||
margin-bottom:40px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width : 768px) {
|
||||
.picker, .picker select {
|
||||
width:auto;
|
||||
display:block;
|
||||
margin-bottom:10px;
|
||||
}
|
||||
.docs-navbar-primary {
|
||||
text-align:center;
|
||||
}
|
||||
.main-body-grid {
|
||||
margin-top:0;
|
||||
}
|
||||
.main-header-grid > .grid-left,
|
||||
.main-body-grid > .grid-left,
|
||||
.main-header-grid > .grid-right,
|
||||
.main-body-grid > .grid-right {
|
||||
display:block;
|
||||
float:none;
|
||||
width:auto!important;
|
||||
margin-left:0;
|
||||
}
|
||||
.main-body-grid > .grid-left,
|
||||
.header-fixed, .footer {
|
||||
position:static!important;
|
||||
}
|
||||
.main-body-grid > .grid-left {
|
||||
background:#efefef;
|
||||
margin-left:-1em;
|
||||
margin-right:-1em;
|
||||
padding:1em;
|
||||
width:auto!important;
|
||||
overflow:visible;
|
||||
}
|
||||
.main-header-grid > .grid-right,
|
||||
.main-body-grid > .grid-right {
|
||||
margin-left:0;
|
||||
}
|
||||
.main-body-grid .side-navigation {
|
||||
display:block!important;
|
||||
}
|
||||
.main-body-grid .side-navigation.ng-hide {
|
||||
display:none!important;
|
||||
}
|
||||
.nav-index-group .nav-index-listing {
|
||||
display:inline-block;
|
||||
padding:3px 0;
|
||||
}
|
||||
.nav-index-group .nav-index-listing:not(.nav-index-section) + .nav-index-listing:not(.nav-index-section):after {
|
||||
padding-right:5px;
|
||||
content:", ";
|
||||
}
|
||||
.nav-index-group .nav-index-listing:last-child {
|
||||
content:"";
|
||||
}
|
||||
.nav-index-group .nav-index-section {
|
||||
display:block;
|
||||
}
|
||||
.toc-toggle {
|
||||
margin-bottom:20px;
|
||||
}
|
||||
.toc-close {
|
||||
position: absolute;
|
||||
bottom: -50px;
|
||||
left: 50%;
|
||||
margin-left: -50%;
|
||||
text-align: center;
|
||||
padding: 5px;
|
||||
background: #eee;
|
||||
border-radius: 5px;
|
||||
width: 90%;
|
||||
border:1px solid #ddd;
|
||||
box-shadow:0 0 10px #bbb;
|
||||
}
|
||||
.navbar-brand {
|
||||
float:none;
|
||||
text-align:center;
|
||||
}
|
||||
.search-results-container {
|
||||
padding-bottom:60px;
|
||||
text-align:left;
|
||||
}
|
||||
.search-results-group {
|
||||
float:none!important;
|
||||
display:block!important;
|
||||
width:auto!important;
|
||||
border:0!important;
|
||||
padding:0!important;
|
||||
}
|
||||
.search-results-group .search-result {
|
||||
display:inline-block!important;
|
||||
padding:0 5px;
|
||||
width:auto!important;
|
||||
}
|
||||
.search-results-group .search-result:after {
|
||||
content:", ";
|
||||
}
|
||||
#wrapper {
|
||||
padding-bottom:0px;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
/* GitHub Theme */
|
||||
.prettyprint {
|
||||
background: white;
|
||||
font-family: Menlo, 'Bitstream Vera Sans Mono', 'DejaVu Sans Mono', Monaco, Consolas, monospace;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.pln {
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
@media screen {
|
||||
.str {
|
||||
color: #dd1144;
|
||||
}
|
||||
|
||||
.kwd {
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.com {
|
||||
color: #999988;
|
||||
}
|
||||
|
||||
.typ {
|
||||
color: #445588;
|
||||
}
|
||||
|
||||
.lit {
|
||||
color: #445588;
|
||||
}
|
||||
|
||||
.pun {
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.opn {
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.clo {
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.tag {
|
||||
color: navy;
|
||||
}
|
||||
|
||||
.atn {
|
||||
color: teal;
|
||||
}
|
||||
|
||||
.atv {
|
||||
color: #dd1144;
|
||||
}
|
||||
|
||||
.dec {
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.var {
|
||||
color: teal;
|
||||
}
|
||||
|
||||
.fun {
|
||||
color: #990000;
|
||||
}
|
||||
}
|
||||
@media print, projection {
|
||||
.str {
|
||||
color: #006600;
|
||||
}
|
||||
|
||||
.kwd {
|
||||
color: #006;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.com {
|
||||
color: #600;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.typ {
|
||||
color: #404;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.lit {
|
||||
color: #004444;
|
||||
}
|
||||
|
||||
.pun, .opn, .clo {
|
||||
color: #444400;
|
||||
}
|
||||
|
||||
.tag {
|
||||
color: #006;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.atn {
|
||||
color: #440044;
|
||||
}
|
||||
|
||||
.atv {
|
||||
color: #006600;
|
||||
}
|
||||
}
|
||||
/* Specify class=linenums on a pre to get line numbering */
|
||||
ol.linenums {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* IE indents via margin-left */
|
||||
li.L0,
|
||||
li.L1,
|
||||
li.L2,
|
||||
li.L3,
|
||||
li.L4,
|
||||
li.L5,
|
||||
li.L6,
|
||||
li.L7,
|
||||
li.L8,
|
||||
li.L9 {
|
||||
/* */
|
||||
}
|
||||
|
||||
/* Alternate shading for lines */
|
||||
li.L1,
|
||||
li.L3,
|
||||
li.L5,
|
||||
li.L7,
|
||||
li.L9 {
|
||||
/* */
|
||||
}
|
||||
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 49 KiB |
|
After Width: | Height: | Size: 57 KiB |
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
|
||||
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
|
||||
]>
|
||||
<svg version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
|
||||
x="0px" y="0px" width="687px" height="176px" viewBox="0 0 687 176" overflow="visible" enable-background="new 0 0 687 176"
|
||||
xml:space="preserve">
|
||||
<defs>
|
||||
</defs>
|
||||
<path fill="#FFFFFF" d="M179.011,125.328V54.527h9.158l43.322,57.035V54.527h8.666v70.801h-9.158l-43.326-57.536v57.536H179.011z
|
||||
M179.011,125.328"/>
|
||||
<path fill="#FFFFFF" d="M310.46,122.554c-5.708,2.182-11.864,3.269-18.467,3.269c-25.644,0-38.469-12.294-38.469-36.887
|
||||
c0-23.27,12.378-34.908,37.134-34.908c7.096,0,13.7,0.994,19.802,2.976v7.921c-6.103-2.311-12.378-3.468-18.813-3.468
|
||||
c-19.306,0-28.96,9.162-28.96,27.479c0,19.639,9.504,29.463,28.517,29.463c3.034,0,6.404-0.396,10.103-1.193V93.145h9.154V122.554z
|
||||
M310.46,122.554"/>
|
||||
<path fill="#FFFFFF" d="M325.067,97.996V54.523h9.154v43.473c0,13.598,6.768,20.4,20.303,20.4c13.531,0,20.301-6.803,20.301-20.4
|
||||
V54.523h9.158v43.473c0,18.556-9.82,27.825-29.459,27.825C334.886,125.821,325.067,116.552,325.067,97.996L325.067,97.996z
|
||||
M325.067,97.996"/>
|
||||
<path fill="#FFFFFF" d="M409.48,54.523v63.376h37.037v7.425h-46.191V54.523H409.48z M409.48,54.523"/>
|
||||
<path fill="#FFFFFF" d="M459.736,125.327h-9.504l35.201-80.146l35.199,80.146h-10.15l-9.158-22.282h-23.418l2.527-7.424h17.82
|
||||
l-13.217-32.088L459.736,125.327z M459.736,125.327"/>
|
||||
<path fill="#FFFFFF" d="M530.289,125.328V54.527h30.203c13.469,0,20.197,5.659,20.197,16.982c0,9.207-6.578,16.028-19.75,20.445
|
||||
l24.309,33.374h-12.086l-22.521-31.835v-5.992c13.531-2.151,20.301-7.344,20.301-15.598c0-6.533-3.766-9.801-11.293-9.801h-20.201
|
||||
v63.226H530.289z M530.289,125.328"/>
|
||||
<path fill="#B52E31" d="M619.561,54.523v50.405c0,13.603-8.006,20.396-24.016,20.396V117.9c9.902,0,14.857-4.329,14.857-12.973
|
||||
V54.523H619.561z M619.561,54.523"/>
|
||||
<path fill="#B52E31" d="M635.896,122.849v-8.418c7.428,2.639,15.447,3.965,24.064,3.965c12.178,0,18.271-4.457,18.271-13.372
|
||||
c0-7.584-4.492-11.385-13.469-11.385h-9.113c-14.818,0-22.234-6.435-22.234-19.31c0-13.531,9.492-20.303,28.479-20.303
|
||||
c8.25,0,15.922,0.998,23.021,2.976v8.418c-7.1-2.644-14.771-3.965-23.021-3.965c-12.875,0-19.311,4.293-19.311,12.875
|
||||
c0,7.588,4.352,11.385,13.066,11.385h9.113c15.08,0,22.627,6.439,22.627,19.31c0,13.864-9.141,20.796-27.43,20.796
|
||||
C651.344,125.819,643.324,124.826,635.896,122.849L635.896,122.849z M635.896,122.849"/>
|
||||
<path fill="#B2B2B2" d="M82.688,0L0,29.1l13.066,108.335l69.71,38.314l70.069-38.834l13.062-108.331L82.688,0z M82.688,0"/>
|
||||
<path fill="#B52E31" d="M157.66,34.846L82.496,9.214v157.381l62.991-34.861L157.66,34.846z M157.66,34.846"/>
|
||||
<path fill="#E23237" d="M9.279,35.308l11.196,96.889l62.019,34.398V9.211L9.279,35.308z M9.279,35.308"/>
|
||||
<path fill="#F2F2F2" d="M99.918,87.493L82.632,51.396L67.415,87.493H99.918z M106.508,102.672h-45.82l-10.251,25.64l-19.067,0.352
|
||||
L82.496,14.929l52.908,113.734h-17.673L106.508,102.672z M106.508,102.672"/>
|
||||
<path fill="#B2B2B2" d="M82.496,14.929l0.136,36.467l17.268,36.125H82.534l-0.039,15.127l24.012,0.023l11.223,25.996l18.245,0.339
|
||||
L82.496,14.929z M82.496,14.929"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 212 B |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 62 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 78 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 51 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 122 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 117 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 97 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 116 KiB |
|
After Width: | Height: | Size: 122 KiB |
|
After Width: | Height: | Size: 124 KiB |
|
After Width: | Height: | Size: 196 KiB |
|
After Width: | Height: | Size: 209 KiB |
|
After Width: | Height: | Size: 205 KiB |
|
After Width: | Height: | Size: 141 KiB |
@@ -89,29 +89,6 @@ directive.jsFiddle = function(getEmbeddedTemplate, escape, script) {
|
||||
};
|
||||
|
||||
|
||||
directive.code = function() {
|
||||
return {restrict: 'E', terminal: true};
|
||||
};
|
||||
|
||||
|
||||
directive.prettyprint = ['reindentCode', function(reindentCode) {
|
||||
return {
|
||||
restrict: 'C',
|
||||
compile: function(element) {
|
||||
var html = element.html();
|
||||
//ensure that angular won't compile {{ curly }} values
|
||||
html = html.replace(/\{\{/g, '<span>{{</span>')
|
||||
.replace(/\}\}/g, '<span>}}</span>');
|
||||
if (window.RUNNING_IN_NG_TEST_RUNNER) {
|
||||
element.html(html);
|
||||
}
|
||||
else {
|
||||
element.html(window.prettyPrintOne(reindentCode(html), undefined, true));
|
||||
}
|
||||
}
|
||||
};
|
||||
}];
|
||||
|
||||
|
||||
directive.ngSetText = ['getEmbeddedTemplate', function(getEmbeddedTemplate) {
|
||||
return {
|
||||
@@ -2,6 +2,56 @@
|
||||
|
||||
var directive = {};
|
||||
|
||||
directive.runnableExample = ['$templateCache', '$document', function($templateCache, $document) {
|
||||
var exampleClassNameSelector = '.runnable-example-file';
|
||||
var doc = $document[0];
|
||||
var tpl =
|
||||
'<nav class="runnable-example-tabs" ng-if="tabs">' +
|
||||
' <a ng-class="{active:$index==activeTabIndex}"' +
|
||||
'ng-repeat="tab in tabs track by $index" ' +
|
||||
'href="" ' +
|
||||
'class="btn"' +
|
||||
'ng-click="setTab($index)">' +
|
||||
' {{ tab }}' +
|
||||
' </a>' +
|
||||
'</nav>';
|
||||
|
||||
return {
|
||||
restrict: 'C',
|
||||
scope : true,
|
||||
controller : ['$scope', function($scope) {
|
||||
$scope.setTab = function(index) {
|
||||
var tab = $scope.tabs[index];
|
||||
$scope.activeTabIndex = index;
|
||||
$scope.$broadcast('tabChange', index, tab);
|
||||
};
|
||||
}],
|
||||
compile : function(element) {
|
||||
element.html(tpl + element.html());
|
||||
return function(scope, element) {
|
||||
var node = element[0];
|
||||
var examples = node.querySelectorAll(exampleClassNameSelector);
|
||||
var tabs = [], now = Date.now();
|
||||
angular.forEach(examples, function(child, index) {
|
||||
tabs.push(child.getAttribute('name'));
|
||||
});
|
||||
|
||||
if(tabs.length > 0) {
|
||||
scope.tabs = tabs;
|
||||
scope.$on('tabChange', function(e, index, title) {
|
||||
angular.forEach(examples, function(child) {
|
||||
child.style.display = 'none';
|
||||
});
|
||||
var selected = examples[index];
|
||||
selected.style.display = 'block';
|
||||
});
|
||||
scope.setTab(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}];
|
||||
|
||||
directive.dropdownToggle =
|
||||
['$document', '$location', '$window',
|
||||
function ($document, $location, $window) {
|
||||
@@ -0,0 +1,145 @@
|
||||
/* This code is taken from the AngularUI - Bootstrap Project (https://github.com/angular-ui/bootstrap)
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2012-2014 the AngularUI Team, https://github.com/organizations/angular-ui/teams/291112
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
angular.module('ui.bootstrap.dropdown', [])
|
||||
|
||||
.constant('dropdownConfig', {
|
||||
openClass: 'open'
|
||||
})
|
||||
|
||||
.service('dropdownService', ['$document', function($document) {
|
||||
var self = this, openScope = null;
|
||||
|
||||
this.open = function( dropdownScope ) {
|
||||
if ( !openScope ) {
|
||||
$document.bind('click', closeDropdown);
|
||||
$document.bind('keydown', escapeKeyBind);
|
||||
}
|
||||
|
||||
if ( openScope && openScope !== dropdownScope ) {
|
||||
openScope.isOpen = false;
|
||||
}
|
||||
|
||||
openScope = dropdownScope;
|
||||
};
|
||||
|
||||
this.close = function( dropdownScope ) {
|
||||
if ( openScope === dropdownScope ) {
|
||||
openScope = null;
|
||||
$document.unbind('click', closeDropdown);
|
||||
$document.unbind('keydown', escapeKeyBind);
|
||||
}
|
||||
};
|
||||
|
||||
var closeDropdown = function() {
|
||||
openScope.$apply(function() {
|
||||
openScope.isOpen = false;
|
||||
});
|
||||
};
|
||||
|
||||
var escapeKeyBind = function( evt ) {
|
||||
if ( evt.which === 27 ) {
|
||||
closeDropdown();
|
||||
}
|
||||
};
|
||||
}])
|
||||
|
||||
.controller('DropdownController', ['$scope', '$attrs', 'dropdownConfig', 'dropdownService', '$animate', function($scope, $attrs, dropdownConfig, dropdownService, $animate) {
|
||||
var self = this, openClass = dropdownConfig.openClass;
|
||||
|
||||
this.init = function( element ) {
|
||||
self.$element = element;
|
||||
$scope.isOpen = angular.isDefined($attrs.isOpen) ? $scope.$parent.$eval($attrs.isOpen) : false;
|
||||
};
|
||||
|
||||
this.toggle = function( open ) {
|
||||
return $scope.isOpen = arguments.length ? !!open : !$scope.isOpen;
|
||||
};
|
||||
|
||||
// Allow other directives to watch status
|
||||
this.isOpen = function() {
|
||||
return $scope.isOpen;
|
||||
};
|
||||
|
||||
$scope.$watch('isOpen', function( value ) {
|
||||
$animate[value ? 'addClass' : 'removeClass'](self.$element, openClass);
|
||||
|
||||
if ( value ) {
|
||||
dropdownService.open( $scope );
|
||||
} else {
|
||||
dropdownService.close( $scope );
|
||||
}
|
||||
|
||||
$scope.onToggle({ open: !!value });
|
||||
});
|
||||
|
||||
$scope.$on('$locationChangeSuccess', function() {
|
||||
$scope.isOpen = false;
|
||||
});
|
||||
}])
|
||||
|
||||
.directive('dropdown', function() {
|
||||
return {
|
||||
restrict: 'CA',
|
||||
controller: 'DropdownController',
|
||||
scope: {
|
||||
isOpen: '=?',
|
||||
onToggle: '&'
|
||||
},
|
||||
link: function(scope, element, attrs, dropdownCtrl) {
|
||||
dropdownCtrl.init( element );
|
||||
}
|
||||
};
|
||||
})
|
||||
|
||||
.directive('dropdownToggle', function() {
|
||||
return {
|
||||
restrict: 'CA',
|
||||
require: '?^dropdown',
|
||||
link: function(scope, element, attrs, dropdownCtrl) {
|
||||
if ( !dropdownCtrl ) {
|
||||
return;
|
||||
}
|
||||
|
||||
element.bind('click', function(event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
if ( !element.hasClass('disabled') && !element.prop('disabled') ) {
|
||||
scope.$apply(function() {
|
||||
dropdownCtrl.toggle();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// WAI-ARIA
|
||||
element.attr({ 'aria-haspopup': true, 'aria-expanded': false });
|
||||
scope.$watch(dropdownCtrl.isOpen, function( isOpen ) {
|
||||
element.attr('aria-expanded', !!isOpen);
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,23 @@
|
||||
angular.module('docsApp', [
|
||||
'ngRoute',
|
||||
'ngCookies',
|
||||
'ngSanitize',
|
||||
'ngAnimate',
|
||||
'DocsController',
|
||||
'versionsData',
|
||||
'pagesData',
|
||||
'directives',
|
||||
'errors',
|
||||
'examples',
|
||||
'search',
|
||||
'tutorials',
|
||||
'versions',
|
||||
'bootstrap',
|
||||
'bootstrapPrettify',
|
||||
'ui.bootstrap.dropdown'
|
||||
])
|
||||
|
||||
|
||||
.config(function($locationProvider) {
|
||||
$locationProvider.html5Mode(true).hashPrefix('!');
|
||||
});
|
||||
@@ -0,0 +1,36 @@
|
||||
angular.module('directives', [])
|
||||
|
||||
.directive('code', function() {
|
||||
return { restrict:'E', terminal: true };
|
||||
})
|
||||
|
||||
/**
|
||||
* backToTop Directive
|
||||
* @param {Function} $anchorScroll
|
||||
*
|
||||
* @description Ensure that the browser scrolls when the anchor is clicked
|
||||
*/
|
||||
.directive('backToTop', ['$anchorScroll', '$location', function($anchorScroll, $location) {
|
||||
return function link(scope, element) {
|
||||
element.on('click', function(event) {
|
||||
$location.hash('');
|
||||
scope.$apply($anchorScroll);
|
||||
});
|
||||
};
|
||||
}])
|
||||
|
||||
|
||||
.directive('code', function() {
|
||||
return {
|
||||
restrict: 'E',
|
||||
terminal: true,
|
||||
compile: function(element) {
|
||||
var linenums = element.hasClass('linenum') || element.parent()[0].nodeName === 'PRE';
|
||||
var match = /lang-(\S)+/.exec(element.className);
|
||||
var lang = match && match[1];
|
||||
var html = element.html();
|
||||
element.html(window.prettyPrintOne(html, lang, linenums));
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
angular.module('DocsController', [])
|
||||
|
||||
.controller('DocsController', function($scope, $rootScope, $location, $window, $cookies, NG_PAGES, NG_NAVIGATION, NG_VERSION) {
|
||||
|
||||
$scope.docsVersion = NG_VERSION.isSnapshot ? 'snapshot' : NG_VERSION.version;
|
||||
|
||||
$scope.fold = function(url) {
|
||||
if(url) {
|
||||
$scope.docs_fold = '/notes/' + url;
|
||||
if(/\/build/.test($window.location.href)) {
|
||||
$scope.docs_fold = '/build/docs' + $scope.docs_fold;
|
||||
}
|
||||
window.scrollTo(0,0);
|
||||
}
|
||||
else {
|
||||
$scope.docs_fold = null;
|
||||
}
|
||||
};
|
||||
var OFFLINE_COOKIE_NAME = 'ng-offline',
|
||||
INDEX_PATH = /^(\/|\/index[^\.]*.html)$/;
|
||||
|
||||
|
||||
/**********************************
|
||||
Publish methods
|
||||
***********************************/
|
||||
|
||||
$scope.navClass = function(navItem) {
|
||||
return {
|
||||
active: navItem.href && this.currentPage.path,
|
||||
'nav-index-section': navItem.type === 'section'
|
||||
};
|
||||
};
|
||||
|
||||
$scope.afterPartialLoaded = function() {
|
||||
var pagePath = $scope.currentPage ? $scope.currentPage.path : $location.path();
|
||||
$window._gaq.push(['_trackPageview', pagePath]);
|
||||
};
|
||||
|
||||
/** stores a cookie that is used by apache to decide which manifest ot send */
|
||||
$scope.enableOffline = function() {
|
||||
//The cookie will be good for one year!
|
||||
var date = new Date();
|
||||
date.setTime(date.getTime()+(365*24*60*60*1000));
|
||||
var expires = "; expires="+date.toGMTString();
|
||||
var value = angular.version.full;
|
||||
document.cookie = OFFLINE_COOKIE_NAME + "="+value+expires+"; path=" + $location.path;
|
||||
|
||||
//force the page to reload so server can serve new manifest file
|
||||
window.location.reload(true);
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**********************************
|
||||
Watches
|
||||
***********************************/
|
||||
|
||||
|
||||
$scope.$watch(function docsPathWatch() {return $location.path(); }, function docsPathWatchAction(path) {
|
||||
|
||||
var currentPage = $scope.currentPage = NG_PAGES[path];
|
||||
if ( !currentPage && path.charAt(0)==='/' ) {
|
||||
// Strip off leading slash
|
||||
path = path.substr(1);
|
||||
}
|
||||
|
||||
currentPage = $scope.currentPage = NG_PAGES[path];
|
||||
if ( !currentPage && path.charAt(path.length-1) === '/' && path.length > 1 ) {
|
||||
// Strip off trailing slash
|
||||
path = path.substr(0, path.length-1);
|
||||
}
|
||||
|
||||
currentPage = $scope.currentPage = NG_PAGES[path];
|
||||
if ( !currentPage && /\/index$/.test(path) ) {
|
||||
// Strip off index from the end
|
||||
path = path.substr(0, path.length - 6);
|
||||
}
|
||||
|
||||
currentPage = $scope.currentPage = NG_PAGES[path];
|
||||
|
||||
if ( currentPage ) {
|
||||
$scope.currentArea = currentPage && NG_NAVIGATION[currentPage.area];
|
||||
var pathParts = currentPage.path.split('/');
|
||||
var breadcrumb = $scope.breadcrumb = [];
|
||||
var breadcrumbPath = '';
|
||||
angular.forEach(pathParts, function(part) {
|
||||
breadcrumbPath += part;
|
||||
breadcrumb.push({ name: (NG_PAGES[breadcrumbPath]&&NG_PAGES[breadcrumbPath].name) || part, url: breadcrumbPath });
|
||||
breadcrumbPath += '/';
|
||||
});
|
||||
} else {
|
||||
$scope.currentArea = NG_NAVIGATION['api'];
|
||||
$scope.breadcrumb = [];
|
||||
}
|
||||
});
|
||||
|
||||
/**********************************
|
||||
Initialize
|
||||
***********************************/
|
||||
|
||||
$scope.versionNumber = angular.version.full;
|
||||
$scope.version = angular.version.full + " " + angular.version.codeName;
|
||||
$scope.subpage = false;
|
||||
$scope.offlineEnabled = ($cookies[OFFLINE_COOKIE_NAME] == angular.version.full);
|
||||
$scope.futurePartialTitle = null;
|
||||
$scope.loading = 0;
|
||||
$scope.$cookies = $cookies;
|
||||
|
||||
$cookies.platformPreference = $cookies.platformPreference || 'gitUnix';
|
||||
|
||||
if (!$location.path() || INDEX_PATH.test($location.path())) {
|
||||
$location.path('/api').replace();
|
||||
}
|
||||
|
||||
// bind escape to hash reset callback
|
||||
angular.element(window).on('keydown', function(e) {
|
||||
if (e.keyCode === 27) {
|
||||
$scope.$apply(function() {
|
||||
$scope.subpage = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,62 @@
|
||||
angular.module('errors', ['ngSanitize'])
|
||||
|
||||
.filter('errorLink', ['$sanitize', function ($sanitize) {
|
||||
var LINKY_URL_REGEXP = /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s\.\;\,\(\)\{\}<>]/g,
|
||||
MAILTO_REGEXP = /^mailto:/,
|
||||
STACK_TRACE_REGEXP = /:\d+:\d+$/;
|
||||
|
||||
var truncate = function (text, nchars) {
|
||||
if (text.length > nchars) {
|
||||
return text.substr(0, nchars - 3) + '...';
|
||||
}
|
||||
return text;
|
||||
};
|
||||
|
||||
return function (text, target) {
|
||||
var targetHtml = target ? ' target="' + target + '"' : '';
|
||||
|
||||
if (!text) return text;
|
||||
|
||||
return $sanitize(text.replace(LINKY_URL_REGEXP, function (url) {
|
||||
if (STACK_TRACE_REGEXP.test(url)) {
|
||||
return url;
|
||||
}
|
||||
|
||||
// if we did not match ftp/http/mailto then assume mailto
|
||||
if (!/^((ftp|https?):\/\/|mailto:)/.test(url)) url = 'mailto:' + url;
|
||||
|
||||
return '<a' + targetHtml + ' href="' + url +'">' +
|
||||
truncate(url.replace(MAILTO_REGEXP, ''), 60) +
|
||||
'</a>';
|
||||
}));
|
||||
};
|
||||
}])
|
||||
|
||||
|
||||
.directive('errorDisplay', ['$location', 'errorLinkFilter', function ($location, errorLinkFilter) {
|
||||
var interpolate = function (formatString) {
|
||||
var formatArgs = arguments;
|
||||
return formatString.replace(/\{\d+\}/g, function (match) {
|
||||
// Drop the braces and use the unary plus to convert to an integer.
|
||||
// The index will be off by one because of the formatString.
|
||||
var index = +match.slice(1, -1);
|
||||
if (index + 1 >= formatArgs.length) {
|
||||
return match;
|
||||
}
|
||||
return formatArgs[index+1];
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
link: function (scope, element, attrs) {
|
||||
var search = $location.search(),
|
||||
formatArgs = [attrs.errorDisplay],
|
||||
i;
|
||||
|
||||
for (i = 0; angular.isDefined(search['p'+i]); i++) {
|
||||
formatArgs.push(search['p'+i]);
|
||||
}
|
||||
element.html(errorLinkFilter(interpolate.apply(null, formatArgs), '_blank'));
|
||||
}
|
||||
};
|
||||
}]);
|
||||
@@ -0,0 +1,266 @@
|
||||
angular.module('examples', [])
|
||||
|
||||
.directive('sourceEdit', function(getEmbeddedTemplate) {
|
||||
return {
|
||||
template: '<div class="btn-group pull-right">' +
|
||||
'<a class="btn dropdown-toggle btn-primary" data-toggle="dropdown" href>' +
|
||||
' <i class="icon-pencil icon-white"></i> Edit<span class="caret"></span>' +
|
||||
'</a>' +
|
||||
'<ul class="dropdown-menu">' +
|
||||
' <li><a ng-click="plunkr($event)" href="">In Plunkr</a></li>' +
|
||||
' <li><a ng-click="fiddle($event)" href="">In JsFiddle</a></li>' +
|
||||
'</ul>' +
|
||||
'</div>',
|
||||
scope: true,
|
||||
controller: function($scope, $attrs, openJsFiddle, openPlunkr) {
|
||||
var sources = {
|
||||
module: $attrs.sourceEdit,
|
||||
deps: read($attrs.sourceEditDeps),
|
||||
html: read($attrs.sourceEditHtml),
|
||||
css: read($attrs.sourceEditCss),
|
||||
js: read($attrs.sourceEditJs),
|
||||
json: read($attrs.sourceEditJson),
|
||||
unit: read($attrs.sourceEditUnit),
|
||||
scenario: read($attrs.sourceEditScenario)
|
||||
};
|
||||
$scope.fiddle = function(e) {
|
||||
e.stopPropagation();
|
||||
openJsFiddle(sources);
|
||||
};
|
||||
$scope.plunkr = function(e) {
|
||||
e.stopPropagation();
|
||||
openPlunkr(sources);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
function read(text) {
|
||||
var files = [];
|
||||
angular.forEach(text ? text.split(' ') : [], function(refId) {
|
||||
// refId is index.html-343, so we need to strip the unique ID when exporting the name
|
||||
files.push({name: refId.replace(/-\d+$/, ''), content: getEmbeddedTemplate(refId)});
|
||||
});
|
||||
return files;
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
.factory('angularUrls', function($document) {
|
||||
var urls = {};
|
||||
|
||||
angular.forEach($document.find('script'), function(script) {
|
||||
var match = script.src.match(/^.*\/(angular[^\/]*\.js)$/);
|
||||
if (match) {
|
||||
urls[match[1].replace(/(\-\d.*)?(\.min)?\.js$/, '.js')] = match[0];
|
||||
}
|
||||
});
|
||||
|
||||
return urls;
|
||||
})
|
||||
|
||||
|
||||
.factory('formPostData', function($document) {
|
||||
return function(url, fields) {
|
||||
var form = angular.element('<form style="display: none;" method="post" action="' + url + '" target="_blank"></form>');
|
||||
angular.forEach(fields, function(value, name) {
|
||||
var input = angular.element('<input type="hidden" name="' + name + '">');
|
||||
input.attr('value', value);
|
||||
form.append(input);
|
||||
});
|
||||
$document.find('body').append(form);
|
||||
form[0].submit();
|
||||
form.remove();
|
||||
};
|
||||
})
|
||||
|
||||
|
||||
.factory('prepareDefaultAppModule', function() {
|
||||
return function(content) {
|
||||
var deps = [];
|
||||
angular.forEach(content.deps, function(file) {
|
||||
if(file.name == 'angular-animate.js') {
|
||||
deps.push('ngAnimate');
|
||||
}
|
||||
});
|
||||
|
||||
var moduleName = 'App';
|
||||
return {
|
||||
module : moduleName,
|
||||
script : "angular.module('" + moduleName + "', [" +
|
||||
(deps.length ? "'" + deps.join("','") + "'" : "") + "]);\n\n"
|
||||
};
|
||||
};
|
||||
})
|
||||
|
||||
.factory('prepareEditorAssetTags', function(angularUrls) {
|
||||
return function(content, options) {
|
||||
options = options || {};
|
||||
var includeLocalFiles = options.includeLocalFiles;
|
||||
var html = makeScriptTag(angularUrls['angular.js']);
|
||||
|
||||
var allFiles = [].concat(content.js, content.css, content.html, content.json);
|
||||
angular.forEach(content.deps, function(file) {
|
||||
if (file.name !== 'angular.js') {
|
||||
var isLocal = false;
|
||||
for(var i=0;i<allFiles.length;i++) {
|
||||
if(allFiles[i].name == file.name) {
|
||||
isLocal = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!(isLocal && !includeLocalFiles)) {
|
||||
var assetUrl = angularUrls[file.name] || file.name;
|
||||
html += makeScriptTag(assetUrl);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if(includeLocalFiles) {
|
||||
angular.forEach(content.css, function(file, index) {
|
||||
html += makeCssLinkTag(file.name);
|
||||
});
|
||||
}
|
||||
|
||||
return html;
|
||||
|
||||
|
||||
function makeScriptTag(src) {
|
||||
return '<script type="text/javascript" src="' + src + '"></script>\n';
|
||||
}
|
||||
|
||||
function makeCssLinkTag(src) {
|
||||
return '<link rel="stylesheet" type="text/css" href="' + src + '" />\n';
|
||||
}
|
||||
};
|
||||
})
|
||||
|
||||
|
||||
.factory('openPlunkr', function(templateMerge, formPostData, prepareEditorAssetTags, prepareDefaultAppModule) {
|
||||
return function(content) {
|
||||
var hasRouting = false;
|
||||
angular.forEach(content.deps, function(file) {
|
||||
hasRouting = hasRouting || file.name == 'angular-route.js';
|
||||
});
|
||||
var indexHtmlContent = '<!doctype html>\n' +
|
||||
'<html ng-app="{{module}}">\n' +
|
||||
' <head>\n' +
|
||||
'{{scriptDeps}}';
|
||||
|
||||
if(hasRouting) {
|
||||
indexHtmlContent += '<script type="text/javascript">\n' +
|
||||
'//this is here to make plunkr work with AngularJS routing\n' +
|
||||
'angular.element(document.getElementsByTagName(\'head\')).append(' +
|
||||
'angular.element(\'<base href="\' + window.location.pathname + \'" />\')' +
|
||||
');\n' +
|
||||
'</script>\n';
|
||||
}
|
||||
|
||||
indexHtmlContent += '</head>\n' +
|
||||
' <body>\n\n' +
|
||||
'{{indexContents}}\n\n' +
|
||||
' </body>\n' +
|
||||
'</html>\n';
|
||||
|
||||
indexProp = {
|
||||
module: content.module,
|
||||
scriptDeps: prepareEditorAssetTags(content, { includeLocalFiles : true }),
|
||||
indexContents: content.html[0].content
|
||||
};
|
||||
|
||||
var allFiles = [].concat(content.js, content.css, content.html, content.json);
|
||||
|
||||
if(!content.module) {
|
||||
var moduleData = prepareDefaultAppModule(content);
|
||||
indexProp.module = moduleData.module;
|
||||
|
||||
var found = false;
|
||||
angular.forEach(content.js, function(file) {
|
||||
if(file.name == 'script.js') {
|
||||
file.content = moduleData.script + file.content;
|
||||
found = true;
|
||||
}
|
||||
});
|
||||
if(!found) {
|
||||
indexProp.scriptDeps += '<script type="text/javascript" src="script.js"></script>\n';
|
||||
allFiles.push({
|
||||
name : 'script.js',
|
||||
content : moduleData.script
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var postData = {};
|
||||
|
||||
angular.forEach(allFiles, function(file, index) {
|
||||
if (file.content && file.name != 'index.html') {
|
||||
postData['files[' + file.name + ']'] = file.content;
|
||||
}
|
||||
});
|
||||
|
||||
postData['files[index.html]'] = templateMerge(indexHtmlContent, indexProp);
|
||||
postData['tags[]'] = "angularjs";
|
||||
|
||||
postData.private = true;
|
||||
postData.description = 'AngularJS Example Plunkr';
|
||||
|
||||
formPostData('http://plnkr.co/edit/?p=preview', postData);
|
||||
};
|
||||
})
|
||||
|
||||
.factory('openJsFiddle', function(templateMerge, formPostData, prepareEditorAssetTags, prepareDefaultAppModule) {
|
||||
var HTML = '<div ng-app=\"{{module}}\">\n{{html:2}}</div>',
|
||||
CSS = '</style> <!-- Ugly Hack to make remote files preload in jsFiddle --> \n' +
|
||||
'{{head:0}}<style>{{css}}',
|
||||
SCRIPT = '{{script}}',
|
||||
SCRIPT_CACHE = '\n\n<!-- {{name}} -->\n<script type="text/ng-template" id="{{name}}">\n{{content:2}}</script>',
|
||||
BASE_HREF_TAG = '<!-- Ugly Hack to make AngularJS routing work inside of jsFiddle -->\n' +
|
||||
'<base href="/" />\n\n';
|
||||
|
||||
return function(content) {
|
||||
var prop = {
|
||||
module: content.module,
|
||||
html: '',
|
||||
css: '',
|
||||
script: ''
|
||||
};
|
||||
if(!prop.module) {
|
||||
var moduleData = prepareDefaultAppModule(content);
|
||||
prop.script = moduleData.script;
|
||||
prop.module = moduleData.module;
|
||||
}
|
||||
|
||||
angular.forEach(content.html, function(file, index) {
|
||||
if (index) {
|
||||
prop.html += templateMerge(SCRIPT_CACHE, file);
|
||||
} else {
|
||||
prop.html += file.content;
|
||||
}
|
||||
});
|
||||
|
||||
prop.head = prepareEditorAssetTags(content, { includeLocalFiles : false });
|
||||
|
||||
angular.forEach(content.js, function(file, index) {
|
||||
prop.script += file.content;
|
||||
});
|
||||
|
||||
angular.forEach(content.css, function(file, index) {
|
||||
prop.css += file.content;
|
||||
});
|
||||
|
||||
var hasRouting = false;
|
||||
angular.forEach(content.deps, function(file) {
|
||||
hasRouting = hasRouting || file.name == 'angular-route.js';
|
||||
});
|
||||
|
||||
var compiledHTML = templateMerge(HTML, prop);
|
||||
if(hasRouting) {
|
||||
compiledHTML = BASE_HREF_TAG + compiledHTML;
|
||||
}
|
||||
formPostData("http://jsfiddle.net/api/post/library/pure/", {
|
||||
title: 'AngularJS Example',
|
||||
html: compiledHTML,
|
||||
js: templateMerge(SCRIPT, prop),
|
||||
css: templateMerge(CSS, prop)
|
||||
});
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,24 @@
|
||||
angular.module('docsApp.navigationService', [])
|
||||
|
||||
.factory('navigationService', function($window) {
|
||||
var service = {
|
||||
currentPage: null,
|
||||
currentVersion: null,
|
||||
changePage: function(newPage) {
|
||||
|
||||
},
|
||||
changeVersion: function(newVersion) {
|
||||
|
||||
//TODO =========
|
||||
// var currentPagePath = '';
|
||||
|
||||
// // preserve URL path when switching between doc versions
|
||||
// if (angular.isObject($rootScope.currentPage) && $rootScope.currentPage.section && $rootScope.currentPage.id) {
|
||||
// currentPagePath = '/' + $rootScope.currentPage.section + '/' + $rootScope.currentPage.id;
|
||||
// }
|
||||
|
||||
// $window.location = version.url + currentPagePath;
|
||||
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,153 @@
|
||||
angular.module('search', [])
|
||||
|
||||
.controller('DocsSearchCtrl', ['$scope', '$location', 'docsSearch', function($scope, $location, docsSearch) {
|
||||
function clearResults() {
|
||||
$scope.results = [];
|
||||
$scope.colClassName = null;
|
||||
$scope.hasResults = false;
|
||||
}
|
||||
|
||||
$scope.search = function(q) {
|
||||
var MIN_SEARCH_LENGTH = 3;
|
||||
if(q.length >= MIN_SEARCH_LENGTH) {
|
||||
var results = docsSearch(q);
|
||||
var totalAreas = 0;
|
||||
for(var i in results) {
|
||||
++totalAreas;
|
||||
}
|
||||
if(totalAreas > 0) {
|
||||
$scope.colClassName = 'cols-' + totalAreas;
|
||||
}
|
||||
$scope.hasResults = totalAreas > 0;
|
||||
$scope.results = results;
|
||||
}
|
||||
else {
|
||||
clearResults();
|
||||
}
|
||||
if(!$scope.$$phase) $scope.$apply();
|
||||
};
|
||||
$scope.submit = function() {
|
||||
var result;
|
||||
for(var i in $scope.results) {
|
||||
result = $scope.results[i][0];
|
||||
if(result) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(result) {
|
||||
$location.path(result.url);
|
||||
$scope.hideResults();
|
||||
}
|
||||
};
|
||||
$scope.hideResults = function() {
|
||||
clearResults();
|
||||
$scope.q = '';
|
||||
};
|
||||
}])
|
||||
|
||||
.controller('Error404SearchCtrl', ['$scope', '$location', 'docsSearch', function($scope, $location, docsSearch) {
|
||||
$scope.results = docsSearch($location.path().split(/[\/\.:]/).pop());
|
||||
}])
|
||||
|
||||
.factory('lunrSearch', function() {
|
||||
return function(properties) {
|
||||
if (window.RUNNING_IN_NG_TEST_RUNNER) return null;
|
||||
|
||||
var engine = lunr(properties);
|
||||
return {
|
||||
store : function(values) {
|
||||
engine.add(values);
|
||||
},
|
||||
search : function(q) {
|
||||
return engine.search(q);
|
||||
}
|
||||
};
|
||||
};
|
||||
})
|
||||
|
||||
.factory('docsSearch', ['$rootScope','lunrSearch', 'NG_PAGES',
|
||||
function($rootScope, lunrSearch, NG_PAGES) {
|
||||
if (window.RUNNING_IN_NG_TEST_RUNNER) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var index = lunrSearch(function() {
|
||||
this.ref('id');
|
||||
this.field('title', {boost: 50});
|
||||
this.field('keywords', { boost : 20 });
|
||||
});
|
||||
|
||||
angular.forEach(NG_PAGES, function(page, key) {
|
||||
if(page.searchTerms) {
|
||||
index.store({
|
||||
id : key,
|
||||
title : page.searchTerms.titleWords,
|
||||
keywords : page.searchTerms.keywords
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
return function(q) {
|
||||
var results = {
|
||||
api : [],
|
||||
tutorial : [],
|
||||
guide : [],
|
||||
error : [],
|
||||
misc : []
|
||||
};
|
||||
angular.forEach(index.search(q), function(result) {
|
||||
var key = result.ref;
|
||||
var item = NG_PAGES[key];
|
||||
var area = item.area;
|
||||
item.path = key;
|
||||
|
||||
var limit = area == 'api' ? 40 : 14;
|
||||
if(results[area].length < limit) {
|
||||
results[area].push(item);
|
||||
}
|
||||
});
|
||||
return results;
|
||||
};
|
||||
}])
|
||||
|
||||
.directive('focused', function($timeout) {
|
||||
return function(scope, element, attrs) {
|
||||
element[0].focus();
|
||||
element.on('focus', function() {
|
||||
scope.$apply(attrs.focused + '=true');
|
||||
});
|
||||
element.on('blur', function() {
|
||||
// have to use $timeout, so that we close the drop-down after the user clicks,
|
||||
// otherwise when the user clicks we process the closing before we process the click.
|
||||
$timeout(function() {
|
||||
scope.$eval(attrs.focused + '=false');
|
||||
});
|
||||
});
|
||||
scope.$eval(attrs.focused + '=true');
|
||||
};
|
||||
})
|
||||
|
||||
.directive('docsSearchInput', ['$document',function($document) {
|
||||
return function(scope, element, attrs) {
|
||||
var ESCAPE_KEY_KEYCODE = 27,
|
||||
FORWARD_SLASH_KEYCODE = 191;
|
||||
angular.element($document[0].body).bind('keydown', function(event) {
|
||||
var input = element[0];
|
||||
if(event.keyCode == FORWARD_SLASH_KEYCODE && document.activeElement != input) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
input.focus();
|
||||
}
|
||||
});
|
||||
|
||||
element.bind('keydown', function(event) {
|
||||
if(event.keyCode == ESCAPE_KEY_KEYCODE) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
scope.$apply(function() {
|
||||
scope.hideResults();
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
}]);
|
||||
@@ -0,0 +1,58 @@
|
||||
angular.module('tutorials', [])
|
||||
|
||||
.directive('docTutorialNav', function(templateMerge) {
|
||||
var pages = [
|
||||
'',
|
||||
'step_00', 'step_01', 'step_02', 'step_03', 'step_04',
|
||||
'step_05', 'step_06', 'step_07', 'step_08', 'step_09',
|
||||
'step_10', 'step_11', 'step_12', 'the_end'
|
||||
];
|
||||
return {
|
||||
compile: function(element, attrs) {
|
||||
var seq = 1 * attrs.docTutorialNav,
|
||||
props = {
|
||||
seq: seq,
|
||||
prev: pages[seq],
|
||||
next: pages[2 + seq],
|
||||
diffLo: seq ? (seq - 1): '0~1',
|
||||
diffHi: seq
|
||||
};
|
||||
|
||||
element.addClass('btn-group');
|
||||
element.addClass('tutorial-nav');
|
||||
element.append(templateMerge(
|
||||
'<a href="tutorial/{{prev}}"><li class="btn btn-primary"><i class="glyphicon glyphicon-step-backward"></i> Previous</li></a>\n' +
|
||||
'<a href="http://angular.github.com/angular-phonecat/step-{{seq}}/app"><li class="btn btn-primary"><i class="glyphicon glyphicon-play"></i> Live Demo</li></a>\n' +
|
||||
'<a href="https://github.com/angular/angular-phonecat/compare/step-{{diffLo}}...step-{{diffHi}}"><li class="btn btn-primary"><i class="glyphicon glyphicon-search"></i> Code Diff</li></a>\n' +
|
||||
'<a href="tutorial/{{next}}"><li class="btn btn-primary">Next <i class="glyphicon glyphicon-step-forward"></i></li></a>', props));
|
||||
}
|
||||
};
|
||||
})
|
||||
|
||||
|
||||
.directive('docTutorialReset', function() {
|
||||
function tab(name, command, id, step) {
|
||||
return '' +
|
||||
' <div class=\'tab-pane well\' title="' + name + '" value="' + id + '">\n' +
|
||||
' <ol>\n' +
|
||||
' <li><p>Reset the workspace to step ' + step + '.</p>' +
|
||||
' <pre>' + command + '</pre></li>\n' +
|
||||
' <li><p>Refresh your browser or check the app out on <a href="http://angular.github.com/angular-phonecat/step-' + step + '/app">Angular\'s server</a>.</p></li>\n' +
|
||||
' </ol>\n' +
|
||||
' </div>\n';
|
||||
}
|
||||
|
||||
return {
|
||||
compile: function(element, attrs) {
|
||||
var step = attrs.docTutorialReset;
|
||||
element.html(
|
||||
'<div ng-hide="show">' +
|
||||
'<p><a href="" ng-click="show=true;$event.stopPropagation()">Workspace Reset Instructions ➤</a></p>' +
|
||||
'</div>\n' +
|
||||
'<div class="tabbable" ng-show="show" ng-model="$cookies.platformPreference">\n' +
|
||||
tab('Git on Mac/Linux', 'git checkout -f step-' + step, 'gitUnix', step) +
|
||||
tab('Git on Windows', 'git checkout -f step-' + step, 'gitWin', step) +
|
||||
'</div>\n');
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,15 @@
|
||||
angular.module('versions', [])
|
||||
|
||||
.controller('DocsVersionsCtrl', ['$scope', '$location', '$window', 'NG_VERSIONS', function($scope, $location, $window, NG_VERSIONS) {
|
||||
$scope.docs_versions = NG_VERSIONS;
|
||||
$scope.docs_version = NG_VERSIONS[0];
|
||||
|
||||
$scope.jumpToDocsVersion = function(version) {
|
||||
var currentPagePath = $location.path();
|
||||
|
||||
// TODO: We need to do some munging of the path for different versions of the API...
|
||||
|
||||
|
||||
$window.location = version.docsUrl + currentPagePath;
|
||||
};
|
||||
}]);
|
||||
@@ -0,0 +1,33 @@
|
||||
describe("DocsController", function() {
|
||||
var $scope;
|
||||
|
||||
angular.module('fake', [])
|
||||
.value('$cookies', {})
|
||||
.value('NG_PAGES', {})
|
||||
.value('NG_NAVIGATION', {})
|
||||
.value('NG_VERSION', {});
|
||||
|
||||
beforeEach(module('fake', 'DocsController'));
|
||||
beforeEach(inject(function($rootScope, $controller) {
|
||||
$scope = $rootScope;
|
||||
$controller('DocsController', { $scope: $scope });
|
||||
}));
|
||||
|
||||
|
||||
describe('afterPartialLoaded', function() {
|
||||
it("should update the Google Analytics with currentPage path if currentPage exists", inject(function($window) {
|
||||
$window._gaq = [];
|
||||
$scope.currentPage = { path: 'a/b/c' };
|
||||
$scope.afterPartialLoaded();
|
||||
expect($window._gaq.pop()).toEqual(['_trackPageview', 'a/b/c']);
|
||||
}));
|
||||
|
||||
|
||||
it("should update the Google Analytics with $location.path if currentPage is missing", inject(function($window, $location) {
|
||||
$window._gaq = [];
|
||||
spyOn($location, 'path').andReturn('x/y/z');
|
||||
$scope.afterPartialLoaded();
|
||||
expect($window._gaq.pop()).toEqual(['_trackPageview', 'x/y/z']);
|
||||
}));
|
||||
});
|
||||
});
|
||||
@@ -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.empty();
|
||||
});
|
||||
|
||||
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,157 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
describe('bootstrap', function() {
|
||||
var $compile, $rootScope, element;
|
||||
|
||||
function clickTab(element, index) {
|
||||
browserTrigger(element.children().eq(0).children().eq(index));
|
||||
}
|
||||
|
||||
beforeEach(module('bootstrap'));
|
||||
beforeEach(inject(function(_$compile_, _$rootScope_) {
|
||||
$compile = _$compile_;
|
||||
$rootScope = _$rootScope_;
|
||||
}));
|
||||
beforeEach(function(){
|
||||
function findTab(element, index) {
|
||||
return _jQuery(element[0]).find('> .nav-tabs > li').eq(index);
|
||||
}
|
||||
function findTabPane(element, index) {
|
||||
return _jQuery(element[0]).find('> .tab-content > .tab-pane').eq(index);
|
||||
}
|
||||
|
||||
this.addMatchers({
|
||||
toHaveTab: function(index, title) {
|
||||
var tab = findTab(element, index);
|
||||
|
||||
this.message = function() {
|
||||
if (tab.length) {
|
||||
return 'Expect tab index ' + index + ' to be ' + toJson(title) + ' but was ' + toJson(tab.text());
|
||||
} else {
|
||||
return 'Expect tab index ' + index + ' to be ' + toJson(title) + ' but there are only ' +
|
||||
element.children().length + ' tabs.';
|
||||
}
|
||||
};
|
||||
|
||||
return tab.length && tab.text() == title;
|
||||
},
|
||||
|
||||
toHaveTabPane: function(index, title) {
|
||||
var tabPane = findTabPane(element, index);
|
||||
|
||||
this.message = function() {
|
||||
if (tabPane.length) {
|
||||
return 'Expect tab pane index ' + index + ' to be ' + toJson(title) + ' but was ' + toJson(tabPane.text());
|
||||
} else {
|
||||
return 'Expect tab pane index ' + index + ' to be ' + toJson(title) + ' but there are only ' +
|
||||
element.children().length + 'tab panes.';
|
||||
}
|
||||
};
|
||||
|
||||
return tabPane.length && tabPane.text() == title;
|
||||
},
|
||||
|
||||
toHaveSelected: function(index) {
|
||||
var tab = findTab(element, index);
|
||||
var tabPane = findTabPane(element, index);
|
||||
|
||||
this.message = function() {
|
||||
return 'Expect tab index ' + index + ' to be selected\n' +
|
||||
' TAB: ' + angular.mock.dump(tab) + '\n' +
|
||||
'TAB-PANE: ' + angular.mock.dump(tabPane);
|
||||
};
|
||||
|
||||
return tabPane.hasClass('active') && tab.hasClass('active');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
dealoc(element);
|
||||
});
|
||||
|
||||
describe('tabbable', function() {
|
||||
|
||||
it('should create the right structure', function() {
|
||||
element = $compile(
|
||||
'<div class="tabbable">' +
|
||||
'<div class="tab-pane" title="first">tab1</div>' +
|
||||
'<div class="tab-pane" title="second">tab2</div>' +
|
||||
'</div>')($rootScope);
|
||||
|
||||
$rootScope.$apply();
|
||||
|
||||
expect(element).toHaveTab(0, 'first');
|
||||
expect(element).toHaveTab(1, 'second');
|
||||
|
||||
expect(element).toHaveTabPane(0, 'tab1');
|
||||
expect(element).toHaveTabPane(1, 'tab2');
|
||||
|
||||
expect(element).toHaveSelected(0);
|
||||
});
|
||||
|
||||
|
||||
it('should respond to tab click', function(){
|
||||
element = $compile(
|
||||
'<div class="tabbable">' +
|
||||
'<div class="tab-pane" title="first">tab1</div>' +
|
||||
'<div class="tab-pane" title="second">tab2</div>' +
|
||||
'</div>')($rootScope);
|
||||
|
||||
expect(element).toHaveSelected(0);
|
||||
clickTab(element, 1);
|
||||
expect(element).toHaveSelected(1);
|
||||
});
|
||||
|
||||
|
||||
it('should select the first tab in repeater', function() {
|
||||
element = $compile(
|
||||
'<div class="tabbable">' +
|
||||
'<div class="tab-pane" ng-repeat="id in [1,2,3]" title="Tab {{id}}" value="tab-{{id}}">' +
|
||||
'Tab content {{id}}!' +
|
||||
'</div>' +
|
||||
'</div>')($rootScope);
|
||||
$rootScope.$apply();
|
||||
|
||||
expect(element).toHaveSelected(0);
|
||||
});
|
||||
|
||||
|
||||
describe('ngModel', function() {
|
||||
it('should bind to model', function() {
|
||||
$rootScope.tab = 'B';
|
||||
|
||||
element = $compile(
|
||||
'<div class="tabbable" ng-model="tab">' +
|
||||
'<div class="tab-pane" title="first" value="A">tab1</div>' +
|
||||
'<div class="tab-pane" title="second" value="B">tab2</div>' +
|
||||
'</div>')($rootScope);
|
||||
|
||||
$rootScope.$apply();
|
||||
expect(element).toHaveSelected(1);
|
||||
|
||||
$rootScope.tab = 'A';
|
||||
$rootScope.$apply();
|
||||
expect(element).toHaveSelected(0);
|
||||
|
||||
clickTab(element, 1);
|
||||
expect($rootScope.tab).toEqual('B');
|
||||
expect(element).toHaveSelected(1);
|
||||
});
|
||||
|
||||
|
||||
it('should not overwrite the model', function() {
|
||||
$rootScope.tab = 'tab-2';
|
||||
element = $compile(
|
||||
'<div class="tabbable" ng-model="tab">' +
|
||||
'<div class="tab-pane" ng-repeat="id in [1,2,3]" title="Tab {{id}}" value="tab-{{id}}">' +
|
||||
'Tab content {{id}}!' +
|
||||
'</div>' +
|
||||
'</div>')($rootScope);
|
||||
$rootScope.$apply();
|
||||
|
||||
expect(element).toHaveSelected(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,91 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<script src="../../src/angular-bootstrap.js"></script>
|
||||
<script type="text/javascript">
|
||||
$script('src/bootstrap/google-prettify/prettify', 'prettify');
|
||||
$script.ready('angular', function() {
|
||||
$script(['src/bootstrap/bootstrap-prettify', 'src/bootstrap/bootstrap'], 'myCode');
|
||||
angular.module('myApp', []).run(function($rootScope){ $rootScope.text = 'WORKS!' });
|
||||
});
|
||||
$script.ready(['myCode', 'prettify'], function() {
|
||||
angular.bootstrap(document, ['bootstrapPrettify', 'bootstrap']);
|
||||
});
|
||||
</script>
|
||||
<link rel="stylesheet" href="../../src/bootstrap/google-prettify/prettify.css" type="text/css">
|
||||
<link rel="stylesheet" href="../../src/bootstrap/css/bootstrap.css" type="text/css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="span12">
|
||||
<h1>AngularJS is {{'working'}}</h1>
|
||||
|
||||
<h2>Directive: <code>prettify</code></h2>
|
||||
<pre class="prettyprint linenums">
|
||||
<p>Sample text here...</p>
|
||||
</pre>
|
||||
|
||||
|
||||
<h2>Directive: <code>ng-set-text</code></h2>
|
||||
<pre class="prettyprint linenums" ng-set-text="hello.html"></pre>
|
||||
<script type="text/html" id="hello.html">
|
||||
<h1>Hello World!</h1>
|
||||
</script>
|
||||
|
||||
<h2>Directive: <code>ng-html-wrap</code></h2>
|
||||
<pre class="prettyprint linenums" ng-set-text="hello.html" ng-html-wrap="angular.js angular-resource.js myApp abc.js abc.css"></pre>
|
||||
|
||||
<h2>Directive <code>ng-embed-app</code></h2>
|
||||
<div ng-embed-app="myApp">{{text}}</div>
|
||||
|
||||
<h1>Bootstrap</h1>
|
||||
|
||||
<h2>Directive <code>drop-down-toggle</code></h2>
|
||||
<div class="btn btn-primary dropdown">
|
||||
<a href="#ABC" class="dropdown-toggle">
|
||||
Account
|
||||
<b class="caret"></b>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li>One</li>
|
||||
<li>Two</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<h2 ng-init="state = 'tab-2' ">Directive <code>tabbable</code></h2>
|
||||
state = {{state}}
|
||||
|
||||
<div class="tabbable" ng-model="state">
|
||||
<div class="tab-pane" ng-repeat="id in [1,2,3]" title="Tab {{id}}" value='tab-{{id}}'>
|
||||
Tab content {{id}}!
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
<div class="tabbable" ng-model="state">
|
||||
<div class="tab-pane" ng-repeat="id in [1,2,3]" title="Tab {{id}}" value='tab-{{id}}'>
|
||||
Tab content {{id}}!
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
<div class="tabbable">
|
||||
<div class="tab-pane" ng-repeat="id in [1,2,3]" title="Tab {{id}}" value='tab-{{id}}'>
|
||||
Tab content {{id}}!
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br/>
|
||||
<br/>
|
||||
<br/>
|
||||
<br/>
|
||||
<br/>
|
||||
<br/>
|
||||
</body>
|
||||
</html>
|
||||
@@ -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');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
@@ -1,227 +0,0 @@
|
||||
|
||||
/*!
|
||||
* $script.js Async loader & dependency manager
|
||||
* https://github.com/ded/script.js
|
||||
* (c) Dustin Diaz, Jacob Thornton 2011
|
||||
* License: MIT
|
||||
*/
|
||||
(function (name, definition, context) {
|
||||
if (typeof context['module'] != 'undefined' && context['module']['exports']) context['module']['exports'] = definition()
|
||||
else if (typeof context['define'] != 'undefined' && context['define'] == 'function' && context['define']['amd']) define(name, definition)
|
||||
else context[name] = definition()
|
||||
})('$script', function () {
|
||||
var doc = document
|
||||
, head = doc.getElementsByTagName('head')[0]
|
||||
, validBase = /^https?:\/\//
|
||||
, list = {}, ids = {}, delay = {}, scriptpath
|
||||
, scripts = {}, s = 'string', f = false
|
||||
, push = 'push', domContentLoaded = 'DOMContentLoaded', readyState = 'readyState'
|
||||
, addEventListener = 'addEventListener', onreadystatechange = 'onreadystatechange'
|
||||
|
||||
function every(ar, fn) {
|
||||
for (var i = 0, j = ar.length; i < j; ++i) if (!fn(ar[i])) return f
|
||||
return 1
|
||||
}
|
||||
function each(ar, fn) {
|
||||
every(ar, function(el) {
|
||||
return !fn(el)
|
||||
})
|
||||
}
|
||||
|
||||
if (!doc[readyState] && doc[addEventListener]) {
|
||||
doc[addEventListener](domContentLoaded, function fn() {
|
||||
doc.removeEventListener(domContentLoaded, fn, f)
|
||||
doc[readyState] = 'complete'
|
||||
}, f)
|
||||
doc[readyState] = 'loading'
|
||||
}
|
||||
|
||||
function $script(paths, idOrDone, optDone) {
|
||||
paths = paths[push] ? paths : [paths]
|
||||
var idOrDoneIsDone = idOrDone && idOrDone.call
|
||||
, done = idOrDoneIsDone ? idOrDone : optDone
|
||||
, id = idOrDoneIsDone ? paths.join('') : idOrDone
|
||||
, queue = paths.length
|
||||
function loopFn(item) {
|
||||
return item.call ? item() : list[item]
|
||||
}
|
||||
function callback() {
|
||||
if (!--queue) {
|
||||
list[id] = 1
|
||||
done && done()
|
||||
for (var dset in delay) {
|
||||
every(dset.split('|'), loopFn) && !each(delay[dset], loopFn) && (delay[dset] = [])
|
||||
}
|
||||
}
|
||||
}
|
||||
setTimeout(function () {
|
||||
each(paths, function (path) {
|
||||
if (scripts[path]) {
|
||||
id && (ids[id] = 1)
|
||||
return scripts[path] == 2 && callback()
|
||||
}
|
||||
scripts[path] = 1
|
||||
id && (ids[id] = 1)
|
||||
create(!validBase.test(path) && scriptpath ? scriptpath + path + '.js' : path, callback)
|
||||
})
|
||||
}, 0)
|
||||
return $script
|
||||
}
|
||||
|
||||
function create(path, fn) {
|
||||
var el = doc.createElement('script')
|
||||
, loaded = f
|
||||
el.onload = el.onerror = el[onreadystatechange] = function () {
|
||||
if ((el[readyState] && !(/^c|loade/.test(el[readyState]))) || loaded) return;
|
||||
el.onload = el[onreadystatechange] = null
|
||||
loaded = 1
|
||||
scripts[path] = 2
|
||||
fn()
|
||||
}
|
||||
el.async = 1
|
||||
el.src = path
|
||||
head.insertBefore(el, head.firstChild)
|
||||
}
|
||||
|
||||
$script.get = create
|
||||
|
||||
$script.order = function (scripts, id, done) {
|
||||
(function callback(s) {
|
||||
s = scripts.shift()
|
||||
if (!scripts.length) $script(s, id, done)
|
||||
else $script(s, callback)
|
||||
}())
|
||||
}
|
||||
|
||||
$script.path = function (p) {
|
||||
scriptpath = p
|
||||
}
|
||||
$script.ready = function (deps, ready, req) {
|
||||
deps = deps[push] ? deps : [deps]
|
||||
var missing = [];
|
||||
!each(deps, function (dep) {
|
||||
list[dep] || missing[push](dep);
|
||||
}) && every(deps, function (dep) {return list[dep]}) ?
|
||||
ready() : !function (key) {
|
||||
delay[key] = delay[key] || []
|
||||
delay[key][push](ready)
|
||||
req && req(missing)
|
||||
}(deps.join('|'))
|
||||
return $script
|
||||
}
|
||||
return $script
|
||||
}, this);
|
||||
|
||||
|
||||
/**
|
||||
* @license AngularJS
|
||||
* (c) 2010-2012 Google, Inc. http://angularjs.org
|
||||
* License: MIT
|
||||
*/
|
||||
(function(window, document) {
|
||||
|
||||
var filename = /^(.*\/)angular-bootstrap.js(#.*)?$/,
|
||||
scripts = document.getElementsByTagName("SCRIPT"),
|
||||
serverPath,
|
||||
match,
|
||||
globalVars = {},
|
||||
IGNORE = {
|
||||
innerHeight: true, innerWidth: true,
|
||||
onkeyup: true, onkeydown: true, onresize: true,
|
||||
event: true, frames: true, external: true,
|
||||
sessionStorage: true, clipboardData: true, localStorage: true};
|
||||
|
||||
for(var j = 0; j < scripts.length; j++) {
|
||||
match = (scripts[j].src || "").match(filename);
|
||||
if (match) {
|
||||
serverPath = match[1];
|
||||
}
|
||||
}
|
||||
|
||||
document.write('<link rel="stylesheet" type="text/css" href="' + serverPath + '../css/angular.css"/>');
|
||||
|
||||
$script.path(serverPath+'../');
|
||||
$script('angularFiles', function() {
|
||||
var index = 0,
|
||||
scripts = angularFiles.angularSrc;
|
||||
|
||||
try { delete window.angularFiles; } catch(e) { window.angularFiles = undefined; }
|
||||
// initialize the window property cache
|
||||
for (var prop in window) {
|
||||
if (IGNORE[prop] || prop.match(/^moz[A-Z]/)) { //skip special variables which keep on changing
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
globalVars[key(prop)] = window[prop];
|
||||
} catch(e) {} //ignore properties that throw exception when accessed (common in FF)
|
||||
}
|
||||
|
||||
(function next() {
|
||||
if (index < scripts.length) {
|
||||
var file = scripts[index++],
|
||||
last = index == scripts.length,
|
||||
name = last ? 'angular' : file;
|
||||
|
||||
$script(file.replace(/\.js$/, ''), name, function() {
|
||||
angularClobberTest(file);
|
||||
next();
|
||||
});
|
||||
} else {
|
||||
// empty the cache to prevent mem leaks
|
||||
globalVars = {};
|
||||
|
||||
bindJQuery();
|
||||
publishExternalAPI(window.angular);
|
||||
|
||||
angularInit(document, angular.bootstrap);
|
||||
}
|
||||
})();
|
||||
});
|
||||
|
||||
function key(prop) {
|
||||
return "ng-clobber_" + prop;
|
||||
}
|
||||
|
||||
function angularClobberTest(file) {
|
||||
var varKey, prop,
|
||||
clobbered = {};
|
||||
|
||||
for (prop in window) {
|
||||
varKey = key(prop);
|
||||
|
||||
if (IGNORE[prop] || prop.match(/^moz[A-Z]/)) { //skip special variables which keep on changing
|
||||
continue;
|
||||
} else if (!globalVars.hasOwnProperty(varKey)) {
|
||||
//console.log('new global variable found: ', prop);
|
||||
try {
|
||||
globalVars[varKey] = window[prop];
|
||||
} catch(e) {} //ignore properties that throw exception when accessed (common in FF)
|
||||
} else if (globalVars[varKey] !== window[prop] && !isActuallyNaN(window[prop]) && prop != 'jqLite') {
|
||||
clobbered[prop] = true;
|
||||
console.error("Global variable clobbered by script " + file + "! Variable name: " + prop);
|
||||
globalVars[varKey] = window[prop];
|
||||
}
|
||||
}
|
||||
for (varKey in globalVars) {
|
||||
prop = varKey.substr(11);
|
||||
if (prop === 'event' || prop.match(/^moz[A-Z]/)) { //skip special variables which keep on changing
|
||||
continue;
|
||||
}
|
||||
if (!clobbered[prop] &&
|
||||
prop != 'event' &&
|
||||
prop != 'jqLite' &&
|
||||
!isActuallyNaN(globalVars[varKey]) &&
|
||||
globalVars[varKey] !== window[prop]) {
|
||||
|
||||
delete globalVars[varKey];
|
||||
console.warn("Global variable unexpectedly deleted in script " + file + "! " +
|
||||
"Variable name: " + prop);
|
||||
}
|
||||
}
|
||||
|
||||
function isActuallyNaN(val) {
|
||||
return (typeof val === 'number') && isNaN(val);
|
||||
}
|
||||
}
|
||||
})(window, document);
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
var _ = require('lodash');
|
||||
var path = require('canonical-path');
|
||||
var packagePath = __dirname;
|
||||
|
||||
var basePackage = require('dgeni-packages/ngdoc');
|
||||
var examplesPackage = require('dgeni-packages/examples');
|
||||
|
||||
module.exports = function(config) {
|
||||
|
||||
config = basePackage(config);
|
||||
config = examplesPackage(config);
|
||||
|
||||
config.append('processing.processors', [
|
||||
require('./processors/git-data'),
|
||||
require('./processors/error-docs'),
|
||||
require('./processors/keywords'),
|
||||
require('./processors/versions-data'),
|
||||
require('./processors/pages-data'),
|
||||
require('./processors/protractor-generate'),
|
||||
require('./processors/index-page'),
|
||||
require('./processors/debug-dump')
|
||||
]);
|
||||
|
||||
config.append('processing.tagDefinitions', [
|
||||
require('./tag-defs/tutorial-step')
|
||||
]);
|
||||
|
||||
config.append('processing.inlineTagDefinitions', [
|
||||
require('./inline-tag-defs/type')
|
||||
]);
|
||||
|
||||
config.set('processing.search.ignoreWordsFile', path.resolve(packagePath, 'ignore.words'));
|
||||
|
||||
config.prepend('rendering.templateFolders', [
|
||||
path.resolve(packagePath, 'templates')
|
||||
]);
|
||||
|
||||
return config;
|
||||
};
|
||||
@@ -0,0 +1,12 @@
|
||||
var typeClassFilter = require('dgeni-packages/ngdoc/rendering/filters/type-class');
|
||||
var encoder = new require('node-html-encoder').Encoder();
|
||||
|
||||
module.exports = {
|
||||
name: 'type',
|
||||
description: 'Replace with markup that displays a nice type',
|
||||
handlerFactory: function() {
|
||||
return function(doc, tagName, tagDescription) {
|
||||
return '<a href="" class="' + typeClassFilter.process(tagDescription) + '">'+encoder.htmlEncode(tagDescription) + '</a>';
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,26 @@
|
||||
var writer = require('dgeni/lib/utils/doc-writer');
|
||||
var log = require('winston');
|
||||
var util = require("util");
|
||||
|
||||
var filter, outputPath, depth;
|
||||
|
||||
module.exports = {
|
||||
name: 'debug-dump',
|
||||
runBefore: ['write-files'],
|
||||
description: 'This processor dumps docs that match a filter to a file',
|
||||
init: function(config, injectables) {
|
||||
filter = config.get('processing.debug-dump.filter');
|
||||
outputPath = config.get('processing.debug-dump.outputPath');
|
||||
depth = config.get('processing.debug-dump.depth', 2);
|
||||
},
|
||||
process: function(docs) {
|
||||
if ( filter && outputPath ) {
|
||||
log.info('Dumping docs:', filter, outputPath);
|
||||
var filteredDocs = filter(docs);
|
||||
var dumpedDocs = util.inspect(filteredDocs, depth);
|
||||
return writer.writeFile(outputPath, dumpedDocs).then(function() {
|
||||
return docs;
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,57 @@
|
||||
var _ = require('lodash');
|
||||
var log = require('winston');
|
||||
var path = require('canonical-path');
|
||||
|
||||
module.exports = {
|
||||
name: 'error-docs',
|
||||
description: 'Compute the various fields for docs in the Error area',
|
||||
runAfter: ['tags-extracted'],
|
||||
init: function(config, injectables) {
|
||||
injectables.value('errorNamespaces', {});
|
||||
|
||||
var minerrInfoPath = config.get('processing.errors.minerrInfoPath');
|
||||
if ( !minerrInfoPath ) {
|
||||
throw new Error('Error in configuration: Please provide a path to the minerr info file (errors.json) ' +
|
||||
'in the `config.processing.errors.minerrInfoPath` property');
|
||||
}
|
||||
injectables.value('minerrInfo', require(minerrInfoPath));
|
||||
},
|
||||
process: function(docs, partialNames, errorNamespaces, minerrInfo) {
|
||||
|
||||
// Create error namespace docs and attach error docs to each
|
||||
_.forEach(docs, function(doc) {
|
||||
if ( doc.docType === 'error' ) {
|
||||
|
||||
// Parse out the error info from the id
|
||||
parts = doc.name.split(':');
|
||||
doc.namespace = parts[0];
|
||||
doc.name = parts[1];
|
||||
|
||||
|
||||
var namespaceDoc = errorNamespaces[doc.namespace];
|
||||
if ( !namespaceDoc ) {
|
||||
// First time we came across this namespace, so create a new one
|
||||
namespaceDoc = errorNamespaces[doc.namespace] = {
|
||||
area: doc.area,
|
||||
name: doc.namespace,
|
||||
errors: [],
|
||||
path: path.dirname(doc.path),
|
||||
outputPath: path.dirname(doc.outputPath) + '.html',
|
||||
docType: 'errorNamespace'
|
||||
};
|
||||
}
|
||||
|
||||
// Add this error to the namespace
|
||||
namespaceDoc.errors.push(doc);
|
||||
doc.namespace = namespaceDoc;
|
||||
|
||||
doc.formattedErrorMessage = minerrInfo.errors[doc.namespace.name][doc.name];
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
return docs.concat(_.values(errorNamespaces));
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,18 @@
|
||||
var gruntUtils = require('../../../lib/grunt/utils');
|
||||
var versionInfo = require('../../../lib/versions/version-info');
|
||||
|
||||
module.exports = {
|
||||
name: 'git-data',
|
||||
runBefore: ['loading-files'],
|
||||
description: 'This processor adds information from the local git repository to the extraData injectable',
|
||||
init: function(config, injectables) {
|
||||
injectables.value('gitData', {
|
||||
version: versionInfo.currentVersion,
|
||||
versions: versionInfo.previousVersions,
|
||||
info: versionInfo.gitRepoInfo
|
||||
});
|
||||
},
|
||||
process: function(extraData, gitData) {
|
||||
extraData.git = gitData;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,42 @@
|
||||
var _ = require('lodash');
|
||||
var log = require('winston');
|
||||
var path = require('canonical-path');
|
||||
var deployment;
|
||||
|
||||
module.exports = {
|
||||
name: 'index-page',
|
||||
runAfter: ['adding-extra-docs'],
|
||||
runBefore: ['extra-docs-added'],
|
||||
description: 'This processor creates docs that will be rendered as the index page for the app',
|
||||
init: function(config) {
|
||||
deployment = config.deployment;
|
||||
if ( !deployment || !deployment.environments ) {
|
||||
throw new Error('No deployment environments found in the config.');
|
||||
}
|
||||
},
|
||||
process: function(docs) {
|
||||
|
||||
// Collect up all the areas in the docs
|
||||
var areas = {};
|
||||
_.forEach(docs, function(doc) {
|
||||
if ( doc.area ) {
|
||||
areas[doc.area] = doc.area;
|
||||
}
|
||||
});
|
||||
areas = _.keys(areas);
|
||||
|
||||
_.forEach(deployment.environments, function(environment) {
|
||||
|
||||
var indexDoc = _.defaults({
|
||||
docType: 'indexPage',
|
||||
areas: areas
|
||||
}, environment);
|
||||
|
||||
indexDoc.id = 'index' + (environment.name === 'default' ? '' : '-' + environment.name);
|
||||
// Use .. to put it at the root of the build
|
||||
indexDoc.outputPath = indexDoc.id + '.html';
|
||||
|
||||
docs.push(indexDoc);
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,91 @@
|
||||
var _ = require('lodash');
|
||||
var log = require('winston');
|
||||
var fs = require('fs');
|
||||
var path = require('canonical-path');
|
||||
|
||||
// Keywords to ignore
|
||||
var wordsToIgnore = [];
|
||||
var propertiesToIgnore;
|
||||
var areasToSearch;
|
||||
|
||||
// Keywords start with "ng:" or one of $, _ or a letter
|
||||
var KEYWORD_REGEX = /^((ng:|[\$_a-z])[\w\-_]+)/;
|
||||
|
||||
module.exports = {
|
||||
name: 'keywords',
|
||||
runAfter: ['docs-processed'],
|
||||
runBefore: ['adding-extra-docs'],
|
||||
description: 'This processor extracts all the keywords from the document',
|
||||
init: function(config) {
|
||||
|
||||
// Load up the keywords to ignore, if specified in the config
|
||||
if ( config.processing.search && config.processing.search.ignoreWordsFile ) {
|
||||
|
||||
var ignoreWordsPath = path.resolve(config.basePath, config.processing.search.ignoreWordsFile);
|
||||
wordsToIgnore = fs.readFileSync(ignoreWordsPath, 'utf8').toString().split(/[,\s\n\r]+/gm);
|
||||
|
||||
log.debug('Loaded ignore words from "' + ignoreWordsPath + '"');
|
||||
log.silly(wordsToIgnore);
|
||||
|
||||
}
|
||||
|
||||
areasToSearch = _.indexBy(config.get('processing.search.areasToSearch', ['api', 'guide', 'misc', 'error', 'tutorial']));
|
||||
|
||||
propertiesToIgnore = _.indexBy(config.get('processing.search.propertiesToIgnore', []));
|
||||
log.debug('Properties to ignore', propertiesToIgnore);
|
||||
|
||||
},
|
||||
process: function(docs) {
|
||||
|
||||
var ignoreWordsMap = _.indexBy(wordsToIgnore);
|
||||
|
||||
// If the title contains a name starting with ng, e.g. "ngController", then add the module name
|
||||
// without the ng to the title text, e.g. "controller".
|
||||
function extractTitleWords(title) {
|
||||
var match = /ng([A-Z]\w*)/.exec(title);
|
||||
if ( match ) {
|
||||
title = title + ' ' + match[1].toLowerCase();
|
||||
}
|
||||
return title;
|
||||
}
|
||||
|
||||
function extractWords(text, words, keywordMap) {
|
||||
|
||||
var tokens = text.toLowerCase().split(/[\.\s,`'"#]+/mg);
|
||||
_.forEach(tokens, function(token){
|
||||
var match = token.match(KEYWORD_REGEX);
|
||||
if (match){
|
||||
key = match[1];
|
||||
if ( !keywordMap[key]) {
|
||||
keywordMap[key] = true;
|
||||
words.push(key);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// We are only interested in docs that live in the right area
|
||||
docs = _.filter(docs, function(doc) { return areasToSearch[doc.area]; });
|
||||
|
||||
_.forEach(docs, function(doc) {
|
||||
|
||||
var words = [];
|
||||
var keywordMap = _.clone(ignoreWordsMap);
|
||||
|
||||
// Search each top level property of the document for search terms
|
||||
_.forEach(doc, function(value, key) {
|
||||
if ( _.isString(value) && !propertiesToIgnore[key] ) {
|
||||
extractWords(value, words, keywordMap);
|
||||
}
|
||||
});
|
||||
|
||||
doc.searchTerms = {
|
||||
titleWords: extractTitleWords(doc.name),
|
||||
keywords: _.sortBy(words).join(' ')
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,217 @@
|
||||
var _ = require('lodash');
|
||||
var path = require('canonical-path');
|
||||
var log = require('winston');
|
||||
|
||||
var AREA_NAMES = {
|
||||
api: 'API',
|
||||
guide: 'Developer Guide',
|
||||
misc: 'Miscellaneous',
|
||||
tutorial: 'Tutorial',
|
||||
error: 'Error Reference'
|
||||
};
|
||||
|
||||
function getNavGroup(pages, area, pageSorter, pageMapper) {
|
||||
|
||||
var navItems = _(pages)
|
||||
// We don't want the child to include the index page as this is already catered for
|
||||
.omit(function(page) { return page.id === 'index'; })
|
||||
|
||||
// Apply the supplied sorting function
|
||||
.sortBy(pageSorter)
|
||||
|
||||
// Apply the supplied mapping function
|
||||
.map(pageMapper)
|
||||
|
||||
.value();
|
||||
|
||||
return {
|
||||
name: area.name,
|
||||
type: 'group',
|
||||
href: area.id,
|
||||
navItems: navItems
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
var navGroupMappers = {
|
||||
api: function(areaPages, area) {
|
||||
var navGroups = _(areaPages)
|
||||
.filter('module') // We are not interested in docs that are not in a module
|
||||
|
||||
.groupBy('module')
|
||||
|
||||
.map(function(modulePages, moduleName) {
|
||||
log.debug('moduleName: ' + moduleName);
|
||||
var navItems = [];
|
||||
var modulePage;
|
||||
|
||||
_(modulePages)
|
||||
|
||||
.groupBy('docType')
|
||||
|
||||
.tap(function(docTypes) {
|
||||
log.debug(_.keys(docTypes));
|
||||
// Extract the module page from the collection
|
||||
modulePage = docTypes.module[0];
|
||||
delete docTypes.module;
|
||||
})
|
||||
|
||||
.tap(function(docTypes) {
|
||||
if ( docTypes.input ) {
|
||||
docTypes.directive = docTypes.directive || [];
|
||||
// Combine input docTypes into directive docTypes
|
||||
docTypes.directive = docTypes.directive.concat(docTypes.input);
|
||||
delete docTypes.input;
|
||||
}
|
||||
})
|
||||
|
||||
.forEach(function(sectionPages, sectionName) {
|
||||
|
||||
sectionPages = _.sortBy(sectionPages, 'name');
|
||||
|
||||
if ( sectionPages.length > 0 ) {
|
||||
// Push a navItem for this section
|
||||
navItems.push({
|
||||
name: sectionName,
|
||||
type: 'section',
|
||||
href: path.dirname(sectionPages[0].path)
|
||||
});
|
||||
|
||||
// Push the rest of the sectionPages for this section
|
||||
_.forEach(sectionPages, function(sectionPage) {
|
||||
|
||||
navItems.push({
|
||||
name: sectionPage.name,
|
||||
href: sectionPage.path,
|
||||
type: sectionPage.docType
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
});
|
||||
return {
|
||||
name: moduleName,
|
||||
href: modulePage.path,
|
||||
type: 'group',
|
||||
navItems: navItems
|
||||
};
|
||||
})
|
||||
.value();
|
||||
return navGroups;
|
||||
},
|
||||
tutorial: function(pages, area) {
|
||||
return [getNavGroup(pages, area, 'step', function(page) {
|
||||
return {
|
||||
name: page.name,
|
||||
step: page.step,
|
||||
href: page.path,
|
||||
type: 'tutorial'
|
||||
};
|
||||
})];
|
||||
},
|
||||
error: function(pages, area) {
|
||||
return [getNavGroup(pages, area, 'path', function(page) {
|
||||
return {
|
||||
name: page.name,
|
||||
href: page.path,
|
||||
type: page.docType === 'errorNamespace' ? 'section' : 'error'
|
||||
};
|
||||
})];
|
||||
},
|
||||
pages: function(pages, area) {
|
||||
return [getNavGroup(pages, area, 'path', function(page) {
|
||||
return {
|
||||
name: page.name,
|
||||
href: page.path,
|
||||
type: 'page'
|
||||
};
|
||||
})];
|
||||
}
|
||||
};
|
||||
|
||||
var outputFolder;
|
||||
|
||||
module.exports = {
|
||||
name: 'pages-data',
|
||||
description: 'This plugin will create a new doc that will be rendered as an angularjs module ' +
|
||||
'which will contain meta information about the pages and navigation',
|
||||
runAfter: ['adding-extra-docs', 'component-groups-generate'],
|
||||
runBefore: ['extra-docs-added'],
|
||||
init: function(config) {
|
||||
outputFolder = config.rendering.outputFolder;
|
||||
},
|
||||
process: function(docs) {
|
||||
|
||||
_(docs)
|
||||
.filter(function(doc) { return doc.area === 'api'; })
|
||||
.filter(function(doc) { return doc.docType === 'module'; })
|
||||
.forEach(function(doc) { if ( !doc.path ) {
|
||||
log.warn('Missing path property for ', doc.id);
|
||||
}})
|
||||
.map(function(doc) { return _.pick(doc, ['id', 'module', 'docType', 'area']); })
|
||||
.tap(function(docs) {
|
||||
log.debug(docs);
|
||||
});
|
||||
|
||||
|
||||
// We are only interested in docs that are in a area and not landing pages
|
||||
var navPages = _.filter(docs, function(page) {
|
||||
return page.area &&
|
||||
page.docType != 'componentGroup';
|
||||
});
|
||||
|
||||
// Generate an object collection of pages that is grouped by area e.g.
|
||||
// - area "api"
|
||||
// - group "ng"
|
||||
// - section "directive"
|
||||
// - ngApp
|
||||
// - ngBind
|
||||
// - section "global"
|
||||
// - angular.element
|
||||
// - angular.bootstrap
|
||||
// - section "service"
|
||||
// - $compile
|
||||
// - group "ngRoute"
|
||||
// - section "directive"
|
||||
// - ngView
|
||||
// - section "service"
|
||||
// - $route
|
||||
//
|
||||
var areas = {};
|
||||
_(navPages)
|
||||
.groupBy('area')
|
||||
.forEach(function(pages, areaId) {
|
||||
var area = {
|
||||
id: areaId,
|
||||
name: AREA_NAMES[areaId]
|
||||
};
|
||||
areas[areaId] = area;
|
||||
|
||||
var navGroupMapper = navGroupMappers[area.id] || navGroupMappers['pages'];
|
||||
area.navGroups = navGroupMapper(pages, area);
|
||||
});
|
||||
|
||||
// Extract a list of basic page information for mapping paths to paritals and for client side searching
|
||||
var pages = _(docs)
|
||||
.map(function(doc) {
|
||||
var page = _.pick(doc, [
|
||||
'docType', 'id', 'name', 'area', 'outputPath', 'path', 'searchTerms'
|
||||
]);
|
||||
return page;
|
||||
})
|
||||
.indexBy('path')
|
||||
.value();
|
||||
|
||||
|
||||
var docData = {
|
||||
docType: 'pages-data',
|
||||
id: 'pages-data',
|
||||
template: 'pages-data.template.js',
|
||||
outputPath: 'js/pages-data.js',
|
||||
|
||||
areas: areas,
|
||||
pages: pages
|
||||
};
|
||||
docs.push(docData);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,52 @@
|
||||
var _ = require('lodash');
|
||||
var log = require('winston');
|
||||
var path = require('canonical-path');
|
||||
var trimIndentation = require('dgeni/lib/utils/trim-indentation');
|
||||
var code = require('dgeni/lib/utils/code');
|
||||
var protractorFolder;
|
||||
|
||||
function createProtractorDoc(example, file, env) {
|
||||
var protractorDoc = {
|
||||
docType: 'e2e-test',
|
||||
id: 'protractorTest' + '-' + example.id,
|
||||
template: 'protractorTests.template.js',
|
||||
outputPath: path.join(protractorFolder, example.id, env + '_test.js'),
|
||||
innerTest: file.fileContents,
|
||||
pathPrefix: '.', // Hold for if we test with full jQuery
|
||||
exampleId: example.id,
|
||||
description: example.doc.id
|
||||
};
|
||||
|
||||
if (env === 'jquery') {
|
||||
protractorDoc.examplePath = example.outputFolder + '/index-jquery.html'
|
||||
} else {
|
||||
protractorDoc.examplePath = example.outputFolder + '/index.html'
|
||||
}
|
||||
return protractorDoc;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
name: 'protractor-generate',
|
||||
description: 'Generate a protractor test file from the e2e tests in the examples',
|
||||
runAfter: ['adding-extra-docs'],
|
||||
runBefore: ['extra-docs-added'],
|
||||
init: function(config, injectables) {
|
||||
protractorFolder = config.get('rendering.protractor.outputFolder', 'ptore2e');
|
||||
},
|
||||
process: function(docs, examples) {
|
||||
_.forEach(examples, function(example) {
|
||||
|
||||
_.forEach(example.files, function(file) {
|
||||
|
||||
// Check if it's a Protractor test.
|
||||
if (!(file.type == 'protractor')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create new files for the tests.
|
||||
docs.push(createProtractorDoc(example, file, 'jquery'));
|
||||
docs.push(createProtractorDoc(example, file, 'jqlite'));
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,38 @@
|
||||
var _ = require('lodash');
|
||||
|
||||
module.exports = {
|
||||
name: 'versions-data',
|
||||
description: 'This plugin will create a new doc that will be rendered as an angularjs module ' +
|
||||
'which will contain meta information about the versions of angular',
|
||||
runAfter: ['adding-extra-docs', 'pages-data'],
|
||||
runBefore: ['extra-docs-added'],
|
||||
process: function(docs, gitData) {
|
||||
|
||||
var version = gitData.version;
|
||||
var versions = gitData.versions;
|
||||
|
||||
if ( !version ) {
|
||||
throw new Error('Invalid configuration. Please provide a valid `source.currentVersion` property');
|
||||
}
|
||||
if ( !versions ) {
|
||||
throw new Error('Invalid configuration. Please provide a valid `source.previousVersions` property');
|
||||
}
|
||||
|
||||
var versionDoc = {
|
||||
docType: 'versions-data',
|
||||
id: 'versions-data',
|
||||
template: 'versions-data.template.js',
|
||||
outputPath: 'js/versions-data.js',
|
||||
};
|
||||
|
||||
versionDoc.currentVersion = version;
|
||||
|
||||
versionDoc.versions = _(versions)
|
||||
.filter(function(version) { return version.major > 0; })
|
||||
.push(version)
|
||||
.reverse()
|
||||
.value();
|
||||
|
||||
docs.push(versionDoc);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
module.exports = {
|
||||
name: 'step',
|
||||
transformFn: function(doc, tag) {
|
||||
if ( doc.docType !== 'tutorial' ) {
|
||||
throw new Error('Invalid tag, step. You should only use this tag on tutorial docs');
|
||||
}
|
||||
return parseInt(tag.description,10);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,17 @@
|
||||
{% extends "base.template.html" %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Error: {$ doc.id $}
|
||||
<div><span class='hint'>{$ doc.fullName $}</span></div>
|
||||
</h1>
|
||||
|
||||
<div>
|
||||
<pre class="minerr-errmsg" error-display="{$ doc.formattedErrorMessage $}">{$ doc.formattedErrorMessage $}</pre>
|
||||
</div>
|
||||
|
||||
<h2>Description</h2>
|
||||
<div class="description">
|
||||
{$ doc.description | marked $}
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,28 @@
|
||||
{% extends 'base.template.html' %}
|
||||
|
||||
{% block content %}
|
||||
<h1>{$ doc.name $}</h1>
|
||||
|
||||
<div class="description">
|
||||
Here are the list of errors in the {$ doc.name $} namespace.
|
||||
|
||||
</div>
|
||||
|
||||
<div class="component-breakdown">
|
||||
<div>
|
||||
<table class="definition-table">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
{% for errorDoc in doc.errors -%}
|
||||
<tr>
|
||||
<td><a href="{$ errorDoc.path $}">{$ errorDoc.name $}</td>
|
||||
<td>{$ errorDoc.fullName $}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,249 @@
|
||||
<!doctype html>
|
||||
<html lang="en" ng-app="docsApp" ng-controller="DocsController">
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="Description"
|
||||
content="AngularJS is what HTML would have been, had it been designed for building web-apps.
|
||||
Declarative templates with data-binding, MVC, dependency injection and great
|
||||
testability story all implemented with pure client-side JavaScript!">
|
||||
<meta name="fragment" content="!">
|
||||
<title ng-bind-template="AngularJS: {{ currentArea.name }}: {{ currentPage.name || 'Error: Page not found'}}">AngularJS</title>
|
||||
|
||||
<script type="text/javascript">
|
||||
// dynamically add base tag as well as css and javascript files.
|
||||
// we can't add css/js the usual way, because some browsers (FF) eagerly prefetch resources
|
||||
// before the base attribute is added, causing 404 and terribly slow loading of the docs app.
|
||||
(function() {
|
||||
var indexFile = (location.pathname.match(/\/(index[^\.]*\.html)/) || ['', ''])[1],
|
||||
rUrl = /(#!\/|api|guide|misc|tutorial|error|index[^\.]*\.html).*$/,
|
||||
baseUrl = location.href.replace(rUrl, indexFile),
|
||||
production = location.hostname === 'docs.angularjs.org',
|
||||
headEl = document.getElementsByTagName('head')[0],
|
||||
sync = true;
|
||||
|
||||
addTag('base', {href: baseUrl});
|
||||
|
||||
|
||||
{% for stylesheet in doc.stylesheets %}addTag('link', {rel: 'stylesheet', href: '{$ stylesheet $}', type: 'text/css'});
|
||||
{% endfor %}
|
||||
|
||||
{% for script in doc.scripts %}addTag('script', {src: '{$ script $}' }, sync);
|
||||
{% endfor %}
|
||||
|
||||
function addTag(name, attributes, sync) {
|
||||
var el = document.createElement(name),
|
||||
attrName;
|
||||
|
||||
for (attrName in attributes) {
|
||||
el.setAttribute(attrName, attributes[attrName]);
|
||||
}
|
||||
|
||||
sync ? document.write(outerHTML(el)) : headEl.appendChild(el);
|
||||
}
|
||||
|
||||
function outerHTML(node){
|
||||
// if IE, Chrome take the internal method otherwise build one
|
||||
return node.outerHTML || (
|
||||
function(n){
|
||||
var div = document.createElement('div'), h;
|
||||
div.appendChild(n);
|
||||
h = div.innerHTML;
|
||||
div = null;
|
||||
return h;
|
||||
})(node);
|
||||
}
|
||||
})();
|
||||
|
||||
|
||||
// force page reload when new update is available
|
||||
window.applicationCache && window.applicationCache.addEventListener('updateready', function(e) {
|
||||
if (window.applicationCache.status == window.applicationCache.UPDATEREADY) {
|
||||
window.applicationCache.swapCache();
|
||||
window.location.reload();
|
||||
}
|
||||
}, false);
|
||||
|
||||
// GA asynchronous tracker
|
||||
var _gaq = _gaq || [];
|
||||
_gaq.push(['_setAccount', 'UA-8594346-3']);
|
||||
_gaq.push(['_setDomainName', '.angularjs.org']);
|
||||
|
||||
(function() {
|
||||
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
||||
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
||||
})();
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="wrapper">
|
||||
<header class="header header-fixed">
|
||||
<section class="navbar navbar-inverse docs-navbar-primary" ng-controller="DocsSearchCtrl">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-9 header-branding">
|
||||
<a class="brand navbar-brand" href="http://angularjs.org">
|
||||
<img class="logo" src="img/angularjs-for-header-only.svg">
|
||||
</a>
|
||||
<ul class="nav navbar-nav">
|
||||
<li class="divider-vertical"></li>
|
||||
<li><a href="http://angularjs.org"><i class="icon-home icon-white"></i> Home</a></li>
|
||||
<li class="divider-vertical"></li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
||||
<i class="icon-eye-open icon-white"></i> Learn <b class="caret"></b>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li class="disabled"><a href="http://angularjs.org/">Why AngularJS?</a></li>
|
||||
<li><a href="http://www.youtube.com/user/angularjs">Watch</a></li>
|
||||
<li><a href="tutorial">Tutorial</a></li>
|
||||
<li><a href="http://builtwith.angularjs.org/">Case Studies</a></li>
|
||||
<li><a href="https://github.com/angular/angular-seed">Seed App project template</a></li>
|
||||
<li><a href="misc/faq">FAQ</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="divider-vertical"></li>
|
||||
<li class="dropdown active">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
||||
<i class="icon-book icon-white"></i> Develop <b class="caret"></b>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="tutorial">Tutorial</a></li>
|
||||
<li><a href="guide">Developer Guide</a></li>
|
||||
<li><a href="api">API Reference</a></li>
|
||||
<li><a href="error">Error Reference</a></li>
|
||||
<li><a href="misc/contribute">Contribute</a></li>
|
||||
<li><a href="http://code.angularjs.org/">Download</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="divider-vertical"></li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
||||
<i class="icon-comment icon-white"></i> Discuss <b class="caret"></b>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="http://blog.angularjs.org">Blog</a></li>
|
||||
<li><a href="http://groups.google.com/group/angular">Mailing List</a></li>
|
||||
<li><a href="http://webchat.freenode.net/?channels=angularjs&uio=d4">Chat Room</a></li>
|
||||
<li class="divider"></li>
|
||||
<li><a href="https://twitter.com/#!/angularjs">Twitter</a></li>
|
||||
<li><a href="https://plus.google.com/110323587230527980117">Google+</a></li>
|
||||
<li class="divider"></li>
|
||||
<li><a href="https://github.com/angular/angular.js">GitHub</a></li>
|
||||
<li><a href="https://github.com/angular/angular.js/issues">Issue Tracker</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="divider-vertical"></li>
|
||||
</ul>
|
||||
</div>
|
||||
<form ng-class="{focus:focus}" class="navbar-search col-md-3 docs-search" ng-submit="submit()">
|
||||
<span class="glyphicon glyphicon-search search-icon"></span>
|
||||
<input type="text"
|
||||
name="as_q"
|
||||
class="search-query"
|
||||
placeholder="Click or press / to search"
|
||||
ng-focus="focus=true"
|
||||
ng-blur="focus=false"
|
||||
ng-change="search(q)"
|
||||
ng-model="q"
|
||||
docs-search-input
|
||||
autocomplete="off" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="search-results-container" ng-show="hasResults">
|
||||
<div class="container">
|
||||
<a href="" ng-click="hideResults()" class="search-close">
|
||||
<span class="glyphicon glyphicon-remove search-close-icon"></span> Close
|
||||
</a>
|
||||
<div class="search-results-frame">
|
||||
<div ng-repeat="(key, value) in results" class="search-results-group" ng-class="colClassName + ' col-group-' + key">
|
||||
<h4 class="search-results-group-heading">{{ key }}</h4>
|
||||
<div class="search-results">
|
||||
<div ng-repeat="item in value" class="search-result">
|
||||
- <a ng-click="hideResults()" ng-href="{{ item.path }}">{{ item.name }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="sup-header">
|
||||
<div class="container main-grid main-header-grid">
|
||||
<div class="grid-left">
|
||||
<div ng-controller="DocsVersionsCtrl" class="picker version-picker">
|
||||
<select ng-options="v as ('v' + v.version + (v.isSnapshot ? ' (snapshot)' : '')) group by (v.isStable?'Stable':'Unstable') for v in docs_versions"
|
||||
ng-model="docs_version"
|
||||
ng-change="jumpToDocsVersion(docs_version)"
|
||||
class="docs-version-jump">
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid-right">
|
||||
<ul class="nav-breadcrumb">
|
||||
<li ng-repeat="crumb in breadcrumb" class="nav-breadcrumb-entry naked-list">
|
||||
<span class="divider"> /</span>
|
||||
<a ng-href="{{crumb.url}}">{{crumb.name}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</header>
|
||||
|
||||
<section role="main" class="container main-body">
|
||||
<div class="main-grid main-body-grid">
|
||||
<div class="grid-left">
|
||||
<a class="btn toc-toggle visible-xs" ng-click="toc=!toc">Show / Hide Table of Contents</a>
|
||||
<div class="side-navigation" ng-show="toc==true">
|
||||
<ul class="nav-list naked-list">
|
||||
<li ng-repeat="navGroup in currentArea.navGroups track by navGroup.name" class="nav-index-group">
|
||||
<a href="{{ navGroup.href }}" ng-class="navClass(navGroup)" class="nav-index-group-heading">{{ navGroup.name }}</a>
|
||||
<ul class="aside-nav">
|
||||
<li ng-repeat="navItem in navGroup.navItems" ng-class="navClass(navItem)" class="nav-index-listing">
|
||||
<a ng-if="navItem.extra.href" ng-class="navClass(navItem.extra)" href="{{navItem.extra.href}}">
|
||||
{{navItem.extra.text}}<i ng-if="navItem.extra.icon" class="icon-{{navItem.extra.icon}}"></i>
|
||||
</a>
|
||||
<a tabindex="2" ng-class="linkClass(navItem)" href="{{navItem.href}}">{{navItem.name}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<a href="" ng-click="toc=false" class="toc-close visible-xs">
|
||||
<span class="glyphicon glyphicon-remove toc-close-icon"></span> Close
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid-right">
|
||||
<div id="loading" ng-show="loading">Loading...</div>
|
||||
<div ng-hide="loading" ng-include="currentPage.outputPath || 'Error404.html'" onload="afterPartialLoaded()" autoscroll></div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer class="footer">
|
||||
<div class="container">
|
||||
<p class="pull-right"><a back-to-top>Back to top</a></p>
|
||||
|
||||
<p>
|
||||
Super-powered by Google ©2010-2014
|
||||
( <a id="version"
|
||||
ng-href="https://github.com/angular/angular.js/blob/master/CHANGELOG.md#{{versionNumber}}"
|
||||
ng-bind-template="v{{version}}">
|
||||
</a>
|
||||
)
|
||||
</p>
|
||||
<p>
|
||||
Code licensed under the
|
||||
<a href="https://github.com/angular/angular.js/blob/master/LICENSE" target="_blank">The
|
||||
MIT License</a>. Documentation licensed under <a
|
||||
href="http://creativecommons.org/licenses/by/3.0/">CC BY 3.0</a>.
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,4 @@
|
||||
// Meta data used by the AngularJS docs app
|
||||
angular.module('pagesData', [])
|
||||
.value('NG_PAGES', {$ doc.pages | json $})
|
||||
.value('NG_NAVIGATION', {$ doc.areas | json $});
|
||||
@@ -0,0 +1,7 @@
|
||||
describe("{$ doc.description $}", function() {
|
||||
beforeEach(function() {
|
||||
browser.get("{$ doc.pathPrefix $}/{$ doc.examplePath $}");
|
||||
});
|
||||
|
||||
{$ doc.innerTest $}
|
||||
});
|
||||
@@ -0,0 +1,27 @@
|
||||
{# Be aware that we need these extra new lines here or marked will not realise that the <div>
|
||||
is HTML and wrap each line in a <p> - thus breaking the HTML #}
|
||||
|
||||
<div>
|
||||
<a ng-href="http://plnkr.co/edit/ngdoc:{$ doc.example.id $}@{{docsVersion}}?p=preview" class="btn pull-right" target="_blank">
|
||||
<i class="glyphicon glyphicon-edit"> </i>
|
||||
Edit in Plunker</a>
|
||||
<div class="runnable-example"
|
||||
path="{$ doc.example.outputFolder $}"
|
||||
{%- for attrName, attrValue in doc.example.attributes %}
|
||||
{$ attrName $}="{$ attrValue $}"{% endfor %}>
|
||||
|
||||
{% for fileName, file in doc.example.files %}
|
||||
<div class="runnable-example-file" {% for attrName, attrValue in file.attributes %}
|
||||
{$ attrName $}="{$ attrValue $}"{% endfor %}>
|
||||
{% code -%}
|
||||
{$ file.fileContents $}
|
||||
{%- endcode %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
<iframe class="runnable-example-frame" src="{$ doc.example.outputFolder $}/index.html" name="{$ doc.example.id $}"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Be aware that we need these extra new lines here or marked will not realise that the <div>
|
||||
above is HTML and wrap each line in a <p> - thus breaking the HTML #}
|
||||
@@ -0,0 +1 @@
|
||||
{% include 'overview.template.html' %}
|
||||
@@ -0,0 +1,4 @@
|
||||
// Meta data used by the AngularJS docs app
|
||||
angular.module('versionsData', [])
|
||||
.value('NG_VERSION', {$ doc.currentVersion | json $})
|
||||
.value('NG_VERSIONS', {$ doc.versions | json $});
|
||||