Comparar commits
1280 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 87c8f51578 | |||
| 5fa6003361 | |||
| 00004fdd3b | |||
| 68b493732c | |||
| e93677e0c8 | |||
| 8fca9540ab | |||
| 8c2bc34b9c | |||
| ebb8ca233d | |||
| 6ba2efe3a4 | |||
| d5fd737058 | |||
| 93a2e9fc55 | |||
| a7fede4f46 | |||
| 488826ace3 | |||
| 9ee70d6d48 | |||
| 95bd0a54dd | |||
| 2b361e1fee | |||
| 7875b0c68d | |||
| 5c1f242785 | |||
| 3350d5fb13 | |||
| b15b316e85 | |||
| b6d7ceba1c | |||
| be6b254d50 | |||
| 0b56ea452f | |||
| 37da19df78 | |||
| d8347039cf | |||
| f39fa53a7e | |||
| cefaef4707 | |||
| d4b6be5afe | |||
| 798f643fab | |||
| 60a429f5cb | |||
| f6cb3cf0ef | |||
| f3926198d9 | |||
| 79f38b49d8 | |||
| 9a0553a1b5 | |||
| 74fd697351 | |||
| e090691ef7 | |||
| 67bd2dae6d | |||
| 998c6939bf | |||
| 2ab86f5557 | |||
| 21a33f0e41 | |||
| 1157b19626 | |||
| 04f1e57459 | |||
| 1292558f7c | |||
| f09f32f59e | |||
| bf724abe8b | |||
| fffbc27db3 | |||
| e511fc2a1c | |||
| f64324e2a8 | |||
| 4fec7dfdbb | |||
| f5bb8e25d5 | |||
| 81e1448836 | |||
| 56611f550d | |||
| 72b0ef2df0 | |||
| 1fbbdd2d38 | |||
| 136efeaf4d | |||
| 5d2444a5ee | |||
| 9bcc3ca34c | |||
| a16093e51c | |||
| a87ebe0841 | |||
| c3f765857e | |||
| c99cf97ff6 | |||
| 9410eaabbf | |||
| fc46e25f23 | |||
| b69b388b31 | |||
| d5f837843e | |||
| a25c2c740c | |||
| 3d6b47b0d5 | |||
| 156f8f0be8 | |||
| 237d5dca5a | |||
| 185ea3939d | |||
| aba16b402f | |||
| 77971e6b99 | |||
| 8d5b3809f6 | |||
| 33a1fa928d | |||
| 04fe614800 | |||
| 2977c8eb9c | |||
| a4fa956ab4 | |||
| 13fc892114 | |||
| 94cd6a480c | |||
| 595464fc7e | |||
| 5602826aeb | |||
| 0985e6d564 | |||
| 680fa8a68e | |||
| e7233c2f61 | |||
| 72f59264e9 | |||
| 2513d5dd48 | |||
| 14fd5de460 | |||
| 0480f2e18d | |||
| f23b640c81 | |||
| 9d210d8a8c | |||
| c7845d124d | |||
| 428567d8cf | |||
| aa604af05b | |||
| 194c11c3d7 | |||
| cd52936473 | |||
| 48cb104f14 | |||
| a7b16464bf | |||
| 1f8709f88a | |||
| 87633f61e9 | |||
| dae599e16d | |||
| 4729b05cc1 | |||
| 521236bd92 | |||
| 431f930c15 | |||
| 04e6926961 | |||
| 1cc9184c47 | |||
| 96315dd3c9 | |||
| 5fe1914e17 | |||
| b812bcc8a5 | |||
| 6ad533ce2b | |||
| 0f6e329aaa | |||
| cfd3ebb77e | |||
| f5a2e394c8 | |||
| 1bebda87f6 | |||
| 86b9139617 | |||
| f572125820 | |||
| 50d0c98030 | |||
| ee81d4a804 | |||
| ac5be9bde2 | |||
| d31db87115 | |||
| c3149a9400 | |||
| 4c35bba639 | |||
| 2672efad63 | |||
| 309ab1f477 | |||
| 37b3fb5d6c | |||
| e589734cbb | |||
| 01b88f19df | |||
| 756208413b | |||
| a79d365b49 | |||
| 1dc943ddb4 | |||
| db2073139b | |||
| 172839af2c | |||
| 0732793b7e | |||
| 41f2b5707a | |||
| 58fcb37760 | |||
| d366f2b4d3 | |||
| 766b748a58 | |||
| 38b2925e6c | |||
| 489f7ce6f7 | |||
| 3226dfa495 | |||
| a84f9d9177 | |||
| 96551c20db | |||
| f6951816a0 | |||
| d9af94a715 | |||
| eb2b04a9ff | |||
| 2f5e0924ef | |||
| c5020c3e5a | |||
| eb01a0d6f8 | |||
| 999125c521 | |||
| 813d18bd78 | |||
| 007d029837 | |||
| f2780bb825 | |||
| 09783be8a9 | |||
| a3dea119e8 | |||
| 55f9b68b0c | |||
| e9c18f603d | |||
| eb7241cbc9 | |||
| 84ed07a84e | |||
| 7235d829ec | |||
| ee16c1edbc | |||
| 9cf31da4c9 | |||
| e931276003 | |||
| 61ca178e2b | |||
| ada4c8eca3 | |||
| 92bc1a04cf | |||
| 1692b977cd | |||
| 098b05f1b2 | |||
| 85de9fbe9c | |||
| 80ede9b9bb | |||
| 09721407d2 | |||
| 9a20381af4 | |||
| df218ead82 | |||
| ba6afa7257 | |||
| e7df265c7a | |||
| 73300e91c4 | |||
| dfaf786e1a | |||
| 25e787cbf0 | |||
| d16f4fc5ce | |||
| aafe21db7e | |||
| 9ed88599d2 | |||
| 0e8babf1d7 | |||
| 16dc9e6167 | |||
| 172c088c6b | |||
| f75116a91e | |||
| 1afe9f1a6e | |||
| 212b6d3992 | |||
| bfd6f5f78e | |||
| 0890c809aa | |||
| d0a0d57fe2 | |||
| 6aa2933ec5 | |||
| d0b67c603b | |||
| 68ab74a46d | |||
| 0ed39c9fd7 | |||
| c312835eb1 | |||
| 888379ec5c | |||
| 59e3ccb42a | |||
| 76ef7de646 | |||
| cfb06ed34d | |||
| c8ea3af32c | |||
| 3c614a5dfe | |||
| 2d4e2f9889 | |||
| 62988e9768 | |||
| b282a01ab6 | |||
| 8e681a606d | |||
| 33303d8d8a | |||
| 00913be944 | |||
| 1de0435feb | |||
| 2db334dbf6 | |||
| 655c1152eb | |||
| f6b18a5998 | |||
| c42cb148da | |||
| fa7baa1627 | |||
| 19613f531c | |||
| 4f6e86640f | |||
| 25d6c2f064 | |||
| b756507625 | |||
| 24e4a924c4 | |||
| 7735371f45 | |||
| 977d45a3e0 | |||
| 307d02bf48 | |||
| 88fc6ecc5c | |||
| ff94a54891 | |||
| 0ed27d4474 | |||
| 5070059ac1 | |||
| 956b1dd1e0 | |||
| 8c68f78ec3 | |||
| 1202c03535 | |||
| 6b28790223 | |||
| 46861c9f0b | |||
| d49b5b82c7 | |||
| 0e393a3122 | |||
| 8cfa60c04d | |||
| 46ca099265 | |||
| 203bbcec6c | |||
| 6f0d32fa8c | |||
| fe57c8728e | |||
| ebf695734c | |||
| f00517643e | |||
| 84a6eb4a3b | |||
| 6478f93ded | |||
| 1967bef9f6 | |||
| 310eada01a | |||
| 1e91cf816b | |||
| cd29ede572 | |||
| ae19cfd35f | |||
| 8dca052a16 | |||
| 579e322809 | |||
| 8487375730 | |||
| 2caff1f4fa | |||
| 4ac60956db | |||
| 97cc714c94 | |||
| a9a003c4c4 | |||
| f7c6ca544b | |||
| ac9fe08068 | |||
| d9cc1219ce | |||
| 824f5880fb | |||
| cea6934258 | |||
| d6a27d8eb3 | |||
| 081cf7ba07 | |||
| 0c534e1eb8 | |||
| 754268890b | |||
| f2899934db | |||
| 5a5d698b11 | |||
| e2206ab269 | |||
| ff11975648 | |||
| 421e610150 | |||
| 94a8c9a27f | |||
| a0c359ee80 | |||
| 31721a353c | |||
| bbc6f5aa5f | |||
| 968a11a631 | |||
| a1940caf91 | |||
| d9e1b2250e | |||
| ad67d1ecf8 | |||
| 2c178a5670 | |||
| f170fd1b8d | |||
| a423542775 | |||
| d5727d7bc0 | |||
| 1221d8311a | |||
| eb61f5c3fc | |||
| fd668086b2 | |||
| 8e7162ca91 | |||
| 923378e2af | |||
| 0437968a4e | |||
| d134394a1d | |||
| cd02434943 | |||
| c078ae15f0 | |||
| 86ca455cb6 | |||
| 477fc72693 | |||
| d7643bf865 | |||
| d26ab24e3c | |||
| fc3a3aedaf | |||
| 3577d959d0 | |||
| 63b14dc2a9 | |||
| 888a8dd797 | |||
| 7363c6fcbe | |||
| dec4a5f57a | |||
| d163122536 | |||
| bafd36b5ec | |||
| ae643d3d76 | |||
| 5f4e8a4c13 | |||
| 29770d3e67 | |||
| 421e294e2c | |||
| 23b2d991f7 | |||
| d295e49907 | |||
| d9363d637a | |||
| f7d3ea3841 | |||
| 283f1d7387 | |||
| c8d3831152 | |||
| 9aee15fe6c | |||
| 8efa577ef5 | |||
| 3ccf3fd249 | |||
| cddfba1676 | |||
| 274897fc24 | |||
| f51d7753bd | |||
| 3e3912973c | |||
| 6d490fbbbb | |||
| 968db4e783 | |||
| 1170ab5481 | |||
| c2ee14dec9 | |||
| 139cbe1c64 | |||
| 1854ea086c | |||
| 716e303230 | |||
| 47d04ced8f | |||
| 95332e39f5 | |||
| ae3025a2e1 | |||
| 39e5daaca8 | |||
| 4add69432f | |||
| 7825ee5ef2 | |||
| 4eed79ee52 | |||
| 571120d650 | |||
| 7999aab26a | |||
| d689e0fc47 | |||
| 819f865723 | |||
| 4f8f182d21 | |||
| a2e1a97382 | |||
| 60920cd75a | |||
| 59b7927994 | |||
| 8befbbe8f0 | |||
| b0f69a1092 | |||
| 3b750e7f27 | |||
| ffa2870b56 | |||
| 1cb7dde0d5 | |||
| 20b9395585 | |||
| 73e9ff44fe | |||
| bffbaf6b37 | |||
| eba2fce923 | |||
| 792ee587ae | |||
| eaf183352c | |||
| 7ab2a5ed9a | |||
| 28fc6841f3 | |||
| 5df23df291 | |||
| 52ae1f7d3c | |||
| 0c247dde28 | |||
| 784fa78267 | |||
| d21b3c6d7e | |||
| a1e35ade49 | |||
| 89da20354c | |||
| 2f1006c6de | |||
| 744e1429b9 | |||
| 59fb1696a8 | |||
| 38afefde25 | |||
| d905f19355 | |||
| d8704ee37d | |||
| 0b260d57cc | |||
| dcc06eb3bb | |||
| 0a92cf1b40 | |||
| 62bc4e42ec | |||
| 95a172df06 | |||
| 40c8289ce8 | |||
| b388a1e873 | |||
| 14c2cf56d1 | |||
| 164671ffeb | |||
| 05043d4771 | |||
| 25f061f340 | |||
| bf277473c6 | |||
| 6b3fd19fa9 | |||
| c074d3b7d4 | |||
| 6cce958548 | |||
| ccb1c68b65 | |||
| f609452727 | |||
| b2150b93a2 | |||
| b9fa20714f | |||
| e5ee242dc6 | |||
| 9dbc5650ed | |||
| 0052ceb7a1 | |||
| e91e6be851 | |||
| 349586e14c | |||
| c4b30a7b0e | |||
| f0555af8cc | |||
| e5244b7dba | |||
| bf2ca8bd0b | |||
| f4bcef13f5 | |||
| efdc23c567 | |||
| e84d27dde7 | |||
| 7aa2fd1af3 | |||
| 5a1c968105 | |||
| e87fd9e0cc | |||
| dae1e429b8 | |||
| 55670b0cf7 | |||
| 5f7507c324 | |||
| a90aac7b26 | |||
| cf1f772157 | |||
| 8e9fef27c2 | |||
| 75fb79f814 | |||
| f4ef56993d | |||
| 3bfbf10cff | |||
| e6ea34e453 | |||
| ae51789c32 | |||
| 4d48ab5109 | |||
| c75c21105a | |||
| 830cf33c1f | |||
| 37abe74d43 | |||
| ea15aaaec2 | |||
| 10d056a4d1 | |||
| a0377362d7 | |||
| 0d1f63e601 | |||
| afc6d9094b | |||
| 420290969e | |||
| dc152f875f | |||
| a4a07df612 | |||
| 60c1609ba9 | |||
| a08f8b3015 | |||
| df13f819b5 | |||
| 0a17edd1ae | |||
| 2efb974189 | |||
| 7b719e6432 | |||
| 2a9b3e5221 | |||
| a888aba61e | |||
| 800246660a | |||
| ca2e017f80 | |||
| 1471a61609 | |||
| 1580d1ed4d | |||
| 34aaeac421 | |||
| 0c69c9a79c | |||
| 5400a61ff1 | |||
| 942cf5e718 | |||
| f32d62722a | |||
| 82a74701a7 | |||
| 09d2f1d900 | |||
| 7edcc0659b | |||
| 673e5d59a5 | |||
| ead6247cd8 | |||
| e00f9d5790 | |||
| fe77f07c07 | |||
| 5a80b9e501 | |||
| ae9db841f9 | |||
| 937d866bd3 | |||
| 592414330b | |||
| ac098b8b2f | |||
| 3a193e2117 | |||
| 0495e45ff7 | |||
| 045d8f6c2a | |||
| 9c78de10ba | |||
| 37249e4375 | |||
| d61745a311 | |||
| 55c7d6872a | |||
| 3bd9120a3a | |||
| 01fe535594 | |||
| f6ac7d9369 | |||
| 0e02d216aa | |||
| 108c4fcd56 | |||
| 05523b01b0 | |||
| be07f052d9 | |||
| 7f34d8dd2f | |||
| f85ffbc09c | |||
| 6d708a8f2c | |||
| 66bc1dc492 | |||
| 8e3ba9d88e | |||
| 1e4894d625 | |||
| 14b6fdd51e | |||
| 3099d967da | |||
| 471a5f5aaa | |||
| fff13f2692 | |||
| 234efc5267 | |||
| c4d02a8f96 | |||
| 21efd50fb7 | |||
| 972ceb24e6 | |||
| 679ac764b1 | |||
| 962b99e8d3 | |||
| 3d15e1ff54 | |||
| 178880bace | |||
| d5d63070c6 | |||
| 97da3347be | |||
| d6252df4cd | |||
| 33308616af | |||
| 68255893cf | |||
| 57d8155bb0 | |||
| 92841cd38a | |||
| 29c3bd3746 | |||
| b0380d4ede | |||
| 28bc80e439 | |||
| d46524aedc | |||
| 677c043a91 | |||
| 50d9389dce | |||
| 2c04a816d7 | |||
| f4a5a30451 | |||
| 4267d01bc2 | |||
| 8324b35506 | |||
| b823bae63e | |||
| 334ba44e95 | |||
| e4d308f329 | |||
| cf587122da | |||
| 93a79ec470 | |||
| 3d862962f7 | |||
| 69bff1183f | |||
| 93a923d38f | |||
| 22aabdbfab | |||
| 5ba1ec0d3b | |||
| 8398d26d10 | |||
| fa33f3158e | |||
| 0fa03fad24 | |||
| 91bacf8e51 | |||
| a848142274 | |||
| be50c63e72 | |||
| 0494d551b6 | |||
| ecf5801787 | |||
| 753fd79bf3 | |||
| 2845d39311 | |||
| 29002b2efb | |||
| e8f80ca211 | |||
| 07b052cfab | |||
| 3aaa3e27f3 | |||
| c316f90999 | |||
| b8e57144cc | |||
| 1017934dce | |||
| 6716dbb7e5 | |||
| 9bebedd967 | |||
| 988034cef6 | |||
| a1fb98c79f | |||
| 872b7b6161 | |||
| ab2c3ce4e9 | |||
| 2bc386ee81 | |||
| 15ff3f9edc | |||
| 9ab505caec | |||
| 85572d7b67 | |||
| 74c04a354a | |||
| a91dba3e8a | |||
| dac859ec1c | |||
| e8165348db | |||
| a4d11bd1a6 | |||
| 559ee6291e | |||
| 6dc651a79f | |||
| 4d009d116d | |||
| 6adf39e233 | |||
| e7b71aa909 | |||
| 2cd4b13135 | |||
| 1c40d50097 | |||
| f22c0f3322 | |||
| 0c3d9ec5dd | |||
| ea571003d9 | |||
| e50d2f7fc3 | |||
| 7b13e902ff | |||
| 9d540cebb6 | |||
| afc40e7dbc | |||
| ae0d9b0c68 | |||
| 8081e9c801 | |||
| 3a20d1187e | |||
| 60f2426774 | |||
| bc41909e7a | |||
| 7a042bc7eb | |||
| 57979a2270 | |||
| ef1c4fb0cb | |||
| 965d74e34a | |||
| 854c1af45e | |||
| 24e8fe3a4b | |||
| 511e82abb9 | |||
| e46a2cb074 | |||
| 351ccaf2f2 | |||
| 2e77651dd2 | |||
| 35011e5ae3 | |||
| bfabac945f | |||
| 5495a34d02 | |||
| d0475b8052 | |||
| 86a52d0302 | |||
| 2b057cf690 | |||
| 082391e385 | |||
| 7603b3cc36 | |||
| ceaa4ff03f | |||
| 180209e55c | |||
| f650445ddc | |||
| 19a7c57e2f | |||
| 9526c77675 | |||
| 3d6ff09847 | |||
| e0918817ae | |||
| cb9860e9e0 | |||
| 3699addf16 | |||
| 04a0204119 | |||
| 4a48e19cac | |||
| 6c4c4695d9 | |||
| e39298db3c | |||
| 6001a1e4e7 | |||
| b835d5f209 | |||
| 3da66ba42e | |||
| 93ee8f85f6 | |||
| 1232ca53f0 | |||
| a756e0de15 | |||
| 81095e777a | |||
| 0d2fa807da | |||
| b36c8ff788 | |||
| aaec5efd52 | |||
| 22e7934804 | |||
| ef5cec7f5e | |||
| 65f9ee8a4a | |||
| 0ac59b8a42 | |||
| 82541248a1 | |||
| 39340fa412 | |||
| cd4b6815c8 | |||
| e24406fc9d | |||
| 4c79c5756f | |||
| 5543041fcd | |||
| c13d960df5 | |||
| 5a31c50d4d | |||
| 39b15b98e6 | |||
| 63a0273591 | |||
| 1bdf5edc24 | |||
| e6d15474df | |||
| d09c25c0d5 | |||
| 77faacb467 | |||
| db3b5c1735 | |||
| 7a0803cfd7 | |||
| 4fd30e0c75 | |||
| 80b2ffe3ee | |||
| bc7d1d39fd | |||
| be4facdea9 | |||
| 5156e633ca | |||
| 49a8b191c4 | |||
| 68f563fba4 | |||
| 3d1e1b1605 | |||
| b8d8ff8bae | |||
| cf944ae651 | |||
| 2e2bbc9d52 | |||
| f1b704a419 | |||
| 505e6d780e | |||
| 7372987754 | |||
| b22f569e4d | |||
| 1f0ee92992 | |||
| 8cda74e691 | |||
| dc3f58f044 | |||
| 4c2027aabb | |||
| 440703efff | |||
| d198157fb8 | |||
| d1067f956c | |||
| b0679a80ae | |||
| d7ab51f29b | |||
| ca48caa8b0 | |||
| e2a96501b7 | |||
| c7107677d2 | |||
| 9b9ebca246 | |||
| 36493e042e | |||
| 4a093196b8 | |||
| cd0b95d383 | |||
| 029aad4f35 | |||
| 4e536c523e | |||
| 416a6ac1bd | |||
| 301efac8dd | |||
| 8c94ae0441 | |||
| 01fdd387d9 | |||
| e3e66d2425 | |||
| 154083b875 | |||
| 3ce06ab387 | |||
| 2a76ff0037 | |||
| 848710b447 | |||
| d537366f0c | |||
| 2e479e4589 | |||
| 6ba0fc3e08 | |||
| f4cdd20a38 | |||
| b7c7f1d6a4 | |||
| 9fecb37e30 | |||
| 2667807c1d | |||
| b1060f20ec | |||
| 162aaa993a | |||
| 17cec5297d | |||
| 8aa6288210 | |||
| 8bddbff9aa | |||
| 814c2d7ffa | |||
| 39252d4633 | |||
| 7d0a7844ea | |||
| 9474d72491 | |||
| 862045e49a | |||
| efa5ab7ec8 | |||
| 97cec8604a | |||
| 8d47693448 | |||
| db5066cd23 | |||
| 52c1c09e16 | |||
| bcbd9a85e6 | |||
| 677c249b61 | |||
| 723c85320f | |||
| 92682abbae | |||
| a88d448fc8 | |||
| 5047678799 | |||
| 5ff2b530b9 | |||
| 2598446d54 | |||
| c479022c20 | |||
| eb657bce36 | |||
| c1f0a39982 | |||
| e0cdfc6d2d | |||
| b172a382f1 | |||
| 77f90a85ef | |||
| e6220f474b | |||
| 88d30d8c93 | |||
| c2a7e4c251 | |||
| fe5ef1584b | |||
| 8762ae2f28 | |||
| 98eea76195 | |||
| a36a3f8c09 | |||
| 3f75aabbc5 | |||
| 6b6c388a1a | |||
| 2f38a3894a | |||
| 4d51f21831 | |||
| ef539bf4a7 | |||
| 9cc2c18059 | |||
| f78ce21da2 | |||
| eabdbab89e | |||
| f9eb8b141e | |||
| 54858b921d | |||
| 02e0f3f856 | |||
| c8d5856216 | |||
| 0813924a7e | |||
| 702b9553e7 | |||
| bb0a8991df | |||
| e681d8cf23 | |||
| c4da135fe0 | |||
| ce623075e3 | |||
| 8e9de00529 | |||
| 8f97939f25 | |||
| fcad4de670 | |||
| 471618d287 | |||
| accb5ed654 | |||
| eadfbbee6f | |||
| 17c075eb0e | |||
| 26684b6371 | |||
| f9a9e6bfb7 | |||
| c09414cc40 | |||
| 371bc8913f | |||
| 1185208bf9 | |||
| 7fed38f1ab | |||
| 2a49e226f9 | |||
| 92f1c65c1c | |||
| edf95175a7 | |||
| 9c1a0cbc16 | |||
| bc3948ce59 | |||
| bade753fe3 | |||
| e6dc2fd6ab | |||
| b4b3bf60b8 | |||
| f636a78977 | |||
| c1cca356df | |||
| 8164418dc8 | |||
| 04d1f0f710 | |||
| 28b3a90723 | |||
| 02abc46d5e | |||
| dc810096d4 | |||
| 86ecca1c38 | |||
| fe427d67af | |||
| de413294ca | |||
| fce1c42db3 | |||
| 3dd2ee7968 | |||
| 24a78e772c | |||
| dd62944b79 | |||
| 7f345f051f | |||
| 94c1ec4b84 | |||
| eb833723cd | |||
| 88896abe48 | |||
| 87ac933c10 | |||
| 9dfa9e8e66 | |||
| 32f4f1e54a | |||
| 6f28711196 | |||
| 1cdc046566 | |||
| ca0ece37e6 | |||
| f5b44acc38 | |||
| 3f24389f36 | |||
| 0c6f37fff7 | |||
| 31c5e45bd4 | |||
| f3706b0755 | |||
| 26c210db33 | |||
| f3303ce3fa | |||
| 452ef8b6e7 | |||
| 68b22562d9 | |||
| d3ffc7aec1 | |||
| f7dbb9d07f | |||
| f3eb6f4a43 | |||
| 925e305184 | |||
| 84aba3f6d3 | |||
| 0caa2a79ae | |||
| dfd48debe5 | |||
| 3475e72730 | |||
| dc58699ee7 | |||
| 2baad552f1 | |||
| 06a2c52b26 | |||
| 97e6ff00d2 | |||
| 255bdc700e | |||
| 6110352df8 | |||
| 880ae3a474 | |||
| 9368c6079d | |||
| bc8526efe7 | |||
| 25fd84490b | |||
| 1c9e90178c | |||
| 82de2f1351 | |||
| 48be4edbdd | |||
| 46af76a8ed | |||
| 2dd49f0c92 | |||
| 539af61e1f | |||
| 85e928b426 | |||
| 5f6e2a0af3 | |||
| 190cfcd1dc | |||
| 8cecd5935e | |||
| 891655b3ce | |||
| 73af6a31b6 | |||
| a3a2f8ea09 | |||
| 8769b658b1 | |||
| 4e30531907 | |||
| 7796c4e87d | |||
| 061566ee27 | |||
| cc2fb73e87 | |||
| 79f8ce0e97 | |||
| 75b7553683 | |||
| 271d37f572 | |||
| c9c1853c57 | |||
| fd7a4e9bd7 | |||
| f2298aed77 | |||
| e7850a796e | |||
| 19a30f5090 | |||
| 23e02d621f | |||
| 056b9550d0 | |||
| 8d1f280771 | |||
| 63530ba66d | |||
| 088b4fcc55 | |||
| e3ffbb155f | |||
| 48b8a3a2c5 | |||
| 34f8bc99c6 | |||
| a5e4b38252 | |||
| 6065e8c801 | |||
| cd5a8d1a50 | |||
| 37b13265c9 | |||
| 0d5f282349 | |||
| db981807bb | |||
| 1f302f09bb | |||
| c0ccae1031 | |||
| 9023057906 | |||
| 2d5eb6d57e | |||
| 42648d0a83 | |||
| 4c749e78b2 | |||
| ef1acfa0e8 | |||
| 5759f419c0 | |||
| 8b3424bd09 | |||
| 76e060cf97 | |||
| 2aa489643a | |||
| 36de623401 | |||
| 74f161b548 | |||
| fa1b0db453 | |||
| 22c40fe752 | |||
| d3538a1fbd | |||
| b21061c164 | |||
| 8e3d3c2c22 | |||
| 9f9237905a | |||
| 872c9d5ebb | |||
| 15d9a044c6 | |||
| 051ef8178e | |||
| 76d2a782fc | |||
| 257bdb2dbb | |||
| b0ece8b516 | |||
| aaa2484e1b | |||
| 43f2c015f3 | |||
| d811812356 | |||
| d73dae09e7 | |||
| 4047440acc | |||
| 3f9afb1f31 | |||
| 81c66c8d85 | |||
| 0fa2ac4ea0 | |||
| 886c99623f | |||
| 68ae02263b | |||
| 9751e8f5b1 | |||
| 89574b61c5 | |||
| 253158cf1c | |||
| 8c34bdbcd7 | |||
| ecd3b58b28 | |||
| 41bac830c5 | |||
| 47b25d1c6d | |||
| 109de75c6a | |||
| 42856ec16a | |||
| faa43d51a9 | |||
| 3e4fce58fa | |||
| b0bddce017 | |||
| b5c69984e3 | |||
| a8375d0459 | |||
| 1f16b349d2 | |||
| 30019dfddd | |||
| 61eea7f4a1 | |||
| 6582e2ff06 | |||
| 8cfe21f6aa | |||
| 6815fc451f | |||
| 31643ee598 | |||
| 1a3bb25f5c | |||
| 181a61f16a | |||
| 763bde9ed1 | |||
| 0486db1e74 | |||
| 6185f156ea | |||
| d37e65c58c | |||
| 43efda72d4 | |||
| e55c0d4945 | |||
| a518833f96 | |||
| 49fe78643a | |||
| d2ef4c9831 | |||
| ec7b87d69c | |||
| 1e01e29f88 | |||
| e9f206606d | |||
| c5e4912319 | |||
| 63b7b18b17 | |||
| cfc008686b | |||
| e1237feb97 | |||
| cf88ec8333 | |||
| bba2dda59a | |||
| e2601f71e3 | |||
| 195c794e5d | |||
| 5732e0d72a | |||
| 187163763e | |||
| 15a32f4c78 | |||
| a76640c409 | |||
| 11773a5825 | |||
| 65de784be1 | |||
| 55cf07926c | |||
| bd39534c2f | |||
| 9dc63f0349 | |||
| edd93f27ce | |||
| 97a2232fbf | |||
| 29743e1d63 | |||
| 2bddccaaf0 | |||
| 8f5d702a86 | |||
| 24d32e9321 | |||
| 679fa4e72e | |||
| 9b4ebc3a05 | |||
| 7d4ead51f7 | |||
| bcd834c084 | |||
| 593a1eacc8 | |||
| d05d29aa66 | |||
| 4a3a9f1a21 | |||
| a89ede0d72 | |||
| 65ec618a48 | |||
| e63d5a3367 | |||
| 5b5463b6f9 | |||
| 205163641f | |||
| 09eae7ff28 | |||
| d46a174080 | |||
| 0c91bb96e0 | |||
| 9e9f436454 | |||
| cbd2fef80f | |||
| 996e471171 | |||
| 70f7dd4c7d | |||
| 9c106aa8ff | |||
| 7dcee4b40e | |||
| f12d1bcb56 | |||
| b9ab70f21b | |||
| c2d6e4c31f | |||
| a6c712323f | |||
| b93306788b | |||
| 2a62e0e04d | |||
| 8e5d8b8861 | |||
| 8b0b6194b2 | |||
| 675a9f827e | |||
| 235247eb12 | |||
| b3b5896329 | |||
| ecb1cde3fc | |||
| 9be48a73ea | |||
| 7e791e02f2 | |||
| 06d55e3501 | |||
| 37cfbdb802 | |||
| 8d1a857e75 | |||
| 42e2c237d4 | |||
| b22e1e3e9c | |||
| 635ec58616 | |||
| f44dd06826 | |||
| 02d7442e4f | |||
| 4ded634d75 | |||
| 80a25af502 | |||
| 9b2d2efc7a | |||
| 6b0e609935 | |||
| 74d3890ba9 | |||
| df4d2d2594 | |||
| b7dc2339f4 | |||
| edbb235668 | |||
| 92776ce0ac | |||
| e48c7f168b | |||
| 8a550852da | |||
| 6af94298ec | |||
| 1163efbcca | |||
| 3a32144d89 | |||
| e3519f5bd4 | |||
| 7d8b1712a7 | |||
| 54b51038ca | |||
| e774a893da | |||
| b03a057a76 | |||
| 48dd1cf024 | |||
| a2d477ac5e | |||
| 1352dfeb0f | |||
| d4e7765a50 | |||
| 73b579c962 | |||
| b67afcd727 | |||
| a10e245e5a | |||
| 181e866175 | |||
| d998c803d3 | |||
| a559ab85cd | |||
| c66edc9169 | |||
| b7606c7a8d | |||
| 12e2ace039 | |||
| ed4b9945f8 | |||
| 951e714e77 | |||
| 008bb1aab3 | |||
| 4cc24d475a | |||
| 4b8c9bc30d | |||
| 978ed1bc1e | |||
| 676765e808 | |||
| f2065265c8 | |||
| a6e2eec9e0 | |||
| 2e383da0d8 | |||
| e30a9d2a94 | |||
| 492292e94b | |||
| 454f519b6d | |||
| 56d53e3ad4 | |||
| 67b3d32218 | |||
| d7ad5b6340 | |||
| db1365c8ce | |||
| b5b0081108 | |||
| fff81c455d | |||
| ad972a0c5c | |||
| 872c92cd4b | |||
| 1d8d19d404 | |||
| ed6f234205 | |||
| 09c11440dd | |||
| e58421a08a | |||
| fb580a6e48 | |||
| f79ebdaa88 | |||
| b432a3d6db | |||
| ef4c46f2be | |||
| 69b1239aa1 | |||
| 4ef57315da | |||
| d26f37236d | |||
| 63e115e7a8 | |||
| 9f98334d6f | |||
| 15f724f146 | |||
| afb22d15ae | |||
| e709b13e77 | |||
| 460399f651 | |||
| 132272d140 | |||
| 9e4d90e110 | |||
| df91739b77 | |||
| d3f7071983 | |||
| d287a01b44 | |||
| 0eadc86d24 | |||
| c7b117631b | |||
| 0e29cfdfda | |||
| cf07df07d6 | |||
| 4e3dd8ae3f | |||
| 4b34bbadf9 | |||
| cc57b9e581 | |||
| aad966820e | |||
| 5443886ec3 | |||
| a8063de6b8 | |||
| e13ada2b43 | |||
| 62b29282fd | |||
| 2814c8e44c | |||
| 7f513b87ee | |||
| a3d4bc0bfe | |||
| e67d198e69 | |||
| b5692c8534 | |||
| 2e311896ad | |||
| 8cc5be1212 | |||
| b0a780822a | |||
| a932442d26 | |||
| 889c9de779 | |||
| e69aa04918 | |||
| c7f52f516c | |||
| 8c641d21d8 | |||
| 9605409838 | |||
| 604d6bd4e3 | |||
| 14f4fae786 | |||
| c476db0dd7 | |||
| 0a5f92a854 | |||
| b1cbf04f25 | |||
| 70b8bf106c | |||
| 99bf85e913 | |||
| e0c208be58 | |||
| 26eca23706 | |||
| 98253fea5d | |||
| 9a13dd78fc | |||
| 3e59438646 | |||
| 7a6f2b4f06 | |||
| a417dd00c5 | |||
| eee5af5924 | |||
| d3579334b2 | |||
| 0b8fd966ff | |||
| 972bc5636d | |||
| 44ed661e3b | |||
| 4009dbd6a0 | |||
| 2677360f4b | |||
| e461788b2b | |||
| f7ed97a33e | |||
| fc0434b3da | |||
| 1408c68205 | |||
| 53bc8e769f | |||
| b5f73e2087 | |||
| cb113c6452 | |||
| 8e5f1d9667 | |||
| 47d23601b1 | |||
| 212d513746 | |||
| 3e6883bdc0 | |||
| ae7552a916 | |||
| 930b16a0af | |||
| 78d9627e4d | |||
| 785f0b64b7 | |||
| d2b73bdc5b | |||
| 4b120ccbe9 | |||
| 1fd52e702c | |||
| de564326b0 | |||
| 154ce016cc | |||
| 5d8df20b0d | |||
| 24248120a9 | |||
| 019e985c8f | |||
| ff493738a2 | |||
| 5ea265983e | |||
| c09cac1cdd | |||
| afd2631728 | |||
| 4b09072c2a | |||
| b865fd317a | |||
| bb6237a15e | |||
| b8b7c85c5e | |||
| 5ec66308e4 | |||
| 9c6a7397b5 | |||
| 87b7f8070a | |||
| 2d28075cde | |||
| 2e0211320b | |||
| 8244dd1271 | |||
| 654e02763f | |||
| 0c1c9824b2 | |||
| 63b14dde15 | |||
| 6f6f80e6d7 | |||
| 13396c72b3 | |||
| a5550cef6b | |||
| 0f49be56a4 | |||
| b9776736d4 | |||
| 9ab36291a9 | |||
| 657e53c117 | |||
| dc2ebab883 | |||
| 82571710c6 | |||
| 06adbb0c54 | |||
| d051dfe47f | |||
| 06b02e9c33 | |||
| 8b3a98f242 | |||
| 026611110a | |||
| 092b011f9b | |||
| 8a027f49a4 | |||
| 359e94151c | |||
| 02f858b264 | |||
| bdb49e6396 | |||
| 05dbcd3a72 | |||
| 64de3eb711 | |||
| 854cebc59c | |||
| 74c9ef50c2 | |||
| 85f3755f9a | |||
| 7aa867cf24 | |||
| 5d4e7cebea | |||
| ed3e47f560 | |||
| d48979526f | |||
| 329ad3cdce | |||
| 84e859b6c5 | |||
| 81d4f97abc | |||
| 2e4bb1899f | |||
| c9878b8434 | |||
| 453310a338 | |||
| 9af5d0c9d6 | |||
| 7626dcf14e | |||
| b4df89fcd1 | |||
| 8c41c5c1b7 | |||
| cfc4599a30 | |||
| 8c1e9588a1 | |||
| 70c3672963 | |||
| f4a5f67f7c | |||
| 80e972c351 | |||
| d320ce6eaf | |||
| 7e97aa3300 | |||
| 102c069d74 | |||
| d8353c2b9a | |||
| 932908532c | |||
| 718dcd1a2b | |||
| f81d6f45e1 | |||
| 8522d4e60e | |||
| 211850add2 | |||
| aa96a3f33a | |||
| ac05a62000 | |||
| f18b7ebd57 | |||
| a7712e8c71 | |||
| 71bf3c8ee5 | |||
| 1900c3b0f3 | |||
| 73faf3413b | |||
| fdc9be3e23 | |||
| 7e21cb4e04 | |||
| 8984e8c2c4 | |||
| 686ea49953 | |||
| ae9eaa95c7 | |||
| e21147cbb9 | |||
| 98c1ac439d | |||
| 337511110c | |||
| 5ab5e8400a | |||
| 7eabb70130 | |||
| ae65fde3e9 | |||
| 27a121c6b2 | |||
| 1cfa42bc24 | |||
| 401ff95867 | |||
| ccc85c80d1 | |||
| 61b525a645 | |||
| a406fdae58 | |||
| a3daf1ca24 | |||
| 2ef91b1c78 | |||
| 5282c63ec3 | |||
| 0a59a3c4df | |||
| 47cf4f4814 | |||
| e6cbd9dc7f | |||
| f825a31ce4 | |||
| 53c4cd5ce1 | |||
| 8b840ce56b | |||
| 7eec283d70 | |||
| 10a9ef46cb | |||
| 179d80a93b | |||
| 48f10196f6 | |||
| bd25b5c7fd | |||
| 09c0f3308c | |||
| 30777e4a87 | |||
| 14e72759ee | |||
| d47e600f1a | |||
| 5bd10297fb | |||
| 55a115179e | |||
| 92e73bd28a | |||
| ebc955f562 | |||
| 5683c11ebd | |||
| 61467e107f | |||
| adf6f3abb2 | |||
| 22c50b0aba | |||
| edb245b649 | |||
| 16cf465575 | |||
| 997a216b50 | |||
| d193951dc5 | |||
| c37c58ad39 | |||
| 529d582f03 | |||
| aa7975e4f7 | |||
| fdfa9912e8 | |||
| 2f59921f7a | |||
| e25fd5e37c | |||
| 5d0171e8ed | |||
| 55fc0cfd49 | |||
| cdfdc3c3e2 | |||
| ef5081184f | |||
| 02e535cdad | |||
| 3e1b120cbe | |||
| 95844701bd | |||
| 403b6751ab | |||
| 2b81ac832a | |||
| 3f9e5ab7a2 | |||
| 23deaa9307 | |||
| 2183d09b58 | |||
| ea9d144c71 | |||
| 7a23131366 | |||
| d7632efe65 | |||
| 477e09f1d4 | |||
| 641fc02212 | |||
| a55fdaad57 | |||
| d006558e69 | |||
| 29ae3200a7 | |||
| 38d1b87e1c | |||
| e139ab8596 | |||
| 28dd492460 | |||
| f13f99b7d7 | |||
| 8533c27031 | |||
| 0e5f4ec32f | |||
| e24efd23a2 | |||
| 10227f852b | |||
| 94f22b656e | |||
| dc6d5bc934 | |||
| a04082dba1 | |||
| be2f31a351 | |||
| 7d240eee9d | |||
| 0a6c892766 | |||
| 51032692f3 |
@@ -0,0 +1,19 @@
|
||||
---
|
||||
engines:
|
||||
duplication:
|
||||
enabled: true
|
||||
config:
|
||||
languages:
|
||||
- javascript
|
||||
eslint:
|
||||
enabled: true
|
||||
fixme:
|
||||
enabled: true
|
||||
ratings:
|
||||
paths:
|
||||
- "**.js"
|
||||
exclude_paths:
|
||||
- dist/
|
||||
- node_modules/
|
||||
- test/
|
||||
- coverage/
|
||||
@@ -0,0 +1 @@
|
||||
**/*{.,-}min.js
|
||||
+213
@@ -0,0 +1,213 @@
|
||||
ecmaFeatures:
|
||||
modules: true
|
||||
jsx: true
|
||||
|
||||
env:
|
||||
amd: true
|
||||
browser: true
|
||||
es6: true
|
||||
jquery: true
|
||||
node: true
|
||||
|
||||
# http://eslint.org/docs/rules/
|
||||
rules:
|
||||
# Possible Errors
|
||||
comma-dangle: [2, never]
|
||||
no-cond-assign: 2
|
||||
no-console: 0
|
||||
no-constant-condition: 2
|
||||
no-control-regex: 2
|
||||
no-debugger: 2
|
||||
no-dupe-args: 2
|
||||
no-dupe-keys: 2
|
||||
no-duplicate-case: 2
|
||||
no-empty: 2
|
||||
no-empty-character-class: 2
|
||||
no-ex-assign: 2
|
||||
no-extra-boolean-cast: 2
|
||||
no-extra-parens: 0
|
||||
no-extra-semi: 2
|
||||
no-func-assign: 2
|
||||
no-inner-declarations: [2, functions]
|
||||
no-invalid-regexp: 2
|
||||
no-irregular-whitespace: 2
|
||||
no-negated-in-lhs: 2
|
||||
no-obj-calls: 2
|
||||
no-regex-spaces: 2
|
||||
no-sparse-arrays: 2
|
||||
no-unexpected-multiline: 2
|
||||
no-unreachable: 2
|
||||
use-isnan: 2
|
||||
valid-jsdoc: 0
|
||||
valid-typeof: 2
|
||||
|
||||
# Best Practices
|
||||
accessor-pairs: 2
|
||||
block-scoped-var: 0
|
||||
complexity: [2, 6]
|
||||
consistent-return: 0
|
||||
curly: 0
|
||||
default-case: 0
|
||||
dot-location: 0
|
||||
dot-notation: 0
|
||||
eqeqeq: 2
|
||||
guard-for-in: 2
|
||||
no-alert: 2
|
||||
no-caller: 2
|
||||
no-case-declarations: 2
|
||||
no-div-regex: 2
|
||||
no-else-return: 0
|
||||
no-empty-label: 2
|
||||
no-empty-pattern: 2
|
||||
no-eq-null: 2
|
||||
no-eval: 2
|
||||
no-extend-native: 2
|
||||
no-extra-bind: 2
|
||||
no-fallthrough: 2
|
||||
no-floating-decimal: 0
|
||||
no-implicit-coercion: 0
|
||||
no-implied-eval: 2
|
||||
no-invalid-this: 0
|
||||
no-iterator: 2
|
||||
no-labels: 0
|
||||
no-lone-blocks: 2
|
||||
no-loop-func: 2
|
||||
no-magic-number: 0
|
||||
no-multi-spaces: 0
|
||||
no-multi-str: 0
|
||||
no-native-reassign: 2
|
||||
no-new-func: 2
|
||||
no-new-wrappers: 2
|
||||
no-new: 2
|
||||
no-octal-escape: 2
|
||||
no-octal: 2
|
||||
no-proto: 2
|
||||
no-redeclare: 2
|
||||
no-return-assign: 2
|
||||
no-script-url: 2
|
||||
no-self-compare: 2
|
||||
no-sequences: 0
|
||||
no-throw-literal: 0
|
||||
no-unused-expressions: 2
|
||||
no-useless-call: 2
|
||||
no-useless-concat: 2
|
||||
no-void: 2
|
||||
no-warning-comments: 0
|
||||
no-with: 2
|
||||
radix: 2
|
||||
vars-on-top: 0
|
||||
wrap-iife: 2
|
||||
yoda: 0
|
||||
|
||||
# Strict
|
||||
strict: 0
|
||||
|
||||
# Variables
|
||||
init-declarations: 0
|
||||
no-catch-shadow: 2
|
||||
no-delete-var: 2
|
||||
no-label-var: 2
|
||||
no-shadow-restricted-names: 2
|
||||
no-shadow: 0
|
||||
no-undef-init: 2
|
||||
no-undef: 0
|
||||
no-undefined: 0
|
||||
no-unused-vars: 0
|
||||
no-use-before-define: 0
|
||||
|
||||
# Node.js and CommonJS
|
||||
callback-return: 2
|
||||
global-require: 2
|
||||
handle-callback-err: 2
|
||||
no-mixed-requires: 0
|
||||
no-new-require: 0
|
||||
no-path-concat: 2
|
||||
no-process-exit: 2
|
||||
no-restricted-modules: 0
|
||||
no-sync: 0
|
||||
|
||||
# Stylistic Issues
|
||||
array-bracket-spacing: 0
|
||||
block-spacing: 0
|
||||
brace-style: 0
|
||||
camelcase: 0
|
||||
comma-spacing: 0
|
||||
comma-style: 0
|
||||
computed-property-spacing: 0
|
||||
consistent-this: 0
|
||||
eol-last: 0
|
||||
func-names: 0
|
||||
func-style: 0
|
||||
id-length: 0
|
||||
id-match: 0
|
||||
indent: 0
|
||||
jsx-quotes: 0
|
||||
key-spacing: 0
|
||||
linebreak-style: 0
|
||||
lines-around-comment: 0
|
||||
max-depth: 0
|
||||
max-len: 0
|
||||
max-nested-callbacks: 0
|
||||
max-params: 0
|
||||
max-statements: [2, 30]
|
||||
new-cap: 0
|
||||
new-parens: 0
|
||||
newline-after-var: 0
|
||||
no-array-constructor: 0
|
||||
no-bitwise: 0
|
||||
no-continue: 0
|
||||
no-inline-comments: 0
|
||||
no-lonely-if: 0
|
||||
no-mixed-spaces-and-tabs: 0
|
||||
no-multiple-empty-lines: 0
|
||||
no-negated-condition: 0
|
||||
no-nested-ternary: 0
|
||||
no-new-object: 0
|
||||
no-plusplus: 0
|
||||
no-restricted-syntax: 0
|
||||
no-spaced-func: 0
|
||||
no-ternary: 0
|
||||
no-trailing-spaces: 0
|
||||
no-underscore-dangle: 0
|
||||
no-unneeded-ternary: 0
|
||||
object-curly-spacing: 0
|
||||
one-var: 0
|
||||
operator-assignment: 0
|
||||
operator-linebreak: 0
|
||||
padded-blocks: 0
|
||||
quote-props: 0
|
||||
quotes: 0
|
||||
require-jsdoc: 0
|
||||
semi-spacing: 0
|
||||
semi: 0
|
||||
sort-vars: 0
|
||||
space-after-keywords: 0
|
||||
space-before-blocks: 0
|
||||
space-before-function-paren: 0
|
||||
space-before-keywords: 0
|
||||
space-in-parens: 0
|
||||
space-infix-ops: 0
|
||||
space-return-throw-case: 0
|
||||
space-unary-ops: 0
|
||||
spaced-comment: 0
|
||||
wrap-regex: 0
|
||||
|
||||
# ECMAScript 6
|
||||
arrow-body-style: 0
|
||||
arrow-parens: 0
|
||||
arrow-spacing: 0
|
||||
constructor-super: 0
|
||||
generator-star-spacing: 0
|
||||
no-arrow-condition: 0
|
||||
no-class-assign: 0
|
||||
no-const-assign: 0
|
||||
no-dupe-class-members: 0
|
||||
no-this-before-super: 0
|
||||
no-var: 0
|
||||
object-shorthand: 0
|
||||
prefer-arrow-callback: 0
|
||||
prefer-const: 0
|
||||
prefer-reflect: 0
|
||||
prefer-spread: 0
|
||||
prefer-template: 0
|
||||
require-yield: 0
|
||||
@@ -1,2 +1,13 @@
|
||||
|
||||
.DS_Store
|
||||
|
||||
node_modules/*
|
||||
custom/*
|
||||
|
||||
docs/index.md
|
||||
|
||||
bower_components/
|
||||
|
||||
coverage/*
|
||||
|
||||
nbproject/*
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- "5.6"
|
||||
- "4.3"
|
||||
|
||||
before_install:
|
||||
- "export DISPLAY=:99.0"
|
||||
- "sh -e /etc/init.d/xvfb start"
|
||||
- "sudo apt-get update"
|
||||
- "sudo apt-get install -y libappindicator1 fonts-liberation"
|
||||
- "wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb"
|
||||
- "sudo dpkg -i google-chrome*.deb"
|
||||
- "export CHROME_BIN=/usr/bin/google-chrome"
|
||||
|
||||
before_script:
|
||||
- npm install
|
||||
|
||||
script:
|
||||
- gulp test
|
||||
- gulp coverage
|
||||
- cat ./coverage/lcov.info | ./node_modules/.bin/coveralls
|
||||
|
||||
notifications:
|
||||
slack: chartjs:pcfCZR6ugg5TEcaLtmIfQYuA
|
||||
|
||||
sudo: required
|
||||
|
||||
addons:
|
||||
firefox: latest
|
||||
@@ -0,0 +1,61 @@
|
||||
Contributing to Chart.js
|
||||
========================
|
||||
|
||||
Contributions to Chart.js are welcome and encouraged, but please have a look through the guidelines in this document before raising an issue, or writing code for the project.
|
||||
|
||||
|
||||
Using issues
|
||||
------------
|
||||
|
||||
The [issue tracker](https://github.com/nnnick/Chart.js/issues) is the preferred channel for reporting bugs, requesting new features and submitting pull requests.
|
||||
|
||||
If you're suggesting a new chart type, please take a look at [writing new chart types](https://github.com/nnnick/Chart.js/blob/master/docs/06-Advanced.md#writing-new-chart-types) in the documentation, and some of the [community extensions](https://github.com/nnnick/Chart.js/blob/master/docs/06-Advanced.md#community-extensions) that have been created already.
|
||||
|
||||
To keep the library lightweight for everyone, it's unlikely we'll add many more chart types to the core of Chart.js, but issues are a good medium to design and spec out how new chart types could work and look.
|
||||
|
||||
Please do not use issues for support requests. For help using Chart.js, please take a look at the [`chartjs`](http://stackoverflow.com/questions/tagged/chartjs) tag on Stack Overflow.
|
||||
|
||||
|
||||
Reporting bugs
|
||||
--------------
|
||||
|
||||
Well structured, detailed bug reports are hugely valuable for the project.
|
||||
|
||||
Guidlines for reporting bugs:
|
||||
|
||||
- Check the issue search to see if it has already been reported
|
||||
- Isolate the problem to a simple test case
|
||||
- Provide a demonstration of the problem on [JS Bin](http://jsbin.com) or similar
|
||||
|
||||
Please provide any additional details associated with the bug, if it's browser or screen density specific, or only happens with a certain configuration or data.
|
||||
|
||||
|
||||
Local development
|
||||
-----------------
|
||||
|
||||
Run `npm install` to install all the libraries, then run `gulp dev --test` to build and run tests as you make changes.
|
||||
|
||||
|
||||
Pull requests
|
||||
-------------
|
||||
|
||||
Clear, concise pull requests are excellent at continuing the project's community driven growth. But please review [these guidelines](https://github.com/blog/1943-how-to-write-the-perfect-pull-request) and the guidelines below before starting work on the project.
|
||||
|
||||
Guidlines:
|
||||
|
||||
- Please create an issue first:
|
||||
- For bugs, we can discuss the fixing approach
|
||||
- For enhancements, we can discuss if it is within the project scope and avoid duplicate effort
|
||||
- Please make changes to the files in [`/src`](https://github.com/nnnick/Chart.js/tree/master/src), not `Chart.js` or `Chart.min.js` in the repo root directory, this avoids merge conflicts
|
||||
- Tabs for indentation, not spaces please
|
||||
- If adding new functionality, please also update the relevant `.md` file in [`/docs`](https://github.com/nnnick/Chart.js/tree/master/docs)
|
||||
- Please make your commits in logical sections with clear commit messages
|
||||
|
||||
Joining the Project
|
||||
-------------
|
||||
- Active committers and contributors are invited to introduce yourself and request commit access to this project. Please send an email to hello@nickdownie.com or file an issue.
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
By contributing your code, you agree to license your contribution under the [MIT license](https://github.com/nnnick/Chart.js/blob/master/LICENSE.md).
|
||||
externo
-1426
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
externo
-39
@@ -1,39 +0,0 @@
|
||||
var Chart=function(s){function v(a,c,b){a=A((a-c.graphMin)/(c.steps*c.stepValue),1,0);return b*c.steps*a}function x(a,c,b,e){function h(){g+=f;var k=a.animation?A(d(g),null,0):1;e.clearRect(0,0,q,u);a.scaleOverlay?(b(k),c()):(c(),b(k));if(1>=g)D(h);else if("function"==typeof a.onAnimationComplete)a.onAnimationComplete()}var f=a.animation?1/A(a.animationSteps,Number.MAX_VALUE,1):1,d=B[a.animationEasing],g=a.animation?0:1;"function"!==typeof c&&(c=function(){});D(h)}function C(a,c,b,e,h,f){var d;a=
|
||||
Math.floor(Math.log(e-h)/Math.LN10);h=Math.floor(h/(1*Math.pow(10,a)))*Math.pow(10,a);e=Math.ceil(e/(1*Math.pow(10,a)))*Math.pow(10,a)-h;a=Math.pow(10,a);for(d=Math.round(e/a);d<b||d>c;)a=d<b?a/2:2*a,d=Math.round(e/a);c=[];z(f,c,d,h,a);return{steps:d,stepValue:a,graphMin:h,labels:c}}function z(a,c,b,e,h){if(a)for(var f=1;f<b+1;f++)c.push(E(a,{value:(e+h*f).toFixed(0!=h%1?h.toString().split(".")[1].length:0)}))}function A(a,c,b){return!isNaN(parseFloat(c))&&isFinite(c)&&a>c?c:!isNaN(parseFloat(b))&&
|
||||
isFinite(b)&&a<b?b:a}function y(a,c){var b={},e;for(e in a)b[e]=a[e];for(e in c)b[e]=c[e];return b}function E(a,c){var b=!/\W/.test(a)?F[a]=F[a]||E(document.getElementById(a).innerHTML):new Function("obj","var p=[],print=function(){p.push.apply(p,arguments);};with(obj){p.push('"+a.replace(/[\r\t\n]/g," ").split("<%").join("\t").replace(/((^|%>)[^\t]*)'/g,"$1\r").replace(/\t=(.*?)%>/g,"',$1,'").split("\t").join("');").split("%>").join("p.push('").split("\r").join("\\'")+"');}return p.join('');");return c?
|
||||
b(c):b}var r=this,B={linear:function(a){return a},easeInQuad:function(a){return a*a},easeOutQuad:function(a){return-1*a*(a-2)},easeInOutQuad:function(a){return 1>(a/=0.5)?0.5*a*a:-0.5*(--a*(a-2)-1)},easeInCubic:function(a){return a*a*a},easeOutCubic:function(a){return 1*((a=a/1-1)*a*a+1)},easeInOutCubic:function(a){return 1>(a/=0.5)?0.5*a*a*a:0.5*((a-=2)*a*a+2)},easeInQuart:function(a){return a*a*a*a},easeOutQuart:function(a){return-1*((a=a/1-1)*a*a*a-1)},easeInOutQuart:function(a){return 1>(a/=0.5)?
|
||||
0.5*a*a*a*a:-0.5*((a-=2)*a*a*a-2)},easeInQuint:function(a){return 1*(a/=1)*a*a*a*a},easeOutQuint:function(a){return 1*((a=a/1-1)*a*a*a*a+1)},easeInOutQuint:function(a){return 1>(a/=0.5)?0.5*a*a*a*a*a:0.5*((a-=2)*a*a*a*a+2)},easeInSine:function(a){return-1*Math.cos(a/1*(Math.PI/2))+1},easeOutSine:function(a){return 1*Math.sin(a/1*(Math.PI/2))},easeInOutSine:function(a){return-0.5*(Math.cos(Math.PI*a/1)-1)},easeInExpo:function(a){return 0==a?1:1*Math.pow(2,10*(a/1-1))},easeOutExpo:function(a){return 1==
|
||||
a?1:1*(-Math.pow(2,-10*a/1)+1)},easeInOutExpo:function(a){return 0==a?0:1==a?1:1>(a/=0.5)?0.5*Math.pow(2,10*(a-1)):0.5*(-Math.pow(2,-10*--a)+2)},easeInCirc:function(a){return 1<=a?a:-1*(Math.sqrt(1-(a/=1)*a)-1)},easeOutCirc:function(a){return 1*Math.sqrt(1-(a=a/1-1)*a)},easeInOutCirc:function(a){return 1>(a/=0.5)?-0.5*(Math.sqrt(1-a*a)-1):0.5*(Math.sqrt(1-(a-=2)*a)+1)},easeInElastic:function(a){var c=1.70158,b=0,e=1;if(0==a)return 0;if(1==(a/=1))return 1;b||(b=0.3);e<Math.abs(1)?(e=1,c=b/4):c=b/(2*
|
||||
Math.PI)*Math.asin(1/e);return-(e*Math.pow(2,10*(a-=1))*Math.sin((1*a-c)*2*Math.PI/b))},easeOutElastic:function(a){var c=1.70158,b=0,e=1;if(0==a)return 0;if(1==(a/=1))return 1;b||(b=0.3);e<Math.abs(1)?(e=1,c=b/4):c=b/(2*Math.PI)*Math.asin(1/e);return e*Math.pow(2,-10*a)*Math.sin((1*a-c)*2*Math.PI/b)+1},easeInOutElastic:function(a){var c=1.70158,b=0,e=1;if(0==a)return 0;if(2==(a/=0.5))return 1;b||(b=1*0.3*1.5);e<Math.abs(1)?(e=1,c=b/4):c=b/(2*Math.PI)*Math.asin(1/e);return 1>a?-0.5*e*Math.pow(2,10*
|
||||
(a-=1))*Math.sin((1*a-c)*2*Math.PI/b):0.5*e*Math.pow(2,-10*(a-=1))*Math.sin((1*a-c)*2*Math.PI/b)+1},easeInBack:function(a){return 1*(a/=1)*a*(2.70158*a-1.70158)},easeOutBack:function(a){return 1*((a=a/1-1)*a*(2.70158*a+1.70158)+1)},easeInOutBack:function(a){var c=1.70158;return 1>(a/=0.5)?0.5*a*a*(((c*=1.525)+1)*a-c):0.5*((a-=2)*a*(((c*=1.525)+1)*a+c)+2)},easeInBounce:function(a){return 1-B.easeOutBounce(1-a)},easeOutBounce:function(a){return(a/=1)<1/2.75?1*7.5625*a*a:a<2/2.75?1*(7.5625*(a-=1.5/2.75)*
|
||||
a+0.75):a<2.5/2.75?1*(7.5625*(a-=2.25/2.75)*a+0.9375):1*(7.5625*(a-=2.625/2.75)*a+0.984375)},easeInOutBounce:function(a){return 0.5>a?0.5*B.easeInBounce(2*a):0.5*B.easeOutBounce(2*a-1)+0.5}},q=s.canvas.width,u=s.canvas.height;window.devicePixelRatio&&(s.canvas.style.width=q+"px",s.canvas.style.height=u+"px",s.canvas.height=u*window.devicePixelRatio,s.canvas.width=q*window.devicePixelRatio,s.scale(window.devicePixelRatio,window.devicePixelRatio));this.PolarArea=function(a,c){r.PolarArea.defaults={scaleOverlay:!0,
|
||||
scaleOverride:!1,scaleSteps:null,scaleStepWidth:null,scaleStartValue:null,scaleShowLine:!0,scaleLineColor:"rgba(0,0,0,.1)",scaleLineWidth:1,scaleShowLabels:!0,scaleLabel:"<%=value%>",scaleFontFamily:"'Arial'",scaleFontSize:12,scaleFontStyle:"normal",scaleFontColor:"#666",scaleShowLabelBackdrop:!0,scaleBackdropColor:"rgba(255,255,255,0.75)",scaleBackdropPaddingY:2,scaleBackdropPaddingX:2,segmentShowStroke:!0,segmentStrokeColor:"#fff",segmentStrokeWidth:2,animation:!0,animationSteps:100,animationEasing:"easeOutBounce",
|
||||
animateRotate:!0,animateScale:!1,onAnimationComplete:null};var b=c?y(r.PolarArea.defaults,c):r.PolarArea.defaults;return new G(a,b,s)};this.Radar=function(a,c){r.Radar.defaults={scaleOverlay:!1,scaleOverride:!1,scaleSteps:null,scaleStepWidth:null,scaleStartValue:null,scaleShowLine:!0,scaleLineColor:"rgba(0,0,0,.1)",scaleLineWidth:1,scaleShowLabels:!1,scaleLabel:"<%=value%>",scaleFontFamily:"'Arial'",scaleFontSize:12,scaleFontStyle:"normal",scaleFontColor:"#666",scaleShowLabelBackdrop:!0,scaleBackdropColor:"rgba(255,255,255,0.75)",
|
||||
scaleBackdropPaddingY:2,scaleBackdropPaddingX:2,angleShowLineOut:!0,angleLineColor:"rgba(0,0,0,.1)",angleLineWidth:1,pointLabelFontFamily:"'Arial'",pointLabelFontStyle:"normal",pointLabelFontSize:12,pointLabelFontColor:"#666",pointDot:!0,pointDotRadius:3,pointDotStrokeWidth:1,datasetStroke:!0,datasetStrokeWidth:2,datasetFill:!0,animation:!0,animationSteps:60,animationEasing:"easeOutQuart",onAnimationComplete:null};var b=c?y(r.Radar.defaults,c):r.Radar.defaults;return new H(a,b,s)};this.Pie=function(a,
|
||||
c){r.Pie.defaults={segmentShowStroke:!0,segmentStrokeColor:"#fff",segmentStrokeWidth:2,animation:!0,animationSteps:100,animationEasing:"easeOutBounce",animateRotate:!0,animateScale:!1,onAnimationComplete:null};var b=c?y(r.Pie.defaults,c):r.Pie.defaults;return new I(a,b,s)};this.Doughnut=function(a,c){r.Doughnut.defaults={segmentShowStroke:!0,segmentStrokeColor:"#fff",segmentStrokeWidth:2,percentageInnerCutout:50,animation:!0,animationSteps:100,animationEasing:"easeOutBounce",animateRotate:!0,animateScale:!1,
|
||||
onAnimationComplete:null};var b=c?y(r.Doughnut.defaults,c):r.Doughnut.defaults;return new J(a,b,s)};this.Line=function(a,c){r.Line.defaults={scaleOverlay:!1,scaleOverride:!1,scaleSteps:null,scaleStepWidth:null,scaleStartValue:null,scaleLineColor:"rgba(0,0,0,.1)",scaleLineWidth:1,scaleShowLabels:!0,scaleLabel:"<%=value%>",scaleFontFamily:"'Arial'",scaleFontSize:12,scaleFontStyle:"normal",scaleFontColor:"#666",scaleShowGridLines:!0,scaleGridLineColor:"rgba(0,0,0,.05)",scaleGridLineWidth:1,bezierCurve:!0,
|
||||
pointDot:!0,pointDotRadius:4,pointDotStrokeWidth:2,datasetStroke:!0,datasetStrokeWidth:2,datasetFill:!0,animation:!0,animationSteps:60,animationEasing:"easeOutQuart",onAnimationComplete:null};var b=c?y(r.Line.defaults,c):r.Line.defaults;return new K(a,b,s)};this.Bar=function(a,c){r.Bar.defaults={scaleOverlay:!1,scaleOverride:!1,scaleSteps:null,scaleStepWidth:null,scaleStartValue:null,scaleLineColor:"rgba(0,0,0,.1)",scaleLineWidth:1,scaleShowLabels:!0,scaleLabel:"<%=value%>",scaleFontFamily:"'Arial'",
|
||||
scaleFontSize:12,scaleFontStyle:"normal",scaleFontColor:"#666",scaleShowGridLines:!0,scaleGridLineColor:"rgba(0,0,0,.05)",scaleGridLineWidth:1,barShowStroke:!0,barStrokeWidth:2,barValueSpacing:5,barDatasetSpacing:1,animation:!0,animationSteps:60,animationEasing:"easeOutQuart",onAnimationComplete:null};var b=c?y(r.Bar.defaults,c):r.Bar.defaults;return new L(a,b,s)};var G=function(a,c,b){var e,h,f,d,g,k,j,l,m;g=Math.min.apply(Math,[q,u])/2;g-=Math.max.apply(Math,[0.5*c.scaleFontSize,0.5*c.scaleLineWidth]);
|
||||
d=2*c.scaleFontSize;c.scaleShowLabelBackdrop&&(d+=2*c.scaleBackdropPaddingY,g-=1.5*c.scaleBackdropPaddingY);l=g;d=d?d:5;e=Number.MIN_VALUE;h=Number.MAX_VALUE;for(f=0;f<a.length;f++)a[f].value>e&&(e=a[f].value),a[f].value<h&&(h=a[f].value);f=Math.floor(l/(0.66*d));d=Math.floor(0.5*(l/d));m=c.scaleShowLabels?c.scaleLabel:null;c.scaleOverride?(j={steps:c.scaleSteps,stepValue:c.scaleStepWidth,graphMin:c.scaleStartValue,labels:[]},z(m,j.labels,j.steps,c.scaleStartValue,c.scaleStepWidth)):j=C(l,f,d,e,h,
|
||||
m);k=g/j.steps;x(c,function(){for(var a=0;a<j.steps;a++)if(c.scaleShowLine&&(b.beginPath(),b.arc(q/2,u/2,k*(a+1),0,2*Math.PI,!0),b.strokeStyle=c.scaleLineColor,b.lineWidth=c.scaleLineWidth,b.stroke()),c.scaleShowLabels){b.textAlign="center";b.font=c.scaleFontStyle+" "+c.scaleFontSize+"px "+c.scaleFontFamily;var e=j.labels[a];if(c.scaleShowLabelBackdrop){var d=b.measureText(e).width;b.fillStyle=c.scaleBackdropColor;b.beginPath();b.rect(Math.round(q/2-d/2-c.scaleBackdropPaddingX),Math.round(u/2-k*(a+
|
||||
1)-0.5*c.scaleFontSize-c.scaleBackdropPaddingY),Math.round(d+2*c.scaleBackdropPaddingX),Math.round(c.scaleFontSize+2*c.scaleBackdropPaddingY));b.fill()}b.textBaseline="middle";b.fillStyle=c.scaleFontColor;b.fillText(e,q/2,u/2-k*(a+1))}},function(e){var d=-Math.PI/2,g=2*Math.PI/a.length,f=1,h=1;c.animation&&(c.animateScale&&(f=e),c.animateRotate&&(h=e));for(e=0;e<a.length;e++)b.beginPath(),b.arc(q/2,u/2,f*v(a[e].value,j,k),d,d+h*g,!1),b.lineTo(q/2,u/2),b.closePath(),b.fillStyle=a[e].color,b.fill(),
|
||||
c.segmentShowStroke&&(b.strokeStyle=c.segmentStrokeColor,b.lineWidth=c.segmentStrokeWidth,b.stroke()),d+=h*g},b)},H=function(a,c,b){var e,h,f,d,g,k,j,l,m;a.labels||(a.labels=[]);g=Math.min.apply(Math,[q,u])/2;d=2*c.scaleFontSize;for(e=l=0;e<a.labels.length;e++)b.font=c.pointLabelFontStyle+" "+c.pointLabelFontSize+"px "+c.pointLabelFontFamily,h=b.measureText(a.labels[e]).width,h>l&&(l=h);g-=Math.max.apply(Math,[l,1.5*(c.pointLabelFontSize/2)]);g-=c.pointLabelFontSize;l=g=A(g,null,0);d=d?d:5;e=Number.MIN_VALUE;
|
||||
h=Number.MAX_VALUE;for(f=0;f<a.datasets.length;f++)for(m=0;m<a.datasets[f].data.length;m++)a.datasets[f].data[m]>e&&(e=a.datasets[f].data[m]),a.datasets[f].data[m]<h&&(h=a.datasets[f].data[m]);f=Math.floor(l/(0.66*d));d=Math.floor(0.5*(l/d));m=c.scaleShowLabels?c.scaleLabel:null;c.scaleOverride?(j={steps:c.scaleSteps,stepValue:c.scaleStepWidth,graphMin:c.scaleStartValue,labels:[]},z(m,j.labels,j.steps,c.scaleStartValue,c.scaleStepWidth)):j=C(l,f,d,e,h,m);k=g/j.steps;x(c,function(){var e=2*Math.PI/
|
||||
a.datasets[0].data.length;b.save();b.translate(q/2,u/2);if(c.angleShowLineOut){b.strokeStyle=c.angleLineColor;b.lineWidth=c.angleLineWidth;for(var d=0;d<a.datasets[0].data.length;d++)b.rotate(e),b.beginPath(),b.moveTo(0,0),b.lineTo(0,-g),b.stroke()}for(d=0;d<j.steps;d++){b.beginPath();if(c.scaleShowLine){b.strokeStyle=c.scaleLineColor;b.lineWidth=c.scaleLineWidth;b.moveTo(0,-k*(d+1));for(var f=0;f<a.datasets[0].data.length;f++)b.rotate(e),b.lineTo(0,-k*(d+1));b.closePath();b.stroke()}c.scaleShowLabels&&
|
||||
(b.textAlign="center",b.font=c.scaleFontStyle+" "+c.scaleFontSize+"px "+c.scaleFontFamily,b.textBaseline="middle",c.scaleShowLabelBackdrop&&(f=b.measureText(j.labels[d]).width,b.fillStyle=c.scaleBackdropColor,b.beginPath(),b.rect(Math.round(-f/2-c.scaleBackdropPaddingX),Math.round(-k*(d+1)-0.5*c.scaleFontSize-c.scaleBackdropPaddingY),Math.round(f+2*c.scaleBackdropPaddingX),Math.round(c.scaleFontSize+2*c.scaleBackdropPaddingY)),b.fill()),b.fillStyle=c.scaleFontColor,b.fillText(j.labels[d],0,-k*(d+
|
||||
1)))}for(d=0;d<a.labels.length;d++){b.font=c.pointLabelFontStyle+" "+c.pointLabelFontSize+"px "+c.pointLabelFontFamily;b.fillStyle=c.pointLabelFontColor;var f=Math.sin(e*d)*(g+c.pointLabelFontSize),h=Math.cos(e*d)*(g+c.pointLabelFontSize);b.textAlign=e*d==Math.PI||0==e*d?"center":e*d>Math.PI?"right":"left";b.textBaseline="middle";b.fillText(a.labels[d],f,-h)}b.restore()},function(d){var e=2*Math.PI/a.datasets[0].data.length;b.save();b.translate(q/2,u/2);for(var g=0;g<a.datasets.length;g++){b.beginPath();
|
||||
b.moveTo(0,d*-1*v(a.datasets[g].data[0],j,k));for(var f=1;f<a.datasets[g].data.length;f++)b.rotate(e),b.lineTo(0,d*-1*v(a.datasets[g].data[f],j,k));b.closePath();b.fillStyle=a.datasets[g].fillColor;b.strokeStyle=a.datasets[g].strokeColor;b.lineWidth=c.datasetStrokeWidth;b.fill();b.stroke();if(c.pointDot){b.fillStyle=a.datasets[g].pointColor;b.strokeStyle=a.datasets[g].pointStrokeColor;b.lineWidth=c.pointDotStrokeWidth;for(f=0;f<a.datasets[g].data.length;f++)b.rotate(e),b.beginPath(),b.arc(0,d*-1*
|
||||
v(a.datasets[g].data[f],j,k),c.pointDotRadius,2*Math.PI,!1),b.fill(),b.stroke()}b.rotate(e)}b.restore()},b)},I=function(a,c,b){for(var e=0,h=Math.min.apply(Math,[u/2,q/2])-5,f=0;f<a.length;f++)e+=a[f].value;x(c,null,function(d){var g=-Math.PI/2,f=1,j=1;c.animation&&(c.animateScale&&(f=d),c.animateRotate&&(j=d));for(d=0;d<a.length;d++){var l=j*a[d].value/e*2*Math.PI;b.beginPath();b.arc(q/2,u/2,f*h,g,g+l);b.lineTo(q/2,u/2);b.closePath();b.fillStyle=a[d].color;b.fill();c.segmentShowStroke&&(b.lineWidth=
|
||||
c.segmentStrokeWidth,b.strokeStyle=c.segmentStrokeColor,b.stroke());g+=l}},b)},J=function(a,c,b){for(var e=0,h=Math.min.apply(Math,[u/2,q/2])-5,f=h*(c.percentageInnerCutout/100),d=0;d<a.length;d++)e+=a[d].value;x(c,null,function(d){var k=-Math.PI/2,j=1,l=1;c.animation&&(c.animateScale&&(j=d),c.animateRotate&&(l=d));for(d=0;d<a.length;d++){var m=l*a[d].value/e*2*Math.PI;b.beginPath();b.arc(q/2,u/2,j*h,k,k+m,!1);b.arc(q/2,u/2,j*f,k+m,k,!0);b.closePath();b.fillStyle=a[d].color;b.fill();c.segmentShowStroke&&
|
||||
(b.lineWidth=c.segmentStrokeWidth,b.strokeStyle=c.segmentStrokeColor,b.stroke());k+=m}},b)},K=function(a,c,b){var e,h,f,d,g,k,j,l,m,t,r,n,p,s=0;g=u;b.font=c.scaleFontStyle+" "+c.scaleFontSize+"px "+c.scaleFontFamily;t=1;for(d=0;d<a.labels.length;d++)e=b.measureText(a.labels[d]).width,t=e>t?e:t;q/a.labels.length<t?(s=45,q/a.labels.length<Math.cos(s)*t?(s=90,g-=t):g-=Math.sin(s)*t):g-=c.scaleFontSize;d=c.scaleFontSize;g=g-5-d;e=Number.MIN_VALUE;h=Number.MAX_VALUE;for(f=0;f<a.datasets.length;f++)for(l=
|
||||
0;l<a.datasets[f].data.length;l++)a.datasets[f].data[l]>e&&(e=a.datasets[f].data[l]),a.datasets[f].data[l]<h&&(h=a.datasets[f].data[l]);f=Math.floor(g/(0.66*d));d=Math.floor(0.5*(g/d));l=c.scaleShowLabels?c.scaleLabel:"";c.scaleOverride?(j={steps:c.scaleSteps,stepValue:c.scaleStepWidth,graphMin:c.scaleStartValue,labels:[]},z(l,j.labels,j.steps,c.scaleStartValue,c.scaleStepWidth)):j=C(g,f,d,e,h,l);k=Math.floor(g/j.steps);d=1;if(c.scaleShowLabels){b.font=c.scaleFontStyle+" "+c.scaleFontSize+"px "+c.scaleFontFamily;
|
||||
for(e=0;e<j.labels.length;e++)h=b.measureText(j.labels[e]).width,d=h>d?h:d;d+=10}r=q-d-t;m=Math.floor(r/(a.labels.length-1));n=q-t/2-r;p=g+c.scaleFontSize/2;x(c,function(){b.lineWidth=c.scaleLineWidth;b.strokeStyle=c.scaleLineColor;b.beginPath();b.moveTo(q-t/2+5,p);b.lineTo(q-t/2-r-5,p);b.stroke();0<s?(b.save(),b.textAlign="right"):b.textAlign="center";b.fillStyle=c.scaleFontColor;for(var d=0;d<a.labels.length;d++)b.save(),0<s?(b.translate(n+d*m,p+c.scaleFontSize),b.rotate(-(s*(Math.PI/180))),b.fillText(a.labels[d],
|
||||
0,0),b.restore()):b.fillText(a.labels[d],n+d*m,p+c.scaleFontSize+3),b.beginPath(),b.moveTo(n+d*m,p+3),c.scaleShowGridLines&&0<d?(b.lineWidth=c.scaleGridLineWidth,b.strokeStyle=c.scaleGridLineColor,b.lineTo(n+d*m,5)):b.lineTo(n+d*m,p+3),b.stroke();b.lineWidth=c.scaleLineWidth;b.strokeStyle=c.scaleLineColor;b.beginPath();b.moveTo(n,p+5);b.lineTo(n,5);b.stroke();b.textAlign="right";b.textBaseline="middle";for(d=0;d<j.steps;d++)b.beginPath(),b.moveTo(n-3,p-(d+1)*k),c.scaleShowGridLines?(b.lineWidth=c.scaleGridLineWidth,
|
||||
b.strokeStyle=c.scaleGridLineColor,b.lineTo(n+r+5,p-(d+1)*k)):b.lineTo(n-0.5,p-(d+1)*k),b.stroke(),c.scaleShowLabels&&b.fillText(j.labels[d],n-8,p-(d+1)*k)},function(d){function e(b,c){return p-d*v(a.datasets[b].data[c],j,k)}for(var f=0;f<a.datasets.length;f++){b.strokeStyle=a.datasets[f].strokeColor;b.lineWidth=c.datasetStrokeWidth;b.beginPath();b.moveTo(n,p-d*v(a.datasets[f].data[0],j,k));for(var g=1;g<a.datasets[f].data.length;g++)c.bezierCurve?b.bezierCurveTo(n+m*(g-0.5),e(f,g-1),n+m*(g-0.5),
|
||||
e(f,g),n+m*g,e(f,g)):b.lineTo(n+m*g,e(f,g));b.stroke();c.datasetFill?(b.lineTo(n+m*(a.datasets[f].data.length-1),p),b.lineTo(n,p),b.closePath(),b.fillStyle=a.datasets[f].fillColor,b.fill()):b.closePath();if(c.pointDot){b.fillStyle=a.datasets[f].pointColor;b.strokeStyle=a.datasets[f].pointStrokeColor;b.lineWidth=c.pointDotStrokeWidth;for(g=0;g<a.datasets[f].data.length;g++)b.beginPath(),b.arc(n+m*g,p-d*v(a.datasets[f].data[g],j,k),c.pointDotRadius,0,2*Math.PI,!0),b.fill(),b.stroke()}}},b)},L=function(a,
|
||||
c,b){var e,h,f,d,g,k,j,l,m,t,r,n,p,s,w=0;g=u;b.font=c.scaleFontStyle+" "+c.scaleFontSize+"px "+c.scaleFontFamily;t=1;for(d=0;d<a.labels.length;d++)e=b.measureText(a.labels[d]).width,t=e>t?e:t;q/a.labels.length<t?(w=45,q/a.labels.length<Math.cos(w)*t?(w=90,g-=t):g-=Math.sin(w)*t):g-=c.scaleFontSize;d=c.scaleFontSize;g=g-5-d;e=Number.MIN_VALUE;h=Number.MAX_VALUE;for(f=0;f<a.datasets.length;f++)for(l=0;l<a.datasets[f].data.length;l++)a.datasets[f].data[l]>e&&(e=a.datasets[f].data[l]),a.datasets[f].data[l]<
|
||||
h&&(h=a.datasets[f].data[l]);f=Math.floor(g/(0.66*d));d=Math.floor(0.5*(g/d));l=c.scaleShowLabels?c.scaleLabel:"";c.scaleOverride?(j={steps:c.scaleSteps,stepValue:c.scaleStepWidth,graphMin:c.scaleStartValue,labels:[]},z(l,j.labels,j.steps,c.scaleStartValue,c.scaleStepWidth)):j=C(g,f,d,e,h,l);k=Math.floor(g/j.steps);d=1;if(c.scaleShowLabels){b.font=c.scaleFontStyle+" "+c.scaleFontSize+"px "+c.scaleFontFamily;for(e=0;e<j.labels.length;e++)h=b.measureText(j.labels[e]).width,d=h>d?h:d;d+=10}r=q-d-t;m=
|
||||
Math.floor(r/a.labels.length);s=(m-2*c.scaleGridLineWidth-2*c.barValueSpacing-(c.barDatasetSpacing*a.datasets.length-1)-(c.barStrokeWidth/2*a.datasets.length-1))/a.datasets.length;n=q-t/2-r;p=g+c.scaleFontSize/2;x(c,function(){b.lineWidth=c.scaleLineWidth;b.strokeStyle=c.scaleLineColor;b.beginPath();b.moveTo(q-t/2+5,p);b.lineTo(q-t/2-r-5,p);b.stroke();0<w?(b.save(),b.textAlign="right"):b.textAlign="center";b.fillStyle=c.scaleFontColor;for(var d=0;d<a.labels.length;d++)b.save(),0<w?(b.translate(n+
|
||||
d*m,p+c.scaleFontSize),b.rotate(-(w*(Math.PI/180))),b.fillText(a.labels[d],0,0),b.restore()):b.fillText(a.labels[d],n+d*m+m/2,p+c.scaleFontSize+3),b.beginPath(),b.moveTo(n+(d+1)*m,p+3),b.lineWidth=c.scaleGridLineWidth,b.strokeStyle=c.scaleGridLineColor,b.lineTo(n+(d+1)*m,5),b.stroke();b.lineWidth=c.scaleLineWidth;b.strokeStyle=c.scaleLineColor;b.beginPath();b.moveTo(n,p+5);b.lineTo(n,5);b.stroke();b.textAlign="right";b.textBaseline="middle";for(d=0;d<j.steps;d++)b.beginPath(),b.moveTo(n-3,p-(d+1)*
|
||||
k),c.scaleShowGridLines?(b.lineWidth=c.scaleGridLineWidth,b.strokeStyle=c.scaleGridLineColor,b.lineTo(n+r+5,p-(d+1)*k)):b.lineTo(n-0.5,p-(d+1)*k),b.stroke(),c.scaleShowLabels&&b.fillText(j.labels[d],n-8,p-(d+1)*k)},function(d){b.lineWidth=c.barStrokeWidth;for(var e=0;e<a.datasets.length;e++){b.fillStyle=a.datasets[e].fillColor;b.strokeStyle=a.datasets[e].strokeColor;for(var f=0;f<a.datasets[e].data.length;f++){var g=n+c.barValueSpacing+m*f+s*e+c.barDatasetSpacing*e+c.barStrokeWidth*e;b.beginPath();
|
||||
b.moveTo(g,p);b.lineTo(g,p-d*v(a.datasets[e].data[f],j,k)+c.barStrokeWidth/2);b.lineTo(g+s,p-d*v(a.datasets[e].data[f],j,k)+c.barStrokeWidth/2);b.lineTo(g+s,p);c.barShowStroke&&b.stroke();b.closePath();b.fill()}}},b)},D=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(a){window.setTimeout(a,1E3/60)},F={}};
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2013 Nick Downie
|
||||
Copyright (c) 2013-2015 Nick Downie
|
||||
|
||||
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:
|
||||
|
||||
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
# Chart.js
|
||||
|
||||
[](https://travis-ci.org/nnnick/Chart.js) [](https://codeclimate.com/github/nnnick/Chart.js)[](https://coveralls.io/r/nnnick/Chart.js?branch=v2.0-dev)
|
||||
|
||||
|
||||
|
||||
*Simple HTML5 Charts using the canvas element* [chartjs.org](http://www.chartjs.org)
|
||||
|
||||
## v2.0 Beta
|
||||
|
||||
Current Release: [2.0.0-beta2](https://github.com/nnnick/Chart.js/releases/tag/2.0.0-beta2)
|
||||
|
||||
The next generation and release of Chart.js has been well under way this year and we are very close to releasing some amazing new features including, but not limited to:
|
||||
- Rewritten, optimized, and unit-tested
|
||||
- New and improved scales (log, time, linear, category, multiple scales)
|
||||
- Improved responsiveness and resizing
|
||||
- Powerful support for adding, removing, changing, and updating data on the fly
|
||||
- Animations on all elements, colors and tooltips
|
||||
- Powerful customization when you need it. Automatic and dynamic when you don't.
|
||||
- Excellent support for modern frameworks and modular build systems.
|
||||
- Even more extensible via new element controllers, combo chart support, and hook system
|
||||
- Bug fixes not addressed in 1.x, and much, much more...
|
||||
|
||||
#####Contributing to 2.0
|
||||
Submit PR's to the v2.0-dev branch.
|
||||
|
||||
#####Building and Testing
|
||||
`gulp build`, `gulp test`
|
||||
|
||||
## v1.x Status: Feature Complete
|
||||
We are now treating v1.x as feature complete. PR's for bug fixes are welcome, but we urge any open PR's for v1.x features to be refactored and resubmitted for v2.x (if the feature has not already been implemented).
|
||||
|
||||
## Documentation
|
||||
|
||||
You can find documentation at [chartjs.org/docs](http://www.chartjs.org/docs/). The markdown files that build the site are available under `/docs`. Please note - in some of the json examples of configuration you might notice some liquid tags - this is just for the generating the site html, please disregard.
|
||||
|
||||
## Bugs, issues and contributing
|
||||
|
||||
Before submitting an issue or a pull request to the project, please take a moment to look over the [contributing guidelines](https://github.com/nnnick/Chart.js/blob/master/CONTRIBUTING.md) first.
|
||||
|
||||
For support using Chart.js, please post questions with the [`chartjs` tag on Stack Overflow](http://stackoverflow.com/questions/tagged/chartjs).
|
||||
|
||||
## License
|
||||
|
||||
Chart.js is available under the [MIT license](http://opensource.org/licenses/MIT).
|
||||
@@ -1,11 +1,13 @@
|
||||
{
|
||||
"name": "Chart.js",
|
||||
"version": "0.2.0",
|
||||
"version": "2.0.0",
|
||||
"description": "Simple HTML5 Charts using the canvas element",
|
||||
"keywords": ["charts"],
|
||||
"homepage": "https://github.com/nnnick/Chart.js",
|
||||
"author": "nnnick",
|
||||
"main": ["Chart.min.js"],
|
||||
"dependencies": {
|
||||
"main": [
|
||||
"dist/Chart.js"
|
||||
],
|
||||
"devDependencies": {
|
||||
"jquery": "~2.1.4"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "nnnick/chartjs",
|
||||
"type": "library",
|
||||
"description": "Simple HTML5 charts using the canvas element.",
|
||||
"keywords": [
|
||||
"chart",
|
||||
"js"
|
||||
],
|
||||
"homepage": "http://www.chartjs.org/",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "NICK DOWNIE",
|
||||
"email": "hello@nickdownie.com"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.3.3"
|
||||
},
|
||||
"minimum-stability": "stable",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"release/2.0": "v2.0-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"node": true,
|
||||
"predef": [ "require", "module" ]
|
||||
}
|
||||
externo
+12749
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
externo
+15
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
externo
+9144
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
externo
+14
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
@@ -0,0 +1,248 @@
|
||||
---
|
||||
title: Getting started
|
||||
anchor: getting-started
|
||||
---
|
||||
|
||||
### Download Chart.js
|
||||
|
||||
To download a zip, go to [Chart.js on Github](https://github.com/nnnick/Chart.js) and choose the version that is right for your application.
|
||||
* [Standard build](https://raw.githubusercontent.com/nnnick/Chart.js/v2.0-dev/dist/Chart.js) (~31kB gzipped)
|
||||
* [Bundled with Moment.js](https://raw.githubusercontent.com/nnnick/Chart.js/v2.0-dev/dist/Chart.bundle.js) (~45kB gzipped)
|
||||
* [CDN Versions](https://cdnjs.com/libraries/Chart.js)
|
||||
|
||||
To install via npm / bower:
|
||||
|
||||
```bash
|
||||
npm install chart.js --save
|
||||
```
|
||||
```bash
|
||||
bower install Chart.js --save
|
||||
```
|
||||
|
||||
### Installation
|
||||
|
||||
To import Chart.js using an old-school script tag:
|
||||
|
||||
```html
|
||||
<script src="Chart.js"></script>
|
||||
<script>
|
||||
var myChart = new Chart({...})
|
||||
</script>
|
||||
```
|
||||
|
||||
To import Chart.js using an awesome module loader:
|
||||
|
||||
```javascript
|
||||
|
||||
// Using CommonJS
|
||||
var Chart = require('src/chart.js')
|
||||
var myChart = new Chart({...})
|
||||
|
||||
// ES6
|
||||
import Chart from 'src/chart.js'
|
||||
let myChart = new Chart({...})
|
||||
|
||||
// Using requirejs
|
||||
require(['path/to/Chartjs'], function(Chart){
|
||||
var myChart = new Chart({...})
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
### Creating a Chart
|
||||
|
||||
To create a chart, we need to instantiate the `Chart` class. To do this, we need to pass in the node, jQuery instance, or 2d context of the canvas of where we want to draw the chart. Here's an example.
|
||||
|
||||
```html
|
||||
<canvas id="myChart" width="400" height="400"></canvas>
|
||||
```
|
||||
|
||||
```javascript
|
||||
// Any of the following formats may be used
|
||||
var ctx = document.getElementById("myChart");
|
||||
var ctx = document.getElementById("myChart").getContext("2d");
|
||||
var ctx = $("#myChart");
|
||||
```
|
||||
|
||||
Once you have the element or context, you're ready to instantiate a pre-defined chart-type or create your own!
|
||||
|
||||
The following example instantiates a bar chart showing the number of votes for different colors and the y-axis starting at 0.
|
||||
|
||||
```html
|
||||
<canvas id="myChart" width="400" height="400"></canvas>
|
||||
<script>
|
||||
var ctx = document.getElementById("myChart");
|
||||
var myChart = new Chart(ctx, {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
|
||||
datasets: [{
|
||||
label: '# of Votes',
|
||||
data: [12, 19, 3, 5, 2, 3]
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
scales: {
|
||||
yAxes: [{
|
||||
ticks: {
|
||||
beginAtZero:true
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
It's that easy to get started using Chart.js! From here you can explore the many options that can help you customise your charts with scales, tooltips, labels, colors, custom actions, and much more.
|
||||
|
||||
### Global chart configuration
|
||||
|
||||
This concept was introduced in Chart.js 1.0 to keep configuration DRY, and allow for changing options globally across chart types, avoiding the need to specify options for each instance, or the default for a particular chart type.
|
||||
|
||||
Chart.js merges configurations and options in a few places with the global defaults using chart type defaults and scales defaults. This way you can be as specific as you want in your individual chart configs, or change the defaults for Chart.js as a whole.
|
||||
|
||||
The global options are defined in `Chart.defaults.global`.
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
responsive | Boolean | true | Resizes when the canvas container does.
|
||||
responsiveAnimationDuration | Number | 0 | Duration in milliseconds it takes to animate to new size after a resize event.
|
||||
maintainAspectRatio | Boolean | true | Maintain the original canvas aspect ratio `(width / height)` when resizing
|
||||
events | Array[String] | `["mousemove", "mouseout", "click", "touchstart", "touchmove", "touchend"]` | Events that the chart should listen to for tooltips and hovering
|
||||
hover |-|-|-
|
||||
*hover*.onHover | Function | null | Called when any of the events fire. Called in the context of the chart and passed an array of active elements (bars, points, etc)
|
||||
*hover*.mode | String | 'single' | Sets which elements hover. Acceptable options are `'single'`, `'label'`, or `'dataset'`. `single` highlights the closest element. `label` highlights elements in all datasets at the same `X` value. `dataset` highlights the closest dataset.
|
||||
*hover*.animationDuration | Number | 400 | Duration in milliseconds it takes to animate hover style changes
|
||||
onClick | Function | null | Called if the event is of type 'mouseup' or 'click'. Called in the context of the chart and passed an array of active elements
|
||||
defaultColor | Color | 'rgba(0,0,0,0.1)' |
|
||||
defaultFontColor | Color | '#666' | Default font color for all text
|
||||
defaultFontFamily | String | "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif" | Default font family for all text
|
||||
defaultFontSize | Number | 12 | Default font size (in px) for text. Does not apply to radialLinear scale point labels
|
||||
defaultFontStyle | String | 'normal' | Default font style. Does not apply to tooltip title or footer. Does not apply to chart title
|
||||
legendCallback | Function | ` function (chart) { }` | Function to generate a legend. Receives the chart object to generate a legend from. Default implementation returns an HTML string.
|
||||
|
||||
The global options for the chart title is defined in `Chart.defaults.global.title`
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
display | Boolean | true | Show the title block
|
||||
position | String | 'top' | Position of the title. 'top' or 'bottom' are allowed
|
||||
fullWidth | Boolean | true | Marks that this box should take the full width of the canvas (pushing down other boxes)
|
||||
fontColor | Color | '#666' | Text color
|
||||
fontFamily | String | 'Helvetica Neue' |
|
||||
fontSize | Number | 12 |
|
||||
fontStyle | String | 'bold' |
|
||||
padding | Number | 10 | Number of pixels to add above and below the title text
|
||||
text | String | '' | Title text
|
||||
|
||||
The global options for the chart legend is defined in `Chart.defaults.global.legend`
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
display | Boolean | true | Is the legend displayed
|
||||
position | String | 'top' | Position of the legend. Options are 'top' or 'bottom'
|
||||
fullWidth | Boolean | true | Marks that this box should take the full width of the canvas (pushing down other boxes)
|
||||
onClick | Function | `function(event, legendItem) {}` | A callback that is called when a click is registered on top of a label item
|
||||
labels |-|-|-
|
||||
*labels*boxWidth | Number | 40 | Width of coloured box
|
||||
*labels*fontSize | Number | 12 | Font size
|
||||
*labels*fontStyle | String | "normal" |
|
||||
*labels*fontColor | Color | "#666" |
|
||||
*labels*fontFamily | String | "Helvetica Neue" |
|
||||
*labels*padding | Number | 10 | Padding between rows of colored boxes
|
||||
*labels*generateLabels: | Function | `function(data) { }` | Generates legend items for each thing in the legend. Default implementation returns the text + styling for the color box. Styles that can be returned are `fillStyle`, `strokeStyle`, `lineCap`, `lineDash`, `lineDashOffset`, `lineWidth`, `lineJoin`. Return a `hidden` attribute to indicate that the label refers to something that is not visible. A strikethrough style will be given to the text in this case.
|
||||
|
||||
The global options for tooltips are defined in `Chart.defaults.global.tooltips`.
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- |:---:| --- | ---
|
||||
enabled | Boolean | true |
|
||||
custom | | null |
|
||||
mode | String | 'single' | Sets which elements appear in the tooltip. Acceptable options are `'single'` or `'label'`. `single` highlights the closest element. `label` highlights elements in all datasets at the same `X` value.
|
||||
backgroundColor | Color | 'rgba(0,0,0,0.8)' | Background color of the tooltip
|
||||
| | |
|
||||
Label | | | There are three labels you can control. `title`, `body`, `footer` the star (\*) represents one of these three. *(i.e. titleFontFamily, footerSpacing)*
|
||||
\*FontFamily | String | "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif" |
|
||||
\*FontSize | Number | 12 |
|
||||
\*FontStyle | String | title - "bold", body - "normal", footer - "bold" |
|
||||
\*Spacing | Number | 2 |
|
||||
\*Color | Color | "#fff" |
|
||||
\*Align | String | "left" | text alignment. See [MDN Canvas Documentation](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/textAlign)
|
||||
titleMarginBottom | Number | 6 | Margin to add on bottom of title section
|
||||
footerMarginTop | Number | 6 | Margin to add before drawing the footer
|
||||
xPadding | Number | 6 | Padding to add on left and right of tooltip
|
||||
yPadding | Number | 6 | Padding to add on top and bottom of tooltip
|
||||
caretSize | Number | 5 | Size, in px, of the tooltip arrow
|
||||
cornerRadius | Number | 6 | Radius of tooltip corner curves
|
||||
multiKeyBackground | Color | "#fff" | Color to draw behind the colored boxes when multiple items are in the tooltip
|
||||
| | |
|
||||
callbacks | - | - | V2.0 introduces callback functions as a replacement for the template engine in v1. The tooltip has the following callbacks for providing text. For all functions, 'this' will be the tooltip object create from the Chart.Tooltip constructor
|
||||
**Callback Functions** | | | All functions are called with the same arguments
|
||||
xLabel | String or Array[Strings] | | This is the xDataValue for each item to be displayed in the tooltip
|
||||
yLabel | String or Array[Strings] | | This is the yDataValue for each item to be displayed in the tooltip
|
||||
index | Number | | Data index.
|
||||
data | Object | | Data object passed to chart.
|
||||
`return`| String or Array[Strings] | | All functions must return either a string or an array of strings. Arrays of strings are treated as multiple lines of text.
|
||||
| | |
|
||||
*callbacks*.beforeTitle | Function | none | Text to render before the title
|
||||
*callbacks*.title | Function | `function(tooltipItems, data) { //Pick first xLabel }` | Text to render as the title
|
||||
*callbacks*.afterTitle | Function | none | Text to render after the ttiel
|
||||
*callbacks*.beforeBody | Function | none | Text to render before the body section
|
||||
*callbacks*.beforeLabel | Function | none | Text to render before an individual label
|
||||
*callbacks*.label | Function | `function(tooltipItem, data) { // Returns "datasetLabel: tooltipItem.yLabel" }` | Text to render as label
|
||||
*callbacks*.afterLabel | Function | none | Text to render after an individual label
|
||||
*callbacks*.afterBody | Function | none | Text to render after the body section
|
||||
*callbacks*.beforeFooter | Function | none | Text to render before the footer section
|
||||
*callbacks*.footer | Function | none | Text to render as the footer
|
||||
*callbacks*.afterFooter | Function | none | Text to render after the footer section
|
||||
|
||||
The global options for animations are defined in `Chart.defaults.global.animation`.
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- |:---:| --- | ---
|
||||
duration | Number | 1000 | The number of milliseconds an animation takes.
|
||||
easing | String | "easeOutQuart" | Easing function to use.
|
||||
onProgress | Function | none | Callback called on each step of an animation. Passed a single argument, an object, containing the chart instance and an object with details of the animation.
|
||||
onComplete | Function | none | Callback called at the end of an animation. Passed the same arguments as `onProgress`
|
||||
|
||||
The global options for elements are defined in `Chart.defaults.global.elements`.
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- |:---:| --- | ---
|
||||
arc | - | - | -
|
||||
*arc*.backgroundColor | Color | `Chart.defaults.global.defaultColor` | Default fill color for arcs
|
||||
*arc*.borderColor | Color | "#fff" | Default stroke color for arcs
|
||||
*arc*.borderWidth | Number | 2 | Default stroke width for arcs
|
||||
line | - | - | -
|
||||
*line*.tension | Number | 0.4 | Default bezier curve tension. Set to `0` for no bezier curves.
|
||||
*line*.backgroundColor | Color | `Chart.defaults.global.defaultColor` | Default line fill color
|
||||
*line*.borderWidth | Number | 3 | Default line stroke width
|
||||
*line*.borderColor | Color | `Chart.defaults.global.defaultColor` | Default line stroke color
|
||||
*line*.borderCapStyle | String | 'butt' | Default line cap style. See [MDN](https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D/lineCap)
|
||||
*line*.borderDash | Array | `[]` | Default line dash. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash)
|
||||
*line*.borderDashOffset | Number | 0.0 | Default line dash offset. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineDashOffset)
|
||||
*line*.borderJoinStyle | String | 'miter' | Default line join style. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineJoin)
|
||||
*line*.fill | Boolean | true |
|
||||
point | - | - | -
|
||||
*point*.radius | Number | 3 | Default point radius
|
||||
*point*.pointStyle | String | 'circle' | Default point style
|
||||
*point*.backgroundColor | Color | `Chart.defaults.global.defaultColor` | Default point fill color
|
||||
*point*.borderWidth | Number | 1 | Default point stroke width
|
||||
*point*.borderColor | Color | `Chart.defaults.global.defaultColor` | Default point stroke color
|
||||
*point*.hitRadius | Number | 1 | Extra radius added to point radius for hit detection
|
||||
*point*.hoverRadius | Number | 4 | Default point radius when hovered
|
||||
*point*.hoverBorderWidth | Number | 1 | Default stroke width when hovered
|
||||
rectangle | - | - | -
|
||||
*rectangle*.backgroundColor | Color | `Chart.defaults.global.defaultColor` | Default bar fill color
|
||||
*rectangle*.borderWidth | Number | 0 | Default bar stroke width
|
||||
*rectangle*.borderColor | Color | `Chart.defaults.global.defaultColor` | Default bar stroke color
|
||||
*rectangle*.borderSkipped | String | 'bottom' | Default skipped (excluded) border for rectangle. Can be one of `bottom`, `left`, `top`, `right`
|
||||
|
||||
If for example, you wanted all charts created to be responsive, and resize when the browser window does, the following setting can be changed:
|
||||
|
||||
```javascript
|
||||
Chart.defaults.global.responsive = true;
|
||||
```
|
||||
|
||||
Now, every time we create a chart, `options.responsive` will be `true`.
|
||||
@@ -0,0 +1,299 @@
|
||||
---
|
||||
title: Scales
|
||||
anchor: scales
|
||||
---
|
||||
|
||||
Scales in v2.0 of Chart.js are significantly more powerful, but also different than those of v1.0.
|
||||
* Multiple x & y axes are now supported.
|
||||
* A built-in label auto-skip feature now detects would-be overlapping ticks and labels and removes every nth label to keep things displaying normally.
|
||||
* Scale titles are now supported
|
||||
* New scale types can be extended without writing an entirely new chart type
|
||||
|
||||
Every scale extends a core scale class with the following options:
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- |:---:| --- | ---
|
||||
type | String | Chart specific. | Type of scale being employed. Custom scales can be created and registered with a string key. Options: ["category"](#scales-category-scale), ["linear"](#scales-linear-scale), ["logarithmic"](#scales-logarithmic-scale), ["time"](#scales-time-scale), ["radialLinear"](#scales-radial-linear-scale)
|
||||
display | Boolean | true | If true, show the scale including gridlines, ticks, and labels. Overrides *gridLines.display*, *scaleLabel.display*, and *ticks.display*.
|
||||
beforeUpdate | Function | undefined | Callback called before the update process starts. Passed a single argument, the scale instance.
|
||||
beforeSetDimensions | Function | undefined | Callback that runs before dimensions are set. Passed a single argument, the scale instance.
|
||||
afterSetDimensions | Function | undefined | Callback that runs after dimensions are set. Passed a single argument, the scale instance.
|
||||
beforeDataLimits | Function | undefined | Callback that runs before data limits are determined. Passed a single argument, the scale instance.
|
||||
afterDataLimits | Function | undefined | Callback that runs after data limits are determined. Passed a single argument, the scale instance.
|
||||
beforeBuildTicks | Function | undefined | Callback that runs before ticks are created. Passed a single argument, the scale instance.
|
||||
afterBuildTicks | Function | undefined | Callback that runs after ticks are created. Useful for filtering ticks. Passed a single argument, the scale instance.
|
||||
beforeTickToLabelConversion | Function | undefined | Callback that runs before ticks are converted into strings. Passed a single argument, the scale instance.
|
||||
afterTickToLabelConversion | Function | undefined | Callback that runs after ticks are converted into strings. Passed a single argument, the scale instance.
|
||||
beforeCalculateTickRotation | Function | undefined | Callback that runs before tick rotation is determined. Passed a single argument, the scale instance.
|
||||
afterCalculateTickRotation | Function | undefined | Callback that runs after tick rotation is determined. Passed a single argument, the scale instance.
|
||||
beforeFit | Function | undefined | Callback that runs before the scale fits to the canvas. Passed a single argument, the scale instance.
|
||||
afterFit | Function | undefined | Callback that runs after the scale fits to the canvas. Passed a single argument, the scale instance.
|
||||
afterUpdate | Function | undefined | Callback that runs at the end of the update process. Passed a single argument, the scale instance.
|
||||
**gridLines** | Array | - | Options for the grid lines that run perpendicular to the axis.
|
||||
*gridLines*.display | Boolean | true |
|
||||
*gridLines*.color | Color | "rgba(0, 0, 0, 0.1)" | Color of the grid lines.
|
||||
*gridLines*.lineWidth | Number | 1 | Stroke width of grid lines
|
||||
*gridLines*.drawOnChartArea | Boolean | true | If true, draw lines on the chart area inside the axis lines. This is useful when there are multiple axes and you need to control which grid lines are drawn
|
||||
*gridLines*.drawTicks | Boolean | true | If true, draw lines beside the ticks in the axis area beside the chart.
|
||||
*gridLines*.zeroLineWidth | Number | 1 | Stroke width of the grid line for the first index (index 0).
|
||||
*gridLines*.zeroLineColor | Color | "rgba(0, 0, 0, 0.25)" | Stroke color of the grid line for the first index (index 0).
|
||||
*gridLines*.offsetGridLines | Boolean | false | If true, offset labels from grid lines.
|
||||
**scaleLabel** | Array | | Title for the entire axis.
|
||||
*scaleLabel*.display | Boolean | false |
|
||||
*scaleLabel*.labelString | String | "" | The text for the title. (i.e. "# of People", "Response Choices")
|
||||
*scaleLabel*.fontColor | Color | "#666" | Font color for the scale title.
|
||||
*scaleLabel*.fontFamily| String | "Helvetica Neue" | Font family for the scale title, follows CSS font-family options.
|
||||
*scaleLabel*.fontSize | Number | 12 | Font size for the scale title.
|
||||
*scaleLabel*.fontStyle | String | "normal" | Font style for the scale title, follows CSS font-style options (i.e. normal, italic, oblique, initial, inherit).
|
||||
**ticks** | Array | | Settings for the labels that run along the axis.
|
||||
*ticks*.beginAtZero | Boolean | false | If true the scale will be begin at 0, if false the ticks will begin at your smallest data value.
|
||||
*ticks*.fontColor | Color | "#666" | Font color for the tick labels.
|
||||
*ticks*.fontFamily | String | "Helvetica Neue" | Font family for the tick labels, follows CSS font-family options.
|
||||
*ticks*.fontSize | Number | 12 | Font size for the tick labels.
|
||||
*ticks*.fontStyle | String | "normal" | Font style for the tick labels, follows CSS font-style options (i.e. normal, italic, oblique, initial, inherit).
|
||||
*ticks*.maxRotation | Number | 90 | Maximum rotation for tick labels when rotating to condense labels. Note: Rotation doesn't occur until necessary. *Note: Only applicable to horizontal scales.*
|
||||
*ticks*.minRotation | Number | 20 | *currently not-implemented* Minimum rotation for tick labels when condensing is necessary. *Note: Only applicable to horizontal scales.*
|
||||
*ticks*.maxTicksLimit | Number | 11 | Maximum number of ticks and gridlines to show. If not defined, it will limit to 11 ticks but will show all gridlines.
|
||||
*ticks*.padding | Number | 10 | Padding between the tick label and the axis. *Note: Only applicable to horizontal scales.*
|
||||
*ticks*.mirror | Boolean | false | Flips tick labels around axis, displaying the labels inside the chart instead of outside. *Note: Only applicable to vertical scales.*
|
||||
*ticks*.reverse | Boolean | false | Reverses order of tick labels.
|
||||
*ticks*.display | Boolean | true | If true, show the ticks.
|
||||
*ticks*.suggestedMin | Number | - | User defined minimum number for the scale, overrides minimum value *except for if* it is higher than the minimum value.
|
||||
*ticks*.suggestedMax | Number | - | User defined maximum number for the scale, overrides maximum value *except for if* it is lower than the maximum value.
|
||||
*ticks*.min | Number | - | User defined minimum number for the scale, overrides minimum value.
|
||||
*ticks*.max | Number | - | User defined minimum number for the scale, overrides maximum value
|
||||
*ticks*.autoSkip | Boolean | true | If true, automatically calculates how many labels that can be shown and hides labels accordingly. Turn it off to show all labels no matter what
|
||||
*ticks*.callback | Function | `function(value) { return '' + value; } ` | Returns the string representation of the tick value as it should be displayed on the chart.
|
||||
|
||||
The `callback` method may be used for advanced tick customization. The following callback would display every label in scientific notation
|
||||
```javascript
|
||||
{
|
||||
scales: {
|
||||
xAxes: [{
|
||||
ticks: {
|
||||
// Return an empty string to draw the tick line but hide the tick label
|
||||
// Return `null` or `undefined` to hide the tick line entirely
|
||||
userCallback: function(value, index, values) {
|
||||
return value.toExponential();
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Category Scale
|
||||
The category scale will be familiar to those who have used v1.0. Labels are drawn in from the labels array included in the chart data.
|
||||
|
||||
The category scale extends the core scale class with the following tick template:
|
||||
|
||||
```javascript
|
||||
{
|
||||
position: "bottom",
|
||||
}
|
||||
```
|
||||
|
||||
The `ticks.min` and `ticks.max` attributes may be used with the category scale. Unlike other scales, the value of these attributes must simply be something that can be found in the `labels` array of the data object.
|
||||
|
||||
### Linear Scale
|
||||
The linear scale can be used to display numerical data. It can be placed on either the x or y axis. The scatter chart type automatically configures a line chart to use one of these scales for the x axis.
|
||||
|
||||
The linear scale extends the core scale class with the following tick template:
|
||||
|
||||
```javascript
|
||||
{
|
||||
position: "left",
|
||||
ticks: {
|
||||
callback: function(tickValue, index, ticks) {
|
||||
var delta = ticks[1] - ticks[0];
|
||||
|
||||
// If we have a number like 2.5 as the delta, figure out how many decimal places we need
|
||||
if (Math.abs(delta) > 1) {
|
||||
if (tickValue !== Math.floor(tickValue)) {
|
||||
// not an integer
|
||||
delta = tickValue - Math.floor(tickValue);
|
||||
}
|
||||
}
|
||||
|
||||
var logDelta = helpers.log10(Math.abs(delta));
|
||||
var tickString = '';
|
||||
|
||||
if (tickValue !== 0) {
|
||||
var numDecimal = -1 * Math.floor(logDelta);
|
||||
numDecimal = Math.max(Math.min(numDecimal, 20), 0); // toFixed has a max of 20 decimal places
|
||||
tickString = tickValue.toFixed(numDecimal);
|
||||
} else {
|
||||
tickString = '0'; // never show decimal places for 0
|
||||
}
|
||||
|
||||
return tickString;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
It also provides additional configuration options:
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- |:---:| --- | ---
|
||||
*ticks*.stepSize | Number | - | User defined fixed step size for the scale. If set, the scale ticks will be enumerated by multiple of stepSize, having one tick per increment. If not set, the ticks are labeled automatically using the nice numbers algorithm.
|
||||
|
||||
### Logarithmic Scale
|
||||
The logarithmic scale is used to display logarithmic data of course. It can be placed on either the x or y axis.
|
||||
|
||||
The log scale extends the core scale class with the following tick template:
|
||||
|
||||
```javascript
|
||||
{
|
||||
position: "left",
|
||||
ticks: {
|
||||
callback: function(value) {
|
||||
var remain = value / (Math.pow(10, Math.floor(Chart.helpers.log10(value))));
|
||||
|
||||
if (remain === 1 || remain === 2 || remain === 5) {
|
||||
return value.toExponential();
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Time Scale
|
||||
The time scale is used to display times and dates. It can be placed on the x axis. When building its ticks, it will automatically calculate the most comfortable unit base on the size of the scale.
|
||||
|
||||
The time scale extends the core scale class with the following tick template:
|
||||
|
||||
```javascript
|
||||
{
|
||||
position: "bottom",
|
||||
time: {
|
||||
// string/callback - By default, date objects are expected. You may use a pattern string from http://momentjs.com/docs/#/parsing/string-format/ to parse a time string format, or use a callback function that is passed the label, and must return a moment() instance.
|
||||
parser: false,
|
||||
// string - By default, unit will automatically be detected. Override with 'week', 'month', 'year', etc. (see supported time measurements)
|
||||
unit: false,
|
||||
|
||||
// Number - The number of steps of the above unit between ticks
|
||||
unitStepSize: 1
|
||||
|
||||
// string - By default, no rounding is applied. To round, set to a supported time unit eg. 'week', 'month', 'year', etc.
|
||||
round: false,
|
||||
|
||||
// Moment js for each of the units. Replaces `displayFormat`
|
||||
// To override, use a pattern string from http://momentjs.com/docs/#/displaying/format/
|
||||
displayFormats: {
|
||||
'millisecond': 'SSS [ms]',
|
||||
'second': 'h:mm:ss a', // 11:20:01 AM
|
||||
'minute': 'h:mm:ss a', // 11:20:01 AM
|
||||
'hour': 'MMM D, hA', // Sept 4, 5PM
|
||||
'day': 'll', // Sep 4 2015
|
||||
'week': 'll', // Week 46, or maybe "[W]WW - YYYY" ?
|
||||
'month': 'MMM YYYY', // Sept 2015
|
||||
'quarter': '[Q]Q - YYYY', // Q3
|
||||
'year': 'YYYY', // 2015
|
||||
},
|
||||
// Sets the display format used in tooltip generation
|
||||
tooltipFormat: ''
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
The following time measurements are supported:
|
||||
|
||||
```javascript
|
||||
{
|
||||
'millisecond': {
|
||||
display: 'SSS [ms]', // 002 ms
|
||||
maxStep: 1000,
|
||||
},
|
||||
'second': {
|
||||
display: 'h:mm:ss a', // 11:20:01 AM
|
||||
maxStep: 60,
|
||||
},
|
||||
'minute': {
|
||||
display: 'h:mm:ss a', // 11:20:01 AM
|
||||
maxStep: 60,
|
||||
},
|
||||
'hour': {
|
||||
display: 'MMM D, hA', // Sept 4, 5PM
|
||||
maxStep: 24,
|
||||
},
|
||||
'day': {
|
||||
display: 'll', // Sep 4 2015
|
||||
maxStep: 7,
|
||||
},
|
||||
'week': {
|
||||
display: 'll', // Week 46, or maybe "[W]WW - YYYY" ?
|
||||
maxStep: 4.3333,
|
||||
},
|
||||
'month': {
|
||||
display: 'MMM YYYY', // Sept 2015
|
||||
maxStep: 12,
|
||||
},
|
||||
'quarter': {
|
||||
display: '[Q]Q - YYYY', // Q3
|
||||
maxStep: 4,
|
||||
},
|
||||
'year': {
|
||||
display: 'YYYY', // 2015
|
||||
maxStep: false,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Radial Linear Scale
|
||||
The radial linear scale is used specifically for the radar chart type.
|
||||
|
||||
The radial linear scale extends the core scale class with the following tick template:
|
||||
|
||||
```javascript
|
||||
{
|
||||
animate: true,
|
||||
lineArc: false,
|
||||
position: "chartArea",
|
||||
|
||||
angleLines: {
|
||||
display: true,
|
||||
color: "rgba(0, 0, 0, 0.1)",
|
||||
lineWidth: 1
|
||||
},
|
||||
|
||||
// label settings
|
||||
ticks: {
|
||||
//Boolean - Show a backdrop to the scale label
|
||||
showLabelBackdrop: true,
|
||||
|
||||
//String - The colour of the label backdrop
|
||||
backdropColor: "rgba(255,255,255,0.75)",
|
||||
|
||||
//Number - The backdrop padding above & below the label in pixels
|
||||
backdropPaddingY: 2,
|
||||
|
||||
//Number - The backdrop padding to the side of the label in pixels
|
||||
backdropPaddingX: 2,
|
||||
|
||||
//Number - Limit the maximum number of ticks and gridlines
|
||||
maxTicksLimit: 11,
|
||||
},
|
||||
|
||||
pointLabels: {
|
||||
//String - Point label font declaration
|
||||
fontFamily: "'Arial'",
|
||||
|
||||
//String - Point label font weight
|
||||
fontStyle: "normal",
|
||||
|
||||
//Number - Point label font size in pixels
|
||||
fontSize: 10,
|
||||
|
||||
//String - Point label font colour
|
||||
fontColor: "#666",
|
||||
|
||||
//Function - Used to determine point labels to show in scale
|
||||
callback: function(pointLabel) {
|
||||
return pointLabel;
|
||||
}
|
||||
},
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,161 @@
|
||||
---
|
||||
title: Line Chart
|
||||
anchor: line-chart
|
||||
---
|
||||
### Introduction
|
||||
A line chart is a way of plotting data points on a line.
|
||||
|
||||
Often, it is used to show trend data, and the comparison of two data sets.
|
||||
|
||||
<div class="canvas-holder">
|
||||
<canvas width="250" height="125"></canvas>
|
||||
</div>
|
||||
|
||||
### Example usage
|
||||
```javascript
|
||||
var myLineChart = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: data,
|
||||
options: options
|
||||
});
|
||||
```
|
||||
|
||||
Alternatively a line chart can be created using syntax similar to the v1.0 syntax
|
||||
```javascript
|
||||
var myLineChart = Chart.Line(ctx, {
|
||||
data: data,
|
||||
options: options
|
||||
});
|
||||
```
|
||||
### Data structure
|
||||
|
||||
```javascript
|
||||
var data = {
|
||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
||||
datasets: [
|
||||
{
|
||||
label: "My First dataset",
|
||||
|
||||
// Boolean - if true fill the area under the line
|
||||
fill: false,
|
||||
|
||||
// String - the color to fill the area under the line with if fill is true
|
||||
backgroundColor: "rgba(220,220,220,0.2)",
|
||||
|
||||
// The properties below allow an array to be specified to change the value of the item at the given index
|
||||
|
||||
// String or array - Line color
|
||||
borderColor: "rgba(220,220,220,1)",
|
||||
|
||||
// String - cap style of the line. See https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineCap
|
||||
borderCapStyle: 'butt',
|
||||
|
||||
// Array - Length and spacing of dashes. See https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash
|
||||
borderDash: [],
|
||||
|
||||
// Number - Offset for line dashes. See https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineDashOffset
|
||||
borderDashOffset: 0.0,
|
||||
|
||||
// String - line join style. See https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineJoin
|
||||
borderJoinStyle: 'miter',
|
||||
|
||||
// String or array - Point stroke color
|
||||
pointBorderColor: "rgba(220,220,220,1)",
|
||||
|
||||
// String or array - Point fill color
|
||||
pointBackgroundColor: "#fff",
|
||||
|
||||
// Number or array - Stroke width of point border
|
||||
pointBorderWidth: 1,
|
||||
|
||||
// Number or array - Radius of point when hovered
|
||||
pointHoverRadius: 5,
|
||||
|
||||
// String or array - point background color when hovered
|
||||
pointHoverBackgroundColor: "rgba(220,220,220,1)",
|
||||
|
||||
// Point border color when hovered
|
||||
pointHoverBorderColor: "rgba(220,220,220,1)",
|
||||
|
||||
// Number or array - border width of point when hovered
|
||||
pointHoverBorderWidth: 2,
|
||||
|
||||
// Tension - bezier curve tension of the line. Set to 0 to draw straight Wlines connecting points
|
||||
tension: 0.1,
|
||||
|
||||
// Number - the pixel size of the point shape. Can be set to 0 to not render a circle over the point
|
||||
radius: 1,
|
||||
|
||||
// The actual data
|
||||
data: [65, 59, 80, 81, 56, 55, 40],
|
||||
|
||||
// String - If specified, binds the dataset to a certain y-axis. If not specified, the first y-axis is used. First id is y-axis-0
|
||||
yAxisID: "y-axis-0",
|
||||
},
|
||||
{
|
||||
label: "My Second dataset",
|
||||
fill: false,
|
||||
backgroundColor: "rgba(220,220,220,0.2)",
|
||||
borderColor: "rgba(220,220,220,1)",
|
||||
pointBorderColor: "rgba(220,220,220,1)",
|
||||
pointBackgroundColor: "#fff",
|
||||
pointBorderWidth: 1,
|
||||
pointHoverRadius: 5,
|
||||
pointHoverBackgroundColor: "rgba(220,220,220,1)",
|
||||
pointHoverBorderColor: "rgba(220,220,220,1)",
|
||||
pointHoverBorderWidth: 2,
|
||||
data: [28, 48, 40, 19, 86, 27, 90]
|
||||
}
|
||||
]
|
||||
};
|
||||
```
|
||||
|
||||
The line chart requires an array of labels. This labels are shown on the X axis. There must be one label for each data point. More labels than datapoints are allowed, in which case the line ends at the last data point.
|
||||
The data for line charts is broken up into an array of datasets. Each dataset has a colour for the fill, a colour for the line and colours for the points and strokes of the points. These colours are strings just like CSS. You can use RGBA, RGB, HEX or HSL notation.
|
||||
|
||||
The label key on each dataset is optional, and can be used when generating a scale for the chart.
|
||||
|
||||
### Chart options
|
||||
|
||||
These are the customisation options specific to Line charts. These options are merged with the [global chart configuration options](#getting-started-global-chart-configuration), and form the options of the chart.
|
||||
|
||||
The default options for line chart are defined in `Chart.defaults.Line`.
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
showLines | Boolean | true | If false, the lines between points are not drawn
|
||||
stacked | Boolean | false | If true, lines stack on top of each other along the y axis.
|
||||
*hover*.mode | String | "label" | Label's hover mode. "label" is used since the x axis displays data by the index in the dataset.
|
||||
elements | - | - | -
|
||||
*elements*.point | - | - | -
|
||||
*elements.point*.radius | Number | `3` | Defines the size of the Point shape. Can be set to zero to skip rendering a point.
|
||||
scales | - | - | -
|
||||
*scales*.xAxes | Array | `[{type:"category","id":"x-axis-1"}]` | Defines all of the x axes used in the chart. See the [scale documentation](#getting-started-scales) for details on the available options.
|
||||
*Options for xAxes* | | |
|
||||
type | String | "category" | As defined in ["Category"](#scales-category-scale).
|
||||
id | String | "x-axis-1" | Id of the axis so that data can bind to it.
|
||||
| | |
|
||||
*scales*.yAxes | Array | `[{type:"linear","id":"y-axis-1"}]` | Defines all of the x axes used in the chart. See the [scale documentation](#getting-started-scales) for details on the available options.
|
||||
*Options for yAxes* | | |
|
||||
type | String | "linear" | As defined in ["Linear"](#scales-linear-scale).
|
||||
id | String | "y-axis-1" | Id of the axis so that data can bind to it.
|
||||
|
||||
You can override these for your `Chart` instance by passing a member `options` into the `Line` method.
|
||||
|
||||
For example, we could have a line chart display without an x axis by doing the following. The config merge is smart enough to handle arrays so that you do not need to specify all axis settings to change one thing.
|
||||
|
||||
```javascript
|
||||
new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: data,
|
||||
options: {
|
||||
xAxes: [{
|
||||
display: false
|
||||
}]
|
||||
}
|
||||
});
|
||||
// This will create a chart with all of the default options, merged from the global config,
|
||||
// and the Line chart defaults, but this particular instance will have the x axis not displaying.
|
||||
```
|
||||
|
||||
We can also change these defaults values for each Line type that is created, this object is available at `Chart.defaults.line`.
|
||||
@@ -0,0 +1,155 @@
|
||||
---
|
||||
title: Bar Chart
|
||||
anchor: bar-chart
|
||||
---
|
||||
|
||||
### Introduction
|
||||
A bar chart is a way of showing data as bars.
|
||||
|
||||
It is sometimes used to show trend data, and the comparison of multiple data sets side by side.
|
||||
|
||||
<div class="canvas-holder">
|
||||
<canvas width="250" height="125"></canvas>
|
||||
</div>
|
||||
|
||||
### Example usage
|
||||
```javascript
|
||||
var myBarChart = new Chart(ctx, {
|
||||
type: 'bar',
|
||||
data: data,
|
||||
options: options
|
||||
});
|
||||
```
|
||||
|
||||
### Data structure
|
||||
|
||||
```javascript
|
||||
var data = {
|
||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
||||
datasets: [
|
||||
{
|
||||
label: "My First dataset",
|
||||
|
||||
// The properties below allow an array to be specified to change the value of the item at the given index
|
||||
// String or array - the bar color
|
||||
backgroundColor: "rgba(220,220,220,0.2)",
|
||||
|
||||
// String or array - bar stroke color
|
||||
borderColor: "rgba(220,220,220,1)",
|
||||
|
||||
// Number or array - bar border width
|
||||
borderWidth: 1,
|
||||
|
||||
// String or array - fill color when hovered
|
||||
hoverBackgroundColor: "rgba(220,220,220,0.2)",
|
||||
|
||||
// String or array - border color when hovered
|
||||
hoverBorderColor: "rgba(220,220,220,1)",
|
||||
|
||||
// The actual data
|
||||
data: [65, 59, 80, 81, 56, 55, 40],
|
||||
|
||||
// String - If specified, binds the dataset to a certain y-axis. If not specified, the first y-axis is used.
|
||||
yAxisID: "y-axis-0",
|
||||
},
|
||||
{
|
||||
label: "My Second dataset",
|
||||
backgroundColor: "rgba(220,220,220,0.2)",
|
||||
borderColor: "rgba(220,220,220,1)",
|
||||
borderWidth: 1,
|
||||
hoverBackgroundColor: "rgba(220,220,220,0.2)",
|
||||
hoverBorderColor: "rgba(220,220,220,1)",
|
||||
data: [28, 48, 40, 19, 86, 27, 90]
|
||||
}
|
||||
]
|
||||
};
|
||||
```
|
||||
The bar chart has the a very similar data structure to the line chart, and has an array of datasets, each with colours and an array of data. Again, colours are in CSS format.
|
||||
We have an array of labels too for display. In the example, we are showing the same data as the previous line chart example.
|
||||
|
||||
The label key on each dataset is optional, and can be used when generating a scale for the chart.
|
||||
|
||||
### Chart Options
|
||||
|
||||
These are the customisation options specific to Bar charts. These options are merged with the [global chart configuration options](#getting-started-global-chart-configuration), and form the options of the chart.
|
||||
|
||||
The default options for bar chart are defined in `Chart.defaults.Bar`.
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- |:---:| --- | ---
|
||||
stacked | Boolean | false |
|
||||
*hover*.mode | String | "label" | Label's hover mode. "label" is used since the x axis displays data by the index in the dataset.
|
||||
scales | Array | - | -
|
||||
*scales*.xAxes | Array | | The bar chart officially supports only 1 x-axis but uses an array to keep the API consistent. Use a scatter chart if you need multiple x axes.
|
||||
*Options for xAxes* | | |
|
||||
type | String | "Category" | As defined in [Scales](#scales-category-scale).
|
||||
display | Boolean | true | If true, show the scale.
|
||||
position | String | "bottom" | Position of the scale. Options are "top" and "bottom" for dataset scales.
|
||||
id | String | "x-axis-1" | Id of the axis so that data can bind to it
|
||||
categoryPercentage | Number | 0.8 | Percent (0-1) of the available width (the space between the gridlines for small datasets) for each data-point to use for the bars. [Read More](#bar-chart-barpercentage-vs-categorypercentage)
|
||||
barPercentage | Number | 0.9 | Percent (0-1) of the available width each bar should be within the category percentage. 1.0 will take the whole category width and put the bars right next to each other. [Read More](#bar-chart-barpercentage-vs-categorypercentage)
|
||||
gridLines | Array | [See Scales](#scales) |
|
||||
*gridLines*.offsetGridLines | Boolean | true | If true, the bars for a particular data point fall between the grid lines. If false, the grid line will go right down the middle of the bars.
|
||||
scaleLabel | Array | [See Scales](#scales) |
|
||||
ticks | Array | [See Scales](#scales) |
|
||||
| | |
|
||||
*scales*.yAxes | Array | `[{ type: "linear" }]` |
|
||||
*Options for xAxes* | | |
|
||||
type | String | "linear" | As defined in [Scales](#scales-linear-scale).
|
||||
display | Boolean | true | If true, show the scale.
|
||||
position | String | "left" | Position of the scale. Options are "left" and "right" for dataset scales.
|
||||
id | String | "y-axis-1" | Id of the axis so that data can bind to it.
|
||||
gridLines | Array | [See Scales](#scales) |
|
||||
scaleLabel | Array | [See Scales](#scales) |
|
||||
ticks | Array | [See Scales](#scales) |
|
||||
|
||||
You can override these for your `Chart` instance by passing a second argument into the `Bar` method as an object with the keys you want to override.
|
||||
|
||||
For example, we could have a bar chart without a stroke on each bar by doing the following:
|
||||
|
||||
```javascript
|
||||
new Chart(ctx, {
|
||||
type: "bar",
|
||||
data: data,
|
||||
options: {
|
||||
scales: {
|
||||
xAxes: [{
|
||||
stacked: true
|
||||
}],
|
||||
yAxes: [{
|
||||
stacked: true
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
// This will create a chart with all of the default options, merged from the global config,
|
||||
// and the Bar chart defaults but this particular instance will have `stacked` set to true
|
||||
// for both x and y axes.
|
||||
```
|
||||
|
||||
We can also change these defaults values for each Bar type that is created, this object is available at `Chart.defaults.Bar`.
|
||||
|
||||
#### barPercentage vs categoryPercentage
|
||||
|
||||
The following shows the relationship between the bar percentage option and the category percentage option.
|
||||
|
||||
```text
|
||||
// categoryPercentage: 1.0
|
||||
// barPercentage: 1.0
|
||||
Bar: | 1.0 | 1.0 |
|
||||
Category: | 1.0 |
|
||||
Sample: |===========|
|
||||
|
||||
// categoryPercentage: 1.0
|
||||
// barPercentage: 0.5
|
||||
Bar: |.5| |.5|
|
||||
Category: | 1.0 |
|
||||
Sample: |==============|
|
||||
|
||||
// categoryPercentage: 0.5
|
||||
// barPercentage: 1.0
|
||||
Bar: |1.||1.|
|
||||
Category: | .5 |
|
||||
Sample: |==============|
|
||||
```
|
||||
@@ -0,0 +1,93 @@
|
||||
---
|
||||
title: Radar Chart
|
||||
anchor: radar-chart
|
||||
---
|
||||
|
||||
### Introduction
|
||||
A radar chart is a way of showing multiple data points and the variation between them.
|
||||
|
||||
They are often useful for comparing the points of two or more different data sets.
|
||||
|
||||
<div class="canvas-holder">
|
||||
<canvas width="250" height="125"></canvas>
|
||||
</div>
|
||||
|
||||
### Example usage
|
||||
|
||||
```javascript
|
||||
var myRadarChart = new Chart(ctx, {
|
||||
type: 'radar',
|
||||
data: data,
|
||||
options: options
|
||||
});
|
||||
```
|
||||
|
||||
### Data structure
|
||||
```javascript
|
||||
var data = {
|
||||
labels: ["Eating", "Drinking", "Sleeping", "Designing", "Coding", "Cycling", "Running"],
|
||||
datasets: [
|
||||
{
|
||||
label: "My First dataset",
|
||||
backgroundColor: "rgba(220,220,220,0.2)",
|
||||
borderColor: "rgba(220,220,220,1)",
|
||||
pointBackgroundColor: "rgba(220,220,220,1)",
|
||||
pointBorderColor: "#fff",
|
||||
pointHoverBackgroundColor: "#fff",
|
||||
pointHoverBorderColor: "rgba(220,220,220,1)",
|
||||
data: [65, 59, 90, 81, 56, 55, 40]
|
||||
},
|
||||
{
|
||||
label: "My Second dataset",
|
||||
backgroundColor: "rgba(151,187,205,0.2)",
|
||||
borderColor: "rgba(151,187,205,1)",
|
||||
pointBackgroundColor: "rgba(151,187,205,1)",
|
||||
pointBorderColor: "#fff",
|
||||
pointHoverBackgroundColor: "#fff",
|
||||
pointHoverBorderColor: "rgba(151,187,205,1)",
|
||||
data: [28, 48, 40, 19, 96, 27, 100]
|
||||
}
|
||||
]
|
||||
};
|
||||
```
|
||||
For a radar chart, to provide context of what each point means, we include an array of strings that show around each point in the chart.
|
||||
For the radar chart data, we have an array of datasets. Each of these is an object, with a fill colour, a stroke colour, a colour for the fill of each point, and a colour for the stroke of each point. We also have an array of data values.
|
||||
The label key on each dataset is optional, and can be used when generating a scale for the chart.
|
||||
|
||||
|
||||
### Chart Options
|
||||
|
||||
These are the customisation options specific to Radar charts. These options are merged with the [global chart configuration options](#getting-started-global-chart-configuration), and form the options of the chart.
|
||||
|
||||
The default options for radar chart are defined in `Chart.defaults.radar`.
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
scale | Array | [See Scales](#scales) and [Defaults for Radial Linear Scale](#scales-radial-linear-scale) | Options for the one scale used on the chart. Use this to style the ticks, labels, and grid lines.
|
||||
*scale*.type | String |"radialLinear" | As defined in ["Radial Linear"](#scales-radial-linear-scale).
|
||||
*elements*.line | Array | | Options for all line elements used on the chart, as defined in the global elements, duplicated here to show Radar chart specific defaults.
|
||||
*elements.line*.tension | Number | 0 | Tension exhibited by lines when calculating splineCurve. Setting to 0 creates straight lines.
|
||||
|
||||
You can override these for your `Chart` instance by passing a second argument into the `Radar` method as an object with the keys you want to override.
|
||||
|
||||
For example, we could have a radar chart without a point for each on piece of data by doing the following:
|
||||
|
||||
```javascript
|
||||
new Chart(ctx, {
|
||||
type: "radar",
|
||||
data: data,
|
||||
options: {
|
||||
scale: {
|
||||
reverse: true,
|
||||
ticks: {
|
||||
beginAtZero: true
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
// This will create a chart with all of the default options, merged from the global config,
|
||||
// and the Radar chart defaults but this particular instance's scale will be reversed as
|
||||
// well as the ticks beginning at zero.
|
||||
```
|
||||
|
||||
We can also change these defaults values for each Radar type that is created, this object is available at `Chart.defaults.radar`.
|
||||
@@ -0,0 +1,91 @@
|
||||
---
|
||||
title: Polar Area Chart
|
||||
anchor: polar-area-chart
|
||||
---
|
||||
### Introduction
|
||||
Polar area charts are similar to pie charts, but each segment has the same angle - the radius of the segment differs depending on the value.
|
||||
|
||||
This type of chart is often useful when we want to show a comparison data similar to a pie chart, but also show a scale of values for context.
|
||||
|
||||
<div class="canvas-holder">
|
||||
<canvas width="250" height="125"></canvas>
|
||||
</div>
|
||||
|
||||
### Example usage
|
||||
|
||||
```javascript
|
||||
new Chart(ctx, {
|
||||
data: data,
|
||||
type: 'polarArea',
|
||||
options: options
|
||||
});
|
||||
```
|
||||
|
||||
### Data structure
|
||||
|
||||
```javascript
|
||||
var data = {
|
||||
datasets: [{
|
||||
data: [
|
||||
10,
|
||||
32,
|
||||
53,
|
||||
14,
|
||||
22,
|
||||
],
|
||||
backgroundColor: [
|
||||
"#F7464A",
|
||||
"#46BFBD",
|
||||
"#FDB45C",
|
||||
"#949FB1",
|
||||
"#4D5360",
|
||||
],
|
||||
label: 'My dataset' // for legend
|
||||
}],
|
||||
labels: [
|
||||
"Red",
|
||||
"Green",
|
||||
"Yellow",
|
||||
"Grey",
|
||||
"Dark Grey"
|
||||
]
|
||||
};
|
||||
```
|
||||
As you can see, for the chart data you pass in an array of objects, with a value and a colour. The value attribute should be a number, while the color attribute should be a string. Similar to CSS, for this string you can use HEX notation, RGB, RGBA or HSL.
|
||||
|
||||
### Chart options
|
||||
|
||||
These are the customisation options specific to Polar Area charts. These options are merged with the [global chart configuration options](#getting-started-global-chart-configuration), and form the options of the chart.
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
scale | Array | [See Scales](#scales) and [Defaults for Radial Linear Scale](#getting-started-radial-linear-scale) | Options for the one scale used on the chart. Use this to style the ticks, labels, and grid.
|
||||
*scale*.type | String |"radialLinear" | As defined in ["Radial Linear"](#scales-radial-linear-scale).
|
||||
*scale*.lineArc | Boolean | true | When true, lines are circular.
|
||||
animateRotate | Boolean |true | If true, will animate the rotation of the chart.
|
||||
animateScale | Boolean | true | If true, will animate scaling the chart.
|
||||
*legend*.*labels*.generateLabels | Function | `function(data) {} ` | Returns labels for each the legend
|
||||
*legend*.onClick | Function | function(event, legendItem) {} ` | Handles clicking an individual legend item
|
||||
legendCallback | Function | `function(chart) ` | Generates the HTML legend via calls to `generateLegend`
|
||||
|
||||
You can override these for your `Chart` instance by passing a second argument into the `PolarArea` method as an object with the keys you want to override.
|
||||
|
||||
For example, we could have a polar area chart with a black stroke on each segment like so:
|
||||
|
||||
```javascript
|
||||
new Chart(ctx, {
|
||||
data: data,
|
||||
type: "polarArea",
|
||||
options: {
|
||||
elements: {
|
||||
arc: {
|
||||
borderColor: "#000000"
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
// This will create a chart with all of the default options, merged from the global config,
|
||||
// and the PolarArea chart defaults but this particular instance will have `elements.arc.borderColor` set to `"#000000"`.
|
||||
```
|
||||
|
||||
We can also change these defaults values for each PolarArea type that is created, this object is available at `Chart.defaults.polarArea`.
|
||||
@@ -0,0 +1,99 @@
|
||||
---
|
||||
title: Pie & Doughnut Charts
|
||||
anchor: doughnut-pie-chart
|
||||
---
|
||||
### Introduction
|
||||
Pie and doughnut charts are probably the most commonly used chart there are. They are divided into segments, the arc of each segment shows the proportional value of each piece of data.
|
||||
|
||||
They are excellent at showing the relational proportions between data.
|
||||
|
||||
Pie and doughnut charts are effectively the same class in Chart.js, but have one different default value - their `percentageInnerCutout`. This equates what percentage of the inner should be cut out. This defaults to `0` for pie charts, and `50` for doughnuts.
|
||||
|
||||
They are also registered under two aliases in the `Chart` core. Other than their different default value, and different alias, they are exactly the same.
|
||||
|
||||
<div class="canvas-holder half">
|
||||
<canvas width="250" height="125"></canvas>
|
||||
</div>
|
||||
|
||||
<div class="canvas-holder half">
|
||||
<canvas width="250" height="125"></canvas>
|
||||
</div>
|
||||
|
||||
|
||||
### Example usage
|
||||
|
||||
```javascript
|
||||
// For a pie chart
|
||||
var myPieChart = new Chart(ctx[0],{
|
||||
type:'pie',
|
||||
data: data,
|
||||
options: options
|
||||
});
|
||||
|
||||
// And for a doughnut chart
|
||||
var myDoughnutChart = new Chart(ctx[1], {
|
||||
type:'doughnut',
|
||||
data: data,
|
||||
options: options
|
||||
});
|
||||
```
|
||||
|
||||
### Data structure
|
||||
|
||||
```javascript
|
||||
var data = {
|
||||
labels: [
|
||||
"Red",
|
||||
"Green",
|
||||
"Yellow"
|
||||
],
|
||||
datasets: [
|
||||
{
|
||||
data: [300, 50, 100],
|
||||
backgroundColor: [
|
||||
"#F7464A",
|
||||
"#46BFBD",
|
||||
"#FDB45C"
|
||||
],
|
||||
hoverBackgroundColor: [
|
||||
"#FF5A5E",
|
||||
"#5AD3D1",
|
||||
"#FFC870"
|
||||
]
|
||||
}]
|
||||
};
|
||||
```
|
||||
|
||||
For a pie chart, you must pass in an array of objects with a value and an optional color property. The value attribute should be a number, Chart.js will total all of the numbers and calculate the relative proportion of each. The color attribute should be a string. Similar to CSS, for this string you can use HEX notation, RGB, RGBA or HSL.
|
||||
|
||||
### Chart options
|
||||
|
||||
These are the customisation options specific to Pie & Doughnut charts. These options are merged with the [global chart configuration options](#getting-started-global-chart-configuration), and form the options of the chart.
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
cutoutPercentage | Number | 50 - for doughnut, 0 - for pie | The percentage of the chart that is cut out of the middle.
|
||||
scale | Array | [See Scales](#scales) and [Defaults for Radial Linear Scale](#getting-started-radial-linear-scale) | Options for the one scale used on the chart. Use this to style the ticks, labels, and grid.
|
||||
*scale*.type | String |"radialLinear" | As defined in ["Radial Linear"](#scales-radial-linear-scale).
|
||||
*scale*.lineArc | Boolean | true | When true, lines are arced compared to straight when false.
|
||||
*animation*.animateRotate | Boolean |true | If true, will animate the rotation of the chart.
|
||||
*animation*.animateScale | Boolean | false | If true, will animate scaling the Doughnut from the centre.
|
||||
*legend*.*labels*.generateLabels | Function | `function(data) {} ` | Returns labels for each the legend
|
||||
*legend*.onClick | Function | function(event, legendItem) {} ` | Handles clicking an individual legend item
|
||||
|
||||
You can override these for your `Chart` instance by passing a second argument into the `Doughnut` method as an object with the keys you want to override.
|
||||
|
||||
For example, we could have a doughnut chart that animates by scaling out from the centre like so:
|
||||
|
||||
```javascript
|
||||
new Chart(ctx,{
|
||||
type:"doughnut",
|
||||
animation:{
|
||||
animateScale:true
|
||||
}
|
||||
});
|
||||
// This will create a chart with all of the default options, merged from the global config,
|
||||
// and the Doughnut chart defaults but this particular instance will have `animateScale` set to `true`.
|
||||
```
|
||||
|
||||
We can also change these default values for each Doughnut type that is created, this object is available at `Chart.defaults.doughnut`. Pie charts also have a clone of these defaults available to change at `Chart.defaults.pie`, with the only difference being `percentageInnerCutout` being set to 0.
|
||||
@@ -0,0 +1,386 @@
|
||||
---
|
||||
title: Advanced usage
|
||||
anchor: advanced-usage
|
||||
---
|
||||
|
||||
|
||||
### Prototype methods
|
||||
|
||||
For each chart, there are a set of global prototype methods on the shared `ChartType` which you may find useful. These are available on all charts created with Chart.js, but for the examples, let's use a line chart we've made.
|
||||
|
||||
```javascript
|
||||
// For example:
|
||||
var myLineChart = new Chart(ctx, config);
|
||||
```
|
||||
|
||||
#### .destroy()
|
||||
|
||||
Use this to destroy any chart instances that are created. This will clean up any references stored to the chart object within Chart.js, along with any associated event listeners attached by Chart.js.
|
||||
This must be called before the canvas is reused for a new chart.
|
||||
|
||||
```javascript
|
||||
// Destroys a specific chart instance
|
||||
myLineChart.destroy();
|
||||
```
|
||||
|
||||
#### .update(duration, lazy)
|
||||
|
||||
Triggers an update of the chart. This can be safely called after replacing the entire data object. This will update all scales, legends, and then re-render the chart.
|
||||
|
||||
```javascript
|
||||
// duration is the time for the animation of the redraw in miliseconds
|
||||
// lazy is a boolean. if true, the animation can be interupted by other animations
|
||||
myLineChart.data.datasets[0].data[2] = 50; // Would update the first dataset's value of 'March' to be 50
|
||||
myLineChart.update(); // Calling update now animates the position of March from 90 to 50.
|
||||
```
|
||||
|
||||
#### .render(duration, lazy)
|
||||
|
||||
Triggers a redraw of all chart elements. Note, this does not update elements for new data. Use `.update()` in that case.
|
||||
|
||||
```javascript
|
||||
// duration is the time for the animation of the redraw in miliseconds
|
||||
// lazy is a boolean. if true, the animation can be interupted by other animations
|
||||
myLineChart.render(duration, lazy);
|
||||
```
|
||||
|
||||
#### .stop()
|
||||
|
||||
Use this to stop any current animation loop. This will pause the chart during any current animation frame. Call `.render()` to re-animate.
|
||||
|
||||
```javascript
|
||||
// Stops the charts animation loop at its current frame
|
||||
myLineChart.stop();
|
||||
// => returns 'this' for chainability
|
||||
```
|
||||
|
||||
#### .resize()
|
||||
|
||||
Use this to manually resize the canvas element. This is run each time the canvas container is resized, but you can call this method manually if you change the size of the canvas nodes container element.
|
||||
|
||||
```javascript
|
||||
// Resizes & redraws to fill its container element
|
||||
myLineChart.resize();
|
||||
// => returns 'this' for chainability
|
||||
```
|
||||
|
||||
#### .clear()
|
||||
|
||||
Will clear the chart canvas. Used extensively internally between animation frames, but you might find it useful.
|
||||
|
||||
```javascript
|
||||
// Will clear the canvas that myLineChart is drawn on
|
||||
myLineChart.clear();
|
||||
// => returns 'this' for chainability
|
||||
```
|
||||
|
||||
#### .toBase64Image()
|
||||
|
||||
This returns a base 64 encoded string of the chart in it's current state.
|
||||
|
||||
```javascript
|
||||
myLineChart.toBase64Image();
|
||||
// => returns png data url of the image on the canvas
|
||||
```
|
||||
|
||||
#### .generateLegend()
|
||||
|
||||
Returns an HTML string of a legend for that chart. The legend is generated from the `legendCallback` in the options.
|
||||
|
||||
```javascript
|
||||
myLineChart.generateLegend();
|
||||
// => returns HTML string of a legend for this chart
|
||||
```
|
||||
|
||||
#### .getElementAtEvent(e)
|
||||
|
||||
Calling `getElementAtEvent(event)` on your Chart instance passing an argument of an event, or jQuery event, will return the single element at the event position. If there are multiple items within range, only the first is returned
|
||||
|
||||
```javascript
|
||||
myLineChart.getElementAtEvent(e);
|
||||
// => returns the first element at the event point.
|
||||
```
|
||||
|
||||
#### .getElementsAtEvent(e)
|
||||
|
||||
Looks for the element under the event point, then returns all elements at the same data index. This is used internally for 'label' mode highlighting.
|
||||
|
||||
Calling `getElementsAtEvent(event)` on your Chart instance passing an argument of an event, or jQuery event, will return the point elements that are at that the same position of that event.
|
||||
|
||||
```javascript
|
||||
canvas.onclick = function(evt){
|
||||
var activePoints = myLineChart.getElementsAtEvent(evt);
|
||||
// => activePoints is an array of points on the canvas that are at the same position as the click event.
|
||||
};
|
||||
```
|
||||
|
||||
This functionality may be useful for implementing DOM based tooltips, or triggering custom behaviour in your application.
|
||||
|
||||
#### .getDatasetAtEvent(e)
|
||||
|
||||
Looks for the element under the event point, then returns all elements from that dataset. This is used internally for 'dataset' mode highlighting
|
||||
|
||||
```javascript
|
||||
myLineChart.getDatasetAtEvent(e);
|
||||
// => returns an array of elements
|
||||
```
|
||||
|
||||
### External Tooltips
|
||||
|
||||
You can enable custom tooltips in the global or chart configuration like so:
|
||||
|
||||
```javascript
|
||||
var myPieChart = new Chart(ctx, {
|
||||
type: 'pie',
|
||||
data: data,
|
||||
options: {
|
||||
tooltips: {
|
||||
custom: function(tooltip) {
|
||||
// tooltip will be false if tooltip is not visible or should be hidden
|
||||
if (!tooltip) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, tooltip will be an object with all tooltip properties like:
|
||||
|
||||
// tooltip.caretHeight
|
||||
// tooltip.caretPadding
|
||||
// tooltip.chart
|
||||
// tooltip.cornerRadius
|
||||
// tooltip.fillColor
|
||||
// tooltip.font...
|
||||
// tooltip.text
|
||||
// tooltip.x
|
||||
// tooltip.y
|
||||
// etc...
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
See `sample/line-customTooltips.html` for examples on how to get started.
|
||||
|
||||
### Writing new scale types
|
||||
|
||||
Starting with Chart.js 2.0 scales can be individually extended. Scales should always derive from Chart.Scale.
|
||||
|
||||
```javascript
|
||||
var MyScale = Chart.Scale.extend({
|
||||
/* extensions ... */
|
||||
});
|
||||
|
||||
// MyScale is now derived from Chart.Scale
|
||||
```
|
||||
|
||||
Once you have created your scale class, you need to register it with the global chart object so that it can be used. A default config for the scale may be provided when registering the constructor. The first parameter to the register function is a string key that is used later to identify which scale type to use for a chart.
|
||||
|
||||
```javascript
|
||||
Chart.scaleService.registerScaleType('myScale', MyScale, defaultConfigObject);
|
||||
```
|
||||
|
||||
To use the new scale, simply pass in the string key to the config when creating a chart.
|
||||
|
||||
```javascript
|
||||
var lineChart = new Chart(ctx, {
|
||||
data: data,
|
||||
type: 'line',
|
||||
options: {
|
||||
scales: {
|
||||
yAxes: [{
|
||||
type: 'myScale' // this is the same key that was passed to the registerScaleType function
|
||||
}]
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
#### Scale Properties
|
||||
|
||||
Scale instances are given the following properties during the fitting process.
|
||||
|
||||
```javascript
|
||||
{
|
||||
left: Number, // left edge of the scale bounding box
|
||||
right: Number, // right edge of the bounding box'
|
||||
top: Number,
|
||||
bottom: Number,
|
||||
width: Number, // the same as right - left
|
||||
height: Number, // the same as bottom - top
|
||||
|
||||
// Margin on each side. Like css, this is outside the bounding box.
|
||||
margins: {
|
||||
left: Number,
|
||||
right: Number,
|
||||
top: Number,
|
||||
bottom: Number,
|
||||
},
|
||||
|
||||
// Amount of padding on the inside of the bounding box (like CSS)
|
||||
paddingLeft: Number,
|
||||
paddingRight: Number,
|
||||
paddingTop: Number,
|
||||
paddingBottom: Number,
|
||||
}
|
||||
```
|
||||
|
||||
#### Scale Interface
|
||||
To work with Chart.js, custom scale types must implement the following interface.
|
||||
|
||||
```javascript
|
||||
{
|
||||
// Determines the data limits. Should set this.min and this.max to be the data max/min
|
||||
determineDataLimits: function() {},
|
||||
|
||||
// Generate tick marks. this.chart is the chart instance. The data object can be accessed as this.chart.data
|
||||
// buildTicks() should create a ticks array on the scale instance, if you intend to use any of the implementations from the base class
|
||||
buildTicks: function() {},
|
||||
|
||||
// Get the value to show for the data at the given index of the the given dataset, ie this.chart.data.datasets[datasetIndex].data[index]
|
||||
getLabelForIndex: function(index, datasetIndex) {},
|
||||
|
||||
// Get the pixel (x coordinate for horizontal scale, y coordinate for vertical scales) for a given value
|
||||
// @param index: index into the ticks array
|
||||
// @param includeOffset: if true, get the pixel halway between the given tick and the next
|
||||
getPixelForTick: function(index, includeOffset) {},
|
||||
|
||||
// Get the pixel (x coordinate for horizontal scale, y coordinate for vertical scales) for a given value
|
||||
// @param value : the value to get the pixel for
|
||||
// @param index : index into the data array of the value
|
||||
// @param datasetIndex : index of the dataset the value comes from
|
||||
// @param includeOffset : if true, get the pixel halway between the given tick and the next
|
||||
getPixelForValue: function(value, index, datasetIndex, includeOffset) {}
|
||||
}
|
||||
```
|
||||
|
||||
Optionally, the following methods may also be overwritten, but an implementation is already provided by the `Chart.Scale` base class.
|
||||
|
||||
```javascript
|
||||
// Transform the ticks array of the scale instance into strings. The default implementation simply calls this.options.ticks.callback(numericalTick, index, ticks);
|
||||
convertTicksToLabels: function() {},
|
||||
|
||||
// Determine how much the labels will rotate by. The default implementation will only rotate labels if the scale is horizontal.
|
||||
calculateTickRotation: function() {},
|
||||
|
||||
// Fits the scale into the canvas.
|
||||
// this.maxWidth and this.maxHeight will tell you the maximum dimensions the scale instance can be. Scales should endeavour to be as efficient as possible with canvas space.
|
||||
// this.margins is the amount of space you have on either side of your scale that you may expand in to. This is used already for calculating the best label rotation
|
||||
// You must set this.minSize to be the size of your scale. It must be an object containing 2 properties: width and height.
|
||||
// You must set this.width to be the width and this.height to be the height of the scale
|
||||
fit: function() {},
|
||||
|
||||
// Draws the scale onto the canvas. this.(left|right|top|bottom) will have been populated to tell you the area on the canvas to draw in
|
||||
// @param chartArea : an object containing four properties: left, right, top, bottom. This is the rectangle that lines, bars, etc will be drawn in. It may be used, for example, to draw grid lines.
|
||||
draw: function(chartArea) {},
|
||||
```
|
||||
|
||||
The Core.Scale base class also has some utility functions that you may find useful.
|
||||
```javascript
|
||||
{
|
||||
// Returns true if the scale instance is horizontal
|
||||
isHorizontal: function() {},
|
||||
|
||||
// Get the correct value from the value from this.chart.data.datasets[x].data[]
|
||||
// If dataValue is an object, returns .x or .y depending on the return of isHorizontal()
|
||||
// If the value is undefined, returns NaN
|
||||
// Otherwise returns the value.
|
||||
// Note that in all cases, the returned value is not guaranteed to be a Number
|
||||
getRightValue: function(dataValue) {},
|
||||
}
|
||||
```
|
||||
|
||||
### Writing new chart types
|
||||
|
||||
Chart.js 2.0 introduces the concept of controllers for each dataset. Like scales, new controllers can be written as needed.
|
||||
|
||||
```javascript
|
||||
Chart.controllers.MyType = Chart.DatasetController.extend({
|
||||
|
||||
});
|
||||
|
||||
|
||||
// Now we can create a new instance of our chart, using the Chart.js API
|
||||
new Chart(ctx, {
|
||||
// this is the string the constructor was registered at, ie Chart.controllers.MyType
|
||||
type: 'MyType',
|
||||
data: data,
|
||||
options: options
|
||||
});
|
||||
```
|
||||
|
||||
#### Dataset Controller Interface
|
||||
|
||||
Dataset controllers must implement the following interface.
|
||||
|
||||
```javascript
|
||||
{
|
||||
// Create elements for each piece of data in the dataset. Store elements in an array on the dataset as dataset.metaData
|
||||
addElements: function() {},
|
||||
|
||||
// Create a single element for the data at the given index and reset its state
|
||||
addElementAndReset: function(index) {},
|
||||
|
||||
// Draw the representation of the dataset
|
||||
// @param ease : if specified, this number represents how far to transition elements. See the implementation of draw() in any of the provided controllers to see how this should be used
|
||||
draw: function(ease) {},
|
||||
|
||||
// Remove hover styling from the given element
|
||||
removeHoverStyle: function(element) {},
|
||||
|
||||
// Add hover styling to the given element
|
||||
setHoverStyle: function(element) {},
|
||||
|
||||
// Update the elements in response to new data
|
||||
// @param reset : if true, put the elements into a reset state so they can animate to their final values
|
||||
update: function(reset) {},
|
||||
}
|
||||
```
|
||||
|
||||
The following methods may optionally be overridden by derived dataset controllers
|
||||
```javascript
|
||||
{
|
||||
// Initializes the controller
|
||||
initialize: function(chart, datasetIndex) {},
|
||||
|
||||
// Ensures that the dataset represented by this controller is linked to a scale. Overridden to helpers.noop in the polar area and doughnut controllers as these
|
||||
// chart types using a single scale
|
||||
linkScales: function() {},
|
||||
|
||||
// Called by the main chart controller when an update is triggered. The default implementation handles the number of data points changing and creating elements appropriately.
|
||||
buildOrUpdateElements: function() {}
|
||||
}
|
||||
```
|
||||
|
||||
### Extending existing chart types
|
||||
|
||||
Extending or replacing an existing controller type is easy. Simply replace the constructor for one of the built in types with your own.
|
||||
|
||||
The built in controller types are:
|
||||
* `Chart.controllers.line`
|
||||
* `Chart.controllers.bar`
|
||||
* `Chart.controllers.radar`
|
||||
* `Chart.controllers.doughnut`
|
||||
* `Chart.controllers.polarArea`
|
||||
* `Chart.controllers.bubble`
|
||||
|
||||
#### Bar Controller
|
||||
The bar controller has a special property that you should be aware of. To correctly calculate the width of a bar, the controller must determine the number of datasets that map to bars. To do this, the bar controller attaches a property `bar` to the dataset during initialization. If you are creating a replacement or updated bar controller, you should do the same. This will ensure that charts with regular bars and your new derived bars will work seamlessly.
|
||||
|
||||
### Building Chart.js
|
||||
|
||||
Chart.js uses <a href="http://gulpjs.com/" target="_blank">gulp</a> to build the library into a single JavaScript file.
|
||||
|
||||
Firstly, we need to ensure development dependencies are installed. With node and npm installed, after cloning the Chart.js repo to a local directory, and navigating to that directory in the command line, we can run the following:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npm install -g gulp
|
||||
```
|
||||
|
||||
This will install the local development dependencies for Chart.js, along with a CLI for the JavaScript task runner <a href="http://gulpjs.com/" target="_blank">gulp</a>.
|
||||
|
||||
Now, we can run the `gulp build` task.
|
||||
|
||||
```bash
|
||||
gulp build
|
||||
```
|
||||
@@ -0,0 +1,42 @@
|
||||
---
|
||||
title: Notes
|
||||
anchor: notes
|
||||
---
|
||||
|
||||
### Browser support
|
||||
Browser support for the canvas element is available in all modern & major mobile browsers <a href="http://caniuse.com/canvas" target="_blank">(caniuse.com/canvas)</a>.
|
||||
|
||||
For IE8 & below, I would recommend using the polyfill ExplorerCanvas - available at <a href="https://code.google.com/p/explorercanvas/" target="_blank">https://code.google.com/p/explorercanvas/</a>. It falls back to Internet explorer's format VML when canvas support is not available. Example use:
|
||||
|
||||
```html
|
||||
<head>
|
||||
<!--[if lte IE 8]>
|
||||
<script src="excanvas.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
```
|
||||
|
||||
Usually I would recommend feature detection to choose whether or not to load a polyfill, rather than IE conditional comments, however in this case, VML is a Microsoft proprietary format, so it will only work in IE.
|
||||
|
||||
Some important points to note in my experience using ExplorerCanvas as a fallback.
|
||||
|
||||
- Initialise charts on load rather than DOMContentReady when using the library, as sometimes a race condition will occur, and it will result in an error when trying to get the 2d context of a canvas.
|
||||
- New VML DOM elements are being created for each animation frame and there is no hardware acceleration. As a result animation is usually slow and jerky, with flashing text. It is a good idea to dynamically turn off animation based on canvas support. I recommend using the excellent <a href="http://modernizr.com/" target="_blank">Modernizr</a> to do this.
|
||||
- When declaring fonts, the library explorercanvas requires the font name to be in single quotes inside the string. For example, instead of your scaleFontFamily property being simply "Arial", explorercanvas support, use "'Arial'" instead. Chart.js does this for default values.
|
||||
|
||||
### Bugs & issues
|
||||
|
||||
Please report these on the GitHub page - at <a href="https://github.com/nnnick/Chart.js" target="_blank">github.com/nnnick/Chart.js</a>. If you could include a link to a simple <a href="http://jsbin.com/" target="_blank">jsbin</a> or similar to demonstrate the issue, that'd be really helpful.
|
||||
|
||||
|
||||
### Contributing
|
||||
New contributions to the library are welcome, just a couple of guidelines:
|
||||
|
||||
- Tabs for indentation, not spaces please.
|
||||
- Please ensure you're changing the individual files in `/src`, not the concatenated output in the `Chart.js` file in the root of the repo.
|
||||
- Please check that your code will pass `jshint` code standards, `gulp jshint` will run this for you.
|
||||
- Please keep pull requests concise, and document new functionality in the relevant `.md` file.
|
||||
- Consider whether your changes are useful for all users, or if creating a Chart.js extension would be more appropriate.
|
||||
|
||||
### License
|
||||
Chart.js is open source and available under the <a href="http://opensource.org/licenses/MIT" target="_blank">MIT license</a>.
|
||||
externo
-1443
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
@@ -1,766 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Chart.js Documentation</title>
|
||||
<link href="styles.css" rel="stylesheet">
|
||||
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
|
||||
<script src="prettify.js"></script>
|
||||
<script src="Chart.js"></script>
|
||||
<script type="text/javascript" src="//use.typekit.net/puc1imu.js"></script>
|
||||
<script type="text/javascript">try{Typekit.load();}catch(e){}</script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="redBorder"></div>
|
||||
<div class="greenBorder"></div>
|
||||
<div class="yellowBorder"></div>
|
||||
<div id="wrapper">
|
||||
<nav>
|
||||
<dl>
|
||||
</dl>
|
||||
</nav>
|
||||
|
||||
<div id="contentWrapper">
|
||||
<h1 id="mainHeader">Chart.js Documentation</h1>
|
||||
<h2 id="introText">Everything you need to know to create great looking charts using Chart.js</h2>
|
||||
<article id="gettingStarted">
|
||||
<h1>Getting started</h1>
|
||||
<h2>Include Chart.js</h2>
|
||||
<p>First we need to include the Chart.js library on the page. The library occupies a global variable of <code>Chart</code>.</p>
|
||||
<pre data-type="html"><code><script src="Chart.js"></script></code></pre>
|
||||
<h2>Creating a chart</h2>
|
||||
<p>To create a chart, we need to instantiate the Chart class. To do this, we need to pass in the 2d context of where we want to draw the chart. Here's an example.</p>
|
||||
<pre data-type="html"><code><canvas id="myChart" width="400" height="400"></canvas></code></pre>
|
||||
<pre data-type="javascript"><code>//Get the context of the canvas element we want to select
|
||||
var ctx = document.getElementById("myChart").getContext("2d");
|
||||
var myNewChart = new Chart(ctx).PolarArea(data);</code></pre>
|
||||
<p>We can also get the context of our canvas with jQuery. To do this, we need to get the DOM node out of the jQuery collection, and call the <code>getContext("2d")</code> method on that.</p>
|
||||
<pre data-type="javascript"><code>//Get context with jQuery - using jQuery's .get() method.
|
||||
var ctx = $("#myChart").get(0).getContext("2d");
|
||||
//This will get the first returned node in the jQuery collection.
|
||||
var myNewChart = new Chart(ctx);</code></pre>
|
||||
<p>After we've instantiated the Chart class on the canvas we want to draw on, Chart.js will handle the scaling for retina displays.</p>
|
||||
<p>With the Chart class set up, we can go on to create one of the charts Chart.js has available. In the example below, we would be drawing a Polar area chart.</p>
|
||||
<pre data-type="javascript"><code>new Chart(ctx).PolarArea(data,options);</code></pre>
|
||||
<p>We call a method of the name of the chart we want to create. We pass in the data for that chart type, and the options for that chart as parameters. Chart.js will merge the options you pass in with the default options for that chart type.</p>
|
||||
</article>
|
||||
|
||||
<article id="lineChart">
|
||||
<h1>Line chart</h1>
|
||||
<h2>Introduction</h2>
|
||||
<p>A line chart is a way of plotting data points on a line.</p>
|
||||
<p>Often, it is used to show trend data, and the comparison of two data sets.</p>
|
||||
<h2>Example usage</h2>
|
||||
<canvas id="line" data-type="Line" width="600" height="400"></canvas>
|
||||
<pre data-type="javascript"><code>new Chart(ctx).Line(data,options);</code></pre>
|
||||
<h2>Data structure</h2>
|
||||
<pre data-type="javascript"><code data-for="line">var data = {
|
||||
labels : ["January","February","March","April","May","June","July"],
|
||||
datasets : [
|
||||
{
|
||||
fillColor : "rgba(220,220,220,0.5)",
|
||||
strokeColor : "rgba(220,220,220,1)",
|
||||
pointColor : "rgba(220,220,220,1)",
|
||||
pointStrokeColor : "#fff",
|
||||
data : [65,59,90,81,56,55,40]
|
||||
},
|
||||
{
|
||||
fillColor : "rgba(151,187,205,0.5)",
|
||||
strokeColor : "rgba(151,187,205,1)",
|
||||
pointColor : "rgba(151,187,205,1)",
|
||||
pointStrokeColor : "#fff",
|
||||
data : [28,48,40,19,96,27,100]
|
||||
}
|
||||
]
|
||||
}</code></pre>
|
||||
<p>The line chart requires an array of labels for each of the data points. This is show on the X axis.</p>
|
||||
<p>The data for line charts is broken up into an array of datasets. Each dataset has a colour for the fill, a colour for the line and colours for the points and strokes of the points. These colours are strings just like CSS. You can use RGBA, RGB, HEX or HSL notation.</p>
|
||||
|
||||
<h2>Chart options</h2>
|
||||
<pre data-type="javascript"><code>Line.defaults = {
|
||||
|
||||
//Boolean - If we show the scale above the chart data
|
||||
scaleOverlay : false,
|
||||
|
||||
//Boolean - If we want to override with a hard coded scale
|
||||
scaleOverride : false,
|
||||
|
||||
//** Required if scaleOverride is true **
|
||||
//Number - The number of steps in a hard coded scale
|
||||
scaleSteps : null,
|
||||
//Number - The value jump in the hard coded scale
|
||||
scaleStepWidth : null,
|
||||
//Number - The scale starting value
|
||||
scaleStartValue : null,
|
||||
|
||||
//String - Colour of the scale line
|
||||
scaleLineColor : "rgba(0,0,0,.1)",
|
||||
|
||||
//Number - Pixel width of the scale line
|
||||
scaleLineWidth : 1,
|
||||
|
||||
//Boolean - Whether to show labels on the scale
|
||||
scaleShowLabels : true,
|
||||
|
||||
//Interpolated JS string - can access value
|
||||
scaleLabel : "<%=value%>",
|
||||
|
||||
//String - Scale label font declaration for the scale label
|
||||
scaleFontFamily : "'Arial'",
|
||||
|
||||
//Number - Scale label font size in pixels
|
||||
scaleFontSize : 12,
|
||||
|
||||
//String - Scale label font weight style
|
||||
scaleFontStyle : "normal",
|
||||
|
||||
//String - Scale label font colour
|
||||
scaleFontColor : "#666",
|
||||
|
||||
///Boolean - Whether grid lines are shown across the chart
|
||||
scaleShowGridLines : true,
|
||||
|
||||
//String - Colour of the grid lines
|
||||
scaleGridLineColor : "rgba(0,0,0,.05)",
|
||||
|
||||
//Number - Width of the grid lines
|
||||
scaleGridLineWidth : 1,
|
||||
|
||||
//Boolean - Whether the line is curved between points
|
||||
bezierCurve : true,
|
||||
|
||||
//Boolean - Whether to show a dot for each point
|
||||
pointDot : true,
|
||||
|
||||
//Number - Radius of each point dot in pixels
|
||||
pointDotRadius : 3,
|
||||
|
||||
//Number - Pixel width of point dot stroke
|
||||
pointDotStrokeWidth : 1,
|
||||
|
||||
//Boolean - Whether to show a stroke for datasets
|
||||
datasetStroke : true,
|
||||
|
||||
//Number - Pixel width of dataset stroke
|
||||
datasetStrokeWidth : 2,
|
||||
|
||||
//Boolean - Whether to fill the dataset with a colour
|
||||
datasetFill : true,
|
||||
|
||||
//Boolean - Whether to animate the chart
|
||||
animation : true,
|
||||
|
||||
//Number - Number of animation steps
|
||||
animationSteps : 60,
|
||||
|
||||
//String - Animation easing effect
|
||||
animationEasing : "easeOutQuart",
|
||||
|
||||
//Function - Fires when the animation is complete
|
||||
onAnimationComplete : null
|
||||
|
||||
}</code></pre>
|
||||
</article>
|
||||
|
||||
<article id="barChart">
|
||||
<h1>Bar chart</h1>
|
||||
<h2>Introduction</h2>
|
||||
<p>A bar chart is a way of showing data as bars.</p>
|
||||
<p>It is sometimes used to show trend data, and the comparison of multiple data sets side by side.</p>
|
||||
<h2>Example usage</h2>
|
||||
<canvas id="bar" data-type="Bar" width="600" height="400"></canvas>
|
||||
<pre data-type="javascript"><code>new Chart(ctx).Bar(data,options);</code></pre>
|
||||
<h2>Data structure</h2>
|
||||
<pre data-type="javascript"><code data-for="bar">var data = {
|
||||
labels : ["January","February","March","April","May","June","July"],
|
||||
datasets : [
|
||||
{
|
||||
fillColor : "rgba(220,220,220,0.5)",
|
||||
strokeColor : "rgba(220,220,220,1)",
|
||||
data : [65,59,90,81,56,55,40]
|
||||
},
|
||||
{
|
||||
fillColor : "rgba(151,187,205,0.5)",
|
||||
strokeColor : "rgba(151,187,205,1)",
|
||||
data : [28,48,40,19,96,27,100]
|
||||
}
|
||||
]
|
||||
}</code></pre>
|
||||
<p>The bar chart has the a very similar data structure to the line chart, and has an array of datasets, each with colours and an array of data. Again, colours are in CSS format.</p>
|
||||
<p>We have an array of labels too for display. In the example, we are showing the same data as the previous line chart example.</p>
|
||||
|
||||
<h2>Chart options</h2>
|
||||
<pre data-type="javascript"><code>Bar.defaults = {
|
||||
|
||||
//Boolean - If we show the scale above the chart data
|
||||
scaleOverlay : false,
|
||||
|
||||
//Boolean - If we want to override with a hard coded scale
|
||||
scaleOverride : false,
|
||||
|
||||
//** Required if scaleOverride is true **
|
||||
//Number - The number of steps in a hard coded scale
|
||||
scaleSteps : null,
|
||||
//Number - The value jump in the hard coded scale
|
||||
scaleStepWidth : null,
|
||||
//Number - The scale starting value
|
||||
scaleStartValue : null,
|
||||
|
||||
//String - Colour of the scale line
|
||||
scaleLineColor : "rgba(0,0,0,.1)",
|
||||
|
||||
//Number - Pixel width of the scale line
|
||||
scaleLineWidth : 1,
|
||||
|
||||
//Boolean - Whether to show labels on the scale
|
||||
scaleShowLabels : true,
|
||||
|
||||
//Interpolated JS string - can access value
|
||||
scaleLabel : "<%=value%>",
|
||||
|
||||
//String - Scale label font declaration for the scale label
|
||||
scaleFontFamily : "'Arial'",
|
||||
|
||||
//Number - Scale label font size in pixels
|
||||
scaleFontSize : 12,
|
||||
|
||||
//String - Scale label font weight style
|
||||
scaleFontStyle : "normal",
|
||||
|
||||
//String - Scale label font colour
|
||||
scaleFontColor : "#666",
|
||||
|
||||
///Boolean - Whether grid lines are shown across the chart
|
||||
scaleShowGridLines : true,
|
||||
|
||||
//String - Colour of the grid lines
|
||||
scaleGridLineColor : "rgba(0,0,0,.05)",
|
||||
|
||||
//Number - Width of the grid lines
|
||||
scaleGridLineWidth : 1,
|
||||
|
||||
//Boolean - If there is a stroke on each bar
|
||||
barShowStroke : true,
|
||||
|
||||
//Number - Pixel width of the bar stroke
|
||||
barStrokeWidth : 2,
|
||||
|
||||
//Number - Spacing between each of the X value sets
|
||||
barValueSpacing : 5,
|
||||
|
||||
//Number - Spacing between data sets within X values
|
||||
barDatasetSpacing : 1,
|
||||
|
||||
//Boolean - Whether to animate the chart
|
||||
animation : true,
|
||||
|
||||
//Number - Number of animation steps
|
||||
animationSteps : 60,
|
||||
|
||||
//String - Animation easing effect
|
||||
animationEasing : "easeOutQuart",
|
||||
|
||||
//Function - Fires when the animation is complete
|
||||
onAnimationComplete : null
|
||||
|
||||
}</code></pre>
|
||||
</article>
|
||||
|
||||
<article id="radarChart">
|
||||
<h1>Radar chart</h1>
|
||||
<h2>Introduction</h2>
|
||||
<p>A radar chart is a way of showing multiple data points and the variation between them.</p>
|
||||
<p>They are often useful for comparing the points of two or more different data sets</p>
|
||||
<h2>Example usage</h2>
|
||||
<canvas id="radar" data-type="Radar" width="400" height="400"></canvas>
|
||||
<pre data-type="javascript"><code>new Chart(ctx).Radar(data,options);</code></pre>
|
||||
<h2>Data structure</h2>
|
||||
<pre data-type="javascript"><code data-for="radar">var data = {
|
||||
labels : ["Eating","Drinking","Sleeping","Designing","Coding","Partying","Running"],
|
||||
datasets : [
|
||||
{
|
||||
fillColor : "rgba(220,220,220,0.5)",
|
||||
strokeColor : "rgba(220,220,220,1)",
|
||||
pointColor : "rgba(220,220,220,1)",
|
||||
pointStrokeColor : "#fff",
|
||||
data : [65,59,90,81,56,55,40]
|
||||
},
|
||||
{
|
||||
fillColor : "rgba(151,187,205,0.5)",
|
||||
strokeColor : "rgba(151,187,205,1)",
|
||||
pointColor : "rgba(151,187,205,1)",
|
||||
pointStrokeColor : "#fff",
|
||||
data : [28,48,40,19,96,27,100]
|
||||
}
|
||||
]
|
||||
}</code></pre>
|
||||
<p>For a radar chart, usually you will want to show a label on each point of the chart, so we include an array of strings that we show around each point in the chart. If you do not want this, you can either not include the array of labels, or choose to hide them in the chart options.</p>
|
||||
<p>For the radar chart data, we have an array of datasets. Each of these is an object, with a fill colour, a stroke colour, a colour for the fill of each point, and a colour for the stroke of each point. We also have an array of data values.</p>
|
||||
|
||||
<h2>Chart options</h2>
|
||||
<pre data-type="javascript"><code>Radar.defaults = {
|
||||
|
||||
//Boolean - If we show the scale above the chart data
|
||||
scaleOverlay : false,
|
||||
|
||||
//Boolean - If we want to override with a hard coded scale
|
||||
scaleOverride : false,
|
||||
|
||||
//** Required if scaleOverride is true **
|
||||
//Number - The number of steps in a hard coded scale
|
||||
scaleSteps : null,
|
||||
//Number - The value jump in the hard coded scale
|
||||
scaleStepWidth : null,
|
||||
//Number - The centre starting value
|
||||
scaleStartValue : null,
|
||||
|
||||
//Boolean - Whether to show lines for each scale point
|
||||
scaleShowLine : true,
|
||||
|
||||
//String - Colour of the scale line
|
||||
scaleLineColor : "rgba(0,0,0,.1)",
|
||||
|
||||
//Number - Pixel width of the scale line
|
||||
scaleLineWidth : 1,
|
||||
|
||||
//Boolean - Whether to show labels on the scale
|
||||
scaleShowLabels : false,
|
||||
|
||||
//Interpolated JS string - can access value
|
||||
scaleLabel : "<%=value%>",
|
||||
|
||||
//String - Scale label font declaration for the scale label
|
||||
scaleFontFamily : "'Arial'",
|
||||
|
||||
//Number - Scale label font size in pixels
|
||||
scaleFontSize : 12,
|
||||
|
||||
//String - Scale label font weight style
|
||||
scaleFontStyle : "normal",
|
||||
|
||||
//String - Scale label font colour
|
||||
scaleFontColor : "#666",
|
||||
|
||||
//Boolean - Show a backdrop to the scale label
|
||||
scaleShowLabelBackdrop : true,
|
||||
|
||||
//String - The colour of the label backdrop
|
||||
scaleBackdropColor : "rgba(255,255,255,0.75)",
|
||||
|
||||
//Number - The backdrop padding above & below the label in pixels
|
||||
scaleBackdropPaddingY : 2,
|
||||
|
||||
//Number - The backdrop padding to the side of the label in pixels
|
||||
scaleBackdropPaddingX : 2,
|
||||
|
||||
//Boolean - Whether we show the angle lines out of the radar
|
||||
angleShowLineOut : true,
|
||||
|
||||
//String - Colour of the angle line
|
||||
angleLineColor : "rgba(0,0,0,.1)",
|
||||
|
||||
//Number - Pixel width of the angle line
|
||||
angleLineWidth : 1,
|
||||
|
||||
//String - Point label font declaration
|
||||
pointLabelFontFamily : "'Arial'",
|
||||
|
||||
//String - Point label font weight
|
||||
pointLabelFontStyle : "normal",
|
||||
|
||||
//Number - Point label font size in pixels
|
||||
pointLabelFontSize : 12,
|
||||
|
||||
//String - Point label font colour
|
||||
pointLabelFontColor : "#666",
|
||||
|
||||
//Boolean - Whether to show a dot for each point
|
||||
pointDot : true,
|
||||
|
||||
//Number - Radius of each point dot in pixels
|
||||
pointDotRadius : 3,
|
||||
|
||||
//Number - Pixel width of point dot stroke
|
||||
pointDotStrokeWidth : 1,
|
||||
|
||||
//Boolean - Whether to show a stroke for datasets
|
||||
datasetStroke : true,
|
||||
|
||||
//Number - Pixel width of dataset stroke
|
||||
datasetStrokeWidth : 2,
|
||||
|
||||
//Boolean - Whether to fill the dataset with a colour
|
||||
datasetFill : true,
|
||||
|
||||
//Boolean - Whether to animate the chart
|
||||
animation : true,
|
||||
|
||||
//Number - Number of animation steps
|
||||
animationSteps : 60,
|
||||
|
||||
//String - Animation easing effect
|
||||
animationEasing : "easeOutQuart",
|
||||
|
||||
//Function - Fires when the animation is complete
|
||||
onAnimationComplete : null
|
||||
|
||||
}</code></pre>
|
||||
</article>
|
||||
|
||||
<article id="polarAreaChart">
|
||||
<h1>Polar area chart</h1>
|
||||
<h2>Introduction</h2>
|
||||
<p>Polar area charts are similar to pie charts, but each segment has the same angle - the radius of the segment differs depending on the value.</p>
|
||||
<p>This type of chart is often useful when we want to show a comparison data similar to a pie chart, but also show a scale of values for context.</p>
|
||||
<h2>Example usage</h2>
|
||||
<canvas id="polarArea" data-type="PolarArea" width="300" height="300"></canvas>
|
||||
<pre data-type="javascript"><code>new Chart(ctx).PolarArea(data,options);</code></pre>
|
||||
<h2>Data structure</h2>
|
||||
<pre data-type="javascript"><code data-for="polarArea">var data = [
|
||||
{
|
||||
value : 30,
|
||||
color: "#D97041"
|
||||
},
|
||||
{
|
||||
value : 90,
|
||||
color: "#C7604C"
|
||||
},
|
||||
{
|
||||
value : 24,
|
||||
color: "#21323D"
|
||||
},
|
||||
{
|
||||
value : 58,
|
||||
color: "#9D9B7F"
|
||||
},
|
||||
{
|
||||
value : 82,
|
||||
color: "#7D4F6D"
|
||||
},
|
||||
{
|
||||
value : 8,
|
||||
color: "#584A5E"
|
||||
}
|
||||
]</code></pre>
|
||||
<p>As you can see, for the chart data you pass in an array of objects, with a value and a colour. The <code>value</code> attribute should be a number, while the <code>color</code> attribute should be a string. Similar to CSS, for this string you can use HEX notation, RGB, RGBA or HSL.</p>
|
||||
<h2>Chart options</h2>
|
||||
<p>These are the default chart options. By passing in an object with any of these attributes, Chart.js will merge these objects and the graph accordingly. Explanations of each option are commented in the code below.</p>
|
||||
<pre data-type="javascript"><code>PolarArea.defaults = {
|
||||
|
||||
//Boolean - Whether we show the scale above or below the chart segments
|
||||
scaleOverlay : true,
|
||||
|
||||
//Boolean - If we want to override with a hard coded scale
|
||||
scaleOverride : false,
|
||||
|
||||
//** Required if scaleOverride is true **
|
||||
//Number - The number of steps in a hard coded scale
|
||||
scaleSteps : null,
|
||||
//Number - The value jump in the hard coded scale
|
||||
scaleStepWidth : null,
|
||||
//Number - The centre starting value
|
||||
scaleStartValue : null,
|
||||
|
||||
//Boolean - Show line for each value in the scale
|
||||
scaleShowLine : true,
|
||||
|
||||
//String - The colour of the scale line
|
||||
scaleLineColor : "rgba(0,0,0,.1)",
|
||||
|
||||
//Number - The width of the line - in pixels
|
||||
scaleLineWidth : 1,
|
||||
|
||||
//Boolean - whether we should show text labels
|
||||
scaleShowLabels : true,
|
||||
|
||||
//Interpolated JS string - can access value
|
||||
scaleLabel : "<%=value%>",
|
||||
|
||||
//String - Scale label font declaration for the scale label
|
||||
scaleFontFamily : "'Arial'",
|
||||
|
||||
//Number - Scale label font size in pixels
|
||||
scaleFontSize : 12,
|
||||
|
||||
//String - Scale label font weight style
|
||||
scaleFontStyle : "normal",
|
||||
|
||||
//String - Scale label font colour
|
||||
scaleFontColor : "#666",
|
||||
|
||||
//Boolean - Show a backdrop to the scale label
|
||||
scaleShowLabelBackdrop : true,
|
||||
|
||||
//String - The colour of the label backdrop
|
||||
scaleBackdropColor : "rgba(255,255,255,0.75)",
|
||||
|
||||
//Number - The backdrop padding above & below the label in pixels
|
||||
scaleBackdropPaddingY : 2,
|
||||
|
||||
//Number - The backdrop padding to the side of the label in pixels
|
||||
scaleBackdropPaddingX : 2,
|
||||
|
||||
//Boolean - Stroke a line around each segment in the chart
|
||||
segmentShowStroke : true,
|
||||
|
||||
//String - The colour of the stroke on each segement.
|
||||
segmentStrokeColor : "#fff",
|
||||
|
||||
//Number - The width of the stroke value in pixels
|
||||
segmentStrokeWidth : 2,
|
||||
|
||||
//Boolean - Whether to animate the chart or not
|
||||
animation : true,
|
||||
|
||||
//Number - Amount of animation steps
|
||||
animationSteps : 100,
|
||||
|
||||
//String - Animation easing effect.
|
||||
animationEasing : "easeOutBounce",
|
||||
|
||||
//Boolean - Whether to animate the rotation of the chart
|
||||
animateRotate : true,
|
||||
|
||||
//Boolean - Whether to animate scaling the chart from the centre
|
||||
animateScale : false,
|
||||
|
||||
//Function - This will fire when the animation of the chart is complete.
|
||||
onAnimationComplete : null
|
||||
}</code></pre>
|
||||
</article>
|
||||
<article id="pieChart">
|
||||
<h1>Pie chart</h1>
|
||||
<h2>Introduction</h2>
|
||||
<p>Pie charts are probably the most commonly used chart there are. They are divided into segments, the arc of each segment shows a the proportional value of each piece of data.</p>
|
||||
<p>They are excellent at showing the relational proportions between data.</p>
|
||||
<h2>Example usage</h2>
|
||||
<canvas id="pie" data-type="Pie" width="400" height="400"></canvas>
|
||||
<pre data-type="javascript"><code>new Chart(ctx).Pie(data,options);</code></pre>
|
||||
<h2>Data structure</h2>
|
||||
<pre data-type="javascript"><code data-for="pie">var data = [
|
||||
{
|
||||
value: 30,
|
||||
color:"#F38630"
|
||||
},
|
||||
{
|
||||
value : 50,
|
||||
color : "#E0E4CC"
|
||||
},
|
||||
{
|
||||
value : 100,
|
||||
color : "#69D2E7"
|
||||
}
|
||||
]</code></pre>
|
||||
<p>For a pie chart, you must pass in an array of objects with a <code>value</code> and a <code>color</code> property. The <code>value</code> attribute should be a number, Chart.js will total all of the numbers and calculate the relative proportion of each. The <code>color</code> attribute should be a string. Similar to CSS, for this string you can use HEX notation, RGB, RGBA or HSL.</p>
|
||||
<h2>Chart options</h2>
|
||||
<p>These are the default options for the Pie chart. Pass in an object with any of these attributes to override them.
|
||||
<pre data-type="javascript"><code>Pie.defaults = {
|
||||
//Boolean - Whether we should show a stroke on each segment
|
||||
segmentShowStroke : true,
|
||||
|
||||
//String - The colour of each segment stroke
|
||||
segmentStrokeColor : "#fff",
|
||||
|
||||
//Number - The width of each segment stroke
|
||||
segmentStrokeWidth : 2,
|
||||
|
||||
//Boolean - Whether we should animate the chart
|
||||
animation : true,
|
||||
|
||||
//Number - Amount of animation steps
|
||||
animationSteps : 100,
|
||||
|
||||
//String - Animation easing effect
|
||||
animationEasing : "easeOutBounce",
|
||||
|
||||
//Boolean - Whether we animate the rotation of the Pie
|
||||
animateRotate : true,
|
||||
|
||||
//Boolean - Whether we animate scaling the Pie from the centre
|
||||
animateScale : false,
|
||||
|
||||
//Function - Will fire on animation completion.
|
||||
onAnimationComplete : null
|
||||
}</code></pre>
|
||||
</article>
|
||||
<article id="doughnutChart">
|
||||
<h1>Doughnut chart</h1>
|
||||
<h2>Introduction</h2>
|
||||
<p>Doughnut charts are similar to pie charts, however they have the centre cut out, and are therefore shaped more like a doughnut than a pie!</p>
|
||||
<p>They are aso excellent at showing the relational proportions between data.</p>
|
||||
<h2>Example usage</h2>
|
||||
<canvas id="doughnut" data-type="Doughnut" width="400" height="400"></canvas>
|
||||
<pre data-type="javascript"><code>new Chart(ctx).Doughnut(data,options);</code></pre>
|
||||
<h2>Data structure</h2>
|
||||
<pre data-type="javascript"><code data-for="doughnut">var data = [
|
||||
{
|
||||
value: 30,
|
||||
color:"#F7464A"
|
||||
},
|
||||
{
|
||||
value : 50,
|
||||
color : "#E2EAE9"
|
||||
},
|
||||
{
|
||||
value : 100,
|
||||
color : "#D4CCC5"
|
||||
},
|
||||
{
|
||||
value : 40,
|
||||
color : "#949FB1"
|
||||
},
|
||||
{
|
||||
value : 120,
|
||||
color : "#4D5360"
|
||||
}
|
||||
|
||||
]</code></pre>
|
||||
<p>For a doughnut chart, you must pass in an array of objects with a <code>value</code> and a <code>color</code> property. The <code>value</code> attribute should be a number, Chart.js will total all of the numbers and calculate the relative proportion of each. The <code>color</code> attribute should be a string. Similar to CSS, for this string you can use HEX notation, RGB, RGBA or HSL.</p>
|
||||
<h2>Chart options</h2>
|
||||
<p>These are the default options for the doughnut chart. Pass in an object with any of these attributes to override them.
|
||||
<pre data-type="javascript"><code>Doughnut.defaults = {
|
||||
//Boolean - Whether we should show a stroke on each segment
|
||||
segmentShowStroke : true,
|
||||
|
||||
//String - The colour of each segment stroke
|
||||
segmentStrokeColor : "#fff",
|
||||
|
||||
//Number - The width of each segment stroke
|
||||
segmentStrokeWidth : 2,
|
||||
|
||||
//The percentage of the chart that we cut out of the middle.
|
||||
percentageInnerCutout : 50,
|
||||
|
||||
//Boolean - Whether we should animate the chart
|
||||
animation : true,
|
||||
|
||||
//Number - Amount of animation steps
|
||||
animationSteps : 100,
|
||||
|
||||
//String - Animation easing effect
|
||||
animationEasing : "easeOutBounce",
|
||||
|
||||
//Boolean - Whether we animate the rotation of the Doughnut
|
||||
animateRotate : true,
|
||||
|
||||
//Boolean - Whether we animate scaling the Doughnut from the centre
|
||||
animateScale : false,
|
||||
|
||||
//Function - Will fire on animation completion.
|
||||
onAnimationComplete : null
|
||||
}</code></pre>
|
||||
</article>
|
||||
<article id="generalIssues">
|
||||
<h1>General issues</h1>
|
||||
<h2>Chart interactivity</h2>
|
||||
<p>If you are looking to add interaction as a layer to charts, Chart.js is <strong>not the library for you</strong>. A better option would be using SVG, as this will let you attach event listeners to any of the elements in the chart, as these are all DOM nodes.</p>
|
||||
<p>Chart.js uses the canvas element, which is a single DOM node, similar in characteristics to a static image. This does mean that it has a wider scope for compatibility, and less memory implications than SVG based charting solutions. The canvas element also allows for saving the contents as a base 64 string, allowing saving the chart as an image. </p>
|
||||
<p>In SVG, all of the lines, data points and everything you see is a DOM node. As a result of this, complex charts with a lot of intricacies, or many charts on the page will often see dips in performance when scrolling or generating the chart, especially when there are multiple on the page. SVG also has relatively poor mobile support, with Android not supporting SVG at all before version 3.0, and iOS before 5.0. (<a href="http://caniuse.com/svg-html5" target="_blank">caniuse.com/svg-html5</a>).</p>
|
||||
<h2>Browser support</h2>
|
||||
<p>Browser support for the canvas element is available in all modern & major mobile browsers (<a href="http://caniuse.com/canvas" target="_blank">caniuse.com/canvas</a>).</p>
|
||||
<p>For IE8 & below, I would recommend using the polyfill ExplorerCanvas - available at <a href="https://code.google.com/p/explorercanvas/" target="_blank">https://code.google.com/p/explorercanvas/</a>. It falls back to Internet explorer's format VML when canvas support is not available. Example use:</p>
|
||||
<pre data-type="html"><code><head>
|
||||
<!--[if lte IE 8]>
|
||||
<script src="excanvas.js"></script>
|
||||
<![endif]-->
|
||||
</head></code></pre>
|
||||
<p>Usually I would recommend feature detection to choose whether or not to load a polyfill, rather than IE conditional comments, however in this case, VML is a Microsoft proprietary format, so it will only work in IE.</p>
|
||||
<p>Some important points to note in my experience using ExplorerCanvas as a fallback.</p>
|
||||
<ul>
|
||||
<li>Initialise charts on load rather than DOMContentReady when using the library, as sometimes a race condition will occur, and it will result in an error when trying to get the 2d context of a canvas.</li>
|
||||
<li>New VML DOM elements are being created for each animation frame and there is no hardware acceleration. As a result animation is usually slow and jerky, with flashing text. It is a good idea to dynamically turn off animation based on canvas support. I recommend using the excellent <a href="http://modernizr.com/" targer="_blank">Modernizr</a> to do this.</li>
|
||||
<li>When declaring fonts, the library explorercanvas requires the font name to be in single quotes inside the string. For example, instead of your scaleFontFamily property being simply "Arial", explorercanvas support, use "'Arial'" instead. Chart.js does this for default values.</li>
|
||||
|
||||
</ul>
|
||||
<h2>Bugs & issues</h2>
|
||||
<p>Please report these on the Github page - at <a href="https://github.com/nnnick/Chart.js" target="_blank">github.com/nnnick/Chart.js</a>.</p>
|
||||
<p>New contributions to the library are welcome.</p>
|
||||
<h2>License</h2>
|
||||
<p>Chart.js is open source and available under the <a href="http://opensource.org/licenses/MIT" target="_blank">MIT license</a>.</p>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
|
||||
var $nav = $("nav dl");
|
||||
|
||||
$("article").each(function(){
|
||||
var $el = $(this);
|
||||
var $h1 = $el.find("h1");
|
||||
var sectionTitle = $h1.html();
|
||||
var articleId = $el.attr("id");
|
||||
var $dt = $("<dt><a href=\"#"+articleId +"\">"+sectionTitle+"</a></dt>");
|
||||
|
||||
$dt.find("a").on("click",function(e){
|
||||
e.preventDefault();
|
||||
$('html,body').animate({scrollTop: $h1.offset().top},400);
|
||||
});
|
||||
|
||||
$nav.append($dt);
|
||||
|
||||
var $subtitles = $el.find("h2");
|
||||
|
||||
$subtitles.each(function(){
|
||||
var $h2 = $(this);
|
||||
var title = $h2.text();
|
||||
var newID = articleId + "-" +camelCase(title);
|
||||
$h2.attr("id",newID);
|
||||
var $dd = $("<dd><a href=\"#" +newID + "\">" + title + "</a></dd>");
|
||||
|
||||
$dd.find("a").on("click",function(e){
|
||||
e.preventDefault();
|
||||
$('html,body').animate({scrollTop: $h2.offset().top},400);
|
||||
})
|
||||
$nav.append($dd);
|
||||
|
||||
});
|
||||
|
||||
var $articles = $el.find("article");
|
||||
|
||||
});
|
||||
|
||||
$("canvas").each(function(){
|
||||
var $canvas = $(this);
|
||||
var ctx = this.getContext("2d");
|
||||
|
||||
|
||||
|
||||
eval($("code[data-for='" + $canvas.attr("id") + "']").text());
|
||||
|
||||
|
||||
var evalString = "new Chart(ctx)." + $canvas.data("type") + "(data);";
|
||||
|
||||
eval(evalString);
|
||||
|
||||
});
|
||||
prettyPrint();
|
||||
|
||||
function camelCase(str){
|
||||
var splitString = str.split(" ");
|
||||
|
||||
var returnedCamel = splitString[0].toLowerCase();
|
||||
|
||||
for (var i=1; i<splitString.length; i++){
|
||||
returnedCamel += splitString[i].charAt(0).toUpperCase() + splitString[i].substring(1).toLowerCase();
|
||||
}
|
||||
|
||||
return returnedCamel;
|
||||
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
|
||||
var _gaq = _gaq || [];
|
||||
_gaq.push(['_setAccount', 'UA-28909194-3']);
|
||||
_gaq.push(['_trackPageview']);
|
||||
|
||||
(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>
|
||||
</html>
|
||||
@@ -1,38 +0,0 @@
|
||||
/* Pretty printing styles. Used with prettify.js. */
|
||||
/* Vim sunburst theme by David Leibovic */
|
||||
|
||||
pre .str, code .str { color: #65B042; } /* string - green */
|
||||
pre .kwd, code .kwd { color: #E28964; } /* keyword - dark pink */
|
||||
pre .com, code .com { color: #AEAEAE; font-style: italic; } /* comment - gray */
|
||||
pre .typ, code .typ { color: #89bdff; } /* type - light blue */
|
||||
pre .lit, code .lit { color: #3387CC; } /* literal - blue */
|
||||
pre .pun, code .pun { color: #fff; } /* punctuation - white */
|
||||
pre .pln, code .pln { color: #fff; } /* plaintext - white */
|
||||
pre .tag, code .tag { color: #89bdff; } /* html/xml tag - light blue */
|
||||
pre .atn, code .atn { color: #bdb76b; } /* html/xml attribute name - khaki */
|
||||
pre .atv, code .atv { color: #65B042; } /* html/xml attribute value - green */
|
||||
pre .dec, code .dec { color: #3387CC; } /* decimal - blue */
|
||||
|
||||
pre.prettyprint, code.prettyprint {
|
||||
background-color: #000;
|
||||
-moz-border-radius: 8px;
|
||||
-webkit-border-radius: 8px;
|
||||
-o-border-radius: 8px;
|
||||
-ms-border-radius: 8px;
|
||||
-khtml-border-radius: 8px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
pre.prettyprint {
|
||||
width: 95%;
|
||||
margin: 1em auto;
|
||||
padding: 1em;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
|
||||
/* Specify class=linenums on a pre to get line numbering */
|
||||
ol.linenums { margin-top: 0; margin-bottom: 0; color: #AEAEAE; } /* IE indents via margin-left */
|
||||
li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8 { list-style-type: none }
|
||||
/* Alternate shading for lines */
|
||||
li.L1,li.L3,li.L5,li.L7,li.L9 { }
|
||||
@@ -1,28 +0,0 @@
|
||||
var q=null;window.PR_SHOULD_USE_CONTINUATION=!0;
|
||||
(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a=
|
||||
[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c<i;++c){var j=f[c];if(/\\[bdsw]/i.test(j))a.push(j);else{var j=m(j),d;c+2<i&&"-"===f[c+1]?(d=m(f[c+2]),c+=2):d=j;b.push([j,d]);d<65||j>122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;c<b.length;++c)i=b[c],i[0]<=j[1]+1?j[1]=Math.max(j[1],i[1]):f.push(j=i);b=["["];o&&b.push("^");b.push.apply(b,a);for(c=0;c<
|
||||
f.length;++c)i=f[c],b.push(e(i[0])),i[1]>i[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c<b;++c){var j=f[c];j==="("?++i:"\\"===j.charAt(0)&&(j=+j.substring(1))&&j<=i&&(d[j]=-1)}for(c=1;c<d.length;++c)-1===d[c]&&(d[c]=++t);for(i=c=0;c<b;++c)j=f[c],j==="("?(++i,d[i]===void 0&&(f[c]="(?:")):"\\"===j.charAt(0)&&
|
||||
(j=+j.substring(1))&&j<=i&&(f[c]="\\"+d[i]);for(i=c=0;c<b;++c)"^"===f[c]&&"^"!==f[c+1]&&(f[c]="");if(a.ignoreCase&&s)for(c=0;c<b;++c)j=f[c],a=j.charAt(0),j.length>=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p<d;++p){var g=a[p];if(g.ignoreCase)l=!0;else if(/[a-z]/i.test(g.source.replace(/\\u[\da-f]{4}|\\x[\da-f]{2}|\\[^UXux]/gi,""))){s=!0;l=!1;break}}for(var r=
|
||||
{b:8,t:9,n:10,v:11,f:12,r:13},n=[],p=0,d=a.length;p<d;++p){g=a[p];if(g.global||g.multiline)throw Error(""+g);n.push("(?:"+y(g)+")")}return RegExp(n.join("|"),l?"gi":"g")}function M(a){function m(a){switch(a.nodeType){case 1:if(e.test(a.className))break;for(var g=a.firstChild;g;g=g.nextSibling)m(g);g=a.nodeName;if("BR"===g||"LI"===g)h[s]="\n",t[s<<1]=y++,t[s++<<1|1]=a;break;case 3:case 4:g=a.nodeValue,g.length&&(g=p?g.replace(/\r\n?/g,"\n"):g.replace(/[\t\n\r ]+/g," "),h[s]=g,t[s<<1]=y,y+=g.length,
|
||||
t[s++<<1|1]=a)}}var e=/(?:^|\s)nocode(?:\s|$)/,h=[],y=0,t=[],s=0,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=document.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);m(a);return{a:h.join("").replace(/\n$/,""),c:t}}function B(a,m,e,h){m&&(a={a:m,d:a},e(a),h.push.apply(h,a.e))}function x(a,m){function e(a){for(var l=a.d,p=[l,"pln"],d=0,g=a.a.match(y)||[],r={},n=0,z=g.length;n<z;++n){var f=g[n],b=r[f],o=void 0,c;if(typeof b===
|
||||
"string")c=!1;else{var i=h[f.charAt(0)];if(i)o=f.match(i[1]),b=i[0];else{for(c=0;c<t;++c)if(i=m[c],o=f.match(i[1])){b=i[0];break}o||(b="pln")}if((c=b.length>=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m),
|
||||
l=[],p={},d=0,g=e.length;d<g;++d){var r=e[d],n=r[3];if(n)for(var k=n.length;--k>=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/,
|
||||
q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/,
|
||||
q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g,
|
||||
"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a),
|
||||
a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e}
|
||||
for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g<d.length;++g)e(d[g]);m===(m|0)&&d[0].setAttribute("value",
|
||||
m);var r=s.createElement("OL");r.className="linenums";for(var n=Math.max(0,m-1|0)||0,g=0,z=d.length;g<z;++g)l=d[g],l.className="L"+(g+n)%10,l.firstChild||l.appendChild(s.createTextNode("\xa0")),r.appendChild(l);a.appendChild(r)}function k(a,m){for(var e=m.length;--e>=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*</.test(m)?"default-markup":"default-code";return A[a]}function E(a){var m=
|
||||
a.g;try{var e=M(a.h),h=e.a;a.a=h;a.c=e.c;a.d=0;C(m,h)(a);var k=/\bMSIE\b/.test(navigator.userAgent),m=/\n/g,t=a.a,s=t.length,e=0,l=a.c,p=l.length,h=0,d=a.e,g=d.length,a=0;d[g]=s;var r,n;for(n=r=0;n<g;)d[n]!==d[n+2]?(d[r++]=d[n++],d[r++]=d[n++]):n+=2;g=r;for(n=r=0;n<g;){for(var z=d[n],f=d[n+1],b=n+2;b+2<=g&&d[b+1]===f;)b+=2;d[r++]=z;d[r++]=f;n=b}for(d.length=r;h<p;){var o=l[h+2]||s,c=d[a+2]||s,b=Math.min(o,c),i=l[h+1],j;if(i.nodeType!==1&&(j=t.substring(e,b))){k&&(j=j.replace(m,"\r"));i.nodeValue=
|
||||
j;var u=i.ownerDocument,v=u.createElement("SPAN");v.className=d[a+1];var x=i.parentNode;x.replaceChild(v,i);v.appendChild(i);e<o&&(l[h+1]=i=u.createTextNode(t.substring(b,o)),x.insertBefore(i,v.nextSibling))}e=b;e>=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],
|
||||
"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"],
|
||||
H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"],
|
||||
J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+
|
||||
I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^<?]+/],["dec",/^<!\w[^>]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^<xmp\b[^>]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),
|
||||
["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css",
|
||||
/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),
|
||||
["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes",
|
||||
hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p<h.length&&l.now()<e;p++){var n=h[p],k=n.className;var k=k.match(g),f,b;if(b=
|
||||
!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}p<h.length?setTimeout(m,
|
||||
250):a&&a()}for(var e=[document.getElementsByTagName("pre"),document.getElementsByTagName("code"),document.getElementsByTagName("xmp")],h=[],k=0;k<e.length;++k)for(var t=0,s=e[k].length;t<s;++t)h.push(e[k][t]);var e=q,l=Date;l.now||(l={now:function(){return+new Date}});var p=0,d,g=/\blang(?:uage)?-([\w.]+)(?!\S)/;m()};window.PR={createSimpleLexer:x,registerLangHandler:k,sourceDecorator:u,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",
|
||||
PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ"}})();
|
||||
@@ -1,33 +0,0 @@
|
||||
/* Pretty printing styles. Used with prettify.js. */
|
||||
/* Vim sunburst theme by David Leibovic */
|
||||
|
||||
pre .str{ color: #65B042; } /* string - green */
|
||||
pre .kwd{ color: #E28964; } /* keyword - dark pink */
|
||||
pre .com{ color: #AEAEAE; font-style: italic; } /* comment - gray */
|
||||
pre .typ{ color: #89bdff; } /* type - light blue */
|
||||
pre .lit{ color: #3387CC; } /* literal - blue */
|
||||
pre .pun{ color: #fff; } /* punctuation - white */
|
||||
pre .pln{ color: #fff; } /* plaintext - white */
|
||||
pre .tag{ color: #89bdff; } /* html/xml tag - light blue */
|
||||
pre .atn{ color: #bdb76b; } /* html/xml attribute name - khaki */
|
||||
pre .atv{ color: #65B042; } /* html/xml attribute value - green */
|
||||
pre .dec{ color: #3387CC; } /* decimal - blue */
|
||||
|
||||
/* Specify class=linenums on a pre to get line numbering */
|
||||
ol.linenums { margin-top: 0; margin-bottom: 0; color: #AEAEAE; } /* IE indents via margin-left */
|
||||
li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8 { list-style-type: none }
|
||||
/* Alternate shading for lines */
|
||||
li.L1,li.L3,li.L5,li.L7,li.L9 { }
|
||||
|
||||
@media print {
|
||||
pre .str{ color: #060; }
|
||||
pre .kwd{ color: #006; font-weight: bold; }
|
||||
pre .com{ color: #600; font-style: italic; }
|
||||
pre .typ{ color: #404; font-weight: bold; }
|
||||
pre .lit{ color: #044; }
|
||||
pre .pun{ color: #440; }
|
||||
pre .pln{ color: #000; }
|
||||
pre .tag{ color: #006; font-weight: bold; }
|
||||
pre .atn{ color: #404; }
|
||||
pre .atv{ color: #060; }
|
||||
}
|
||||
@@ -1,263 +0,0 @@
|
||||
/* Pretty printing styles. Used with prettify.js. */
|
||||
/* Vim sunburst theme by David Leibovic */
|
||||
pre .str {
|
||||
color: #65B042;
|
||||
}
|
||||
/* string - green */
|
||||
pre .kwd {
|
||||
color: #E28964;
|
||||
}
|
||||
/* keyword - dark pink */
|
||||
pre .com {
|
||||
color: #AEAEAE;
|
||||
font-style: italic;
|
||||
}
|
||||
/* comment - gray */
|
||||
pre .typ {
|
||||
color: #89bdff;
|
||||
}
|
||||
/* type - light blue */
|
||||
pre .lit {
|
||||
color: #3387CC;
|
||||
}
|
||||
/* literal - blue */
|
||||
pre .pun {
|
||||
color: #fff;
|
||||
}
|
||||
/* punctuation - white */
|
||||
pre .pln {
|
||||
color: #fff;
|
||||
}
|
||||
/* plaintext - white */
|
||||
pre .tag {
|
||||
color: #89bdff;
|
||||
}
|
||||
/* html/xml tag - light blue */
|
||||
pre .atn {
|
||||
color: #bdb76b;
|
||||
}
|
||||
/* html/xml attribute name - khaki */
|
||||
pre .atv {
|
||||
color: #65B042;
|
||||
}
|
||||
/* html/xml attribute value - green */
|
||||
pre .dec {
|
||||
color: #3387CC;
|
||||
}
|
||||
/* decimal - blue */
|
||||
/* Specify class=linenums on a pre to get line numbering */
|
||||
ol.linenums {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
color: #AEAEAE;
|
||||
}
|
||||
/* IE indents via margin-left */
|
||||
li.L0,
|
||||
li.L1,
|
||||
li.L2,
|
||||
li.L3,
|
||||
li.L5,
|
||||
li.L6,
|
||||
li.L7,
|
||||
li.L8 {
|
||||
list-style-type: none;
|
||||
}
|
||||
/* Alternate shading for lines */
|
||||
@media print {
|
||||
pre .str {
|
||||
color: #060;
|
||||
}
|
||||
pre .kwd {
|
||||
color: #006;
|
||||
font-weight: bold;
|
||||
}
|
||||
pre .com {
|
||||
color: #600;
|
||||
font-style: italic;
|
||||
}
|
||||
pre .typ {
|
||||
color: #404;
|
||||
font-weight: bold;
|
||||
}
|
||||
pre .lit {
|
||||
color: #044;
|
||||
}
|
||||
pre .pun {
|
||||
color: #440;
|
||||
}
|
||||
pre .pln {
|
||||
color: #000;
|
||||
}
|
||||
pre .tag {
|
||||
color: #006;
|
||||
font-weight: bold;
|
||||
}
|
||||
pre .atn {
|
||||
color: #404;
|
||||
}
|
||||
pre .atv {
|
||||
color: #060;
|
||||
}
|
||||
}
|
||||
* {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
color: inherit;
|
||||
text-rendering: optimizeLegibility;
|
||||
}
|
||||
body {
|
||||
color: #282b36;
|
||||
min-width: 768px;
|
||||
}
|
||||
.redBorder,
|
||||
.greenBorder,
|
||||
.yellowBorder {
|
||||
border-top: 8px solid #282b36;
|
||||
width: 33.33%;
|
||||
float: left;
|
||||
height: 16px;
|
||||
position: relative;
|
||||
z-index: 50;
|
||||
}
|
||||
.redBorder {
|
||||
background-color: #f33e6f;
|
||||
}
|
||||
.greenBorder {
|
||||
background-color: #46bfbd;
|
||||
}
|
||||
.yellowBorder {
|
||||
background-color: #fdb45c;
|
||||
}
|
||||
h1 {
|
||||
font-family: "proxima-nova";
|
||||
font-weight: 600;
|
||||
font-size: 32px;
|
||||
}
|
||||
h2 {
|
||||
font-family: "proxima-nova";
|
||||
font-weight: 600;
|
||||
font-size: 22px;
|
||||
line-height: 40px;
|
||||
}
|
||||
#mainHeader {
|
||||
font-size: 55px;
|
||||
}
|
||||
#introText {
|
||||
font-weight: 400;
|
||||
margin-top: 20px;
|
||||
font-size: 26px;
|
||||
line-height: 40px;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
#wrapper {
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
min-width: 768px;
|
||||
}
|
||||
#wrapper nav {
|
||||
width: 20%;
|
||||
padding-right: 20px;
|
||||
position: fixed;
|
||||
height: 100%;
|
||||
overflow-y: scroll;
|
||||
top: 0;
|
||||
z-index: 0;
|
||||
padding: 40px 20px;
|
||||
font-family: "proxima-nova";
|
||||
background-color: #ebebeb;
|
||||
}
|
||||
#wrapper nav dl {
|
||||
color: #767c8d;
|
||||
}
|
||||
#wrapper nav dl dt {
|
||||
list-style: none;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
#wrapper nav dl dt a {
|
||||
display: block;
|
||||
padding: 2px 0;
|
||||
border-bottom: 1px solid rgba(118, 124, 141, 0.2);
|
||||
text-decoration: none;
|
||||
}
|
||||
#wrapper nav dl dd {
|
||||
margin-bottom: 5px;
|
||||
padding-left: 5px;
|
||||
}
|
||||
#wrapper nav dl dd:before {
|
||||
content: "- ";
|
||||
}
|
||||
#wrapper nav dl dd a {
|
||||
text-decoration: none;
|
||||
font-size: 12px;
|
||||
border-bottom: 1px solid transparent;
|
||||
}
|
||||
#wrapper nav dl a {
|
||||
-webkit-transition: all 200ms ease-in-out;
|
||||
-moz-transition: all 200ms ease-in-out;
|
||||
-o-transition: all 200ms ease-in-out;
|
||||
-ms-transition: all 200ms ease-in-out;
|
||||
transition: all 200ms ease-in-out;
|
||||
}
|
||||
#wrapper nav dl a:hover {
|
||||
color: #2d91ea;
|
||||
border-bottom-color: #2d91ea;
|
||||
}
|
||||
#wrapper #contentWrapper {
|
||||
width: 80%;
|
||||
max-width: 1080px;
|
||||
margin-left: 20%;
|
||||
padding: 0px 40px;
|
||||
padding-top: 72px;
|
||||
}
|
||||
article {
|
||||
border-top: 1px solid #ebebeb;
|
||||
padding: 40px 0;
|
||||
}
|
||||
article h2 {
|
||||
margin-top: 20px;
|
||||
}
|
||||
p,
|
||||
ul li {
|
||||
font-family: "proxima-nova";
|
||||
line-height: 20px;
|
||||
font-size: 16px;
|
||||
margin-top: 10px;
|
||||
color: #767c8d;
|
||||
}
|
||||
p a,
|
||||
ul li a {
|
||||
text-decoration: none;
|
||||
border-bottom: 1px solid #2d91ea;
|
||||
color: #2d91ea;
|
||||
}
|
||||
canvas {
|
||||
margin-top: 20px;
|
||||
}
|
||||
pre {
|
||||
background-color: #292b36;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
position: relative;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
margin: 40px 0 20px 0;
|
||||
}
|
||||
pre code {
|
||||
display: block;
|
||||
}
|
||||
pre:before {
|
||||
content: attr(data-type);
|
||||
position: absolute;
|
||||
font-size: 12px;
|
||||
top: -30px;
|
||||
left: 0;
|
||||
font-family: "proxima-nova";
|
||||
font-weight: 400;
|
||||
display: inline-block;
|
||||
padding: 2px 5px;
|
||||
border-radius: 5px;
|
||||
background-color: #ebebeb;
|
||||
}
|
||||
@@ -1,185 +0,0 @@
|
||||
@import "prettify";
|
||||
|
||||
@codeBackground : #292B36;
|
||||
|
||||
@primaryFont : "proxima-nova";
|
||||
|
||||
@textColour : #282B36;
|
||||
@secondaryTextColour : #767c8d;
|
||||
|
||||
@borderPaleColour : #EBEBEB;
|
||||
@pageBorderColour : @textColour;
|
||||
|
||||
@red : #F33E6F;
|
||||
@green : #46BFBD;
|
||||
@yellow : #FDB45C;
|
||||
@blue : #2D91EA;
|
||||
|
||||
*{
|
||||
padding:0;
|
||||
margin:0;
|
||||
box-sizing:border-box;
|
||||
-moz-box-sizing:border-box;
|
||||
-webkit-box-sizing:border-box;
|
||||
color:inherit;
|
||||
text-rendering: optimizeLegibility;
|
||||
}
|
||||
|
||||
body{
|
||||
color: @textColour;
|
||||
min-width: 768px;
|
||||
}
|
||||
|
||||
.redBorder,.greenBorder,.yellowBorder{
|
||||
border-top: 8px solid @pageBorderColour;
|
||||
width: 33.33%;
|
||||
float: left;
|
||||
height: 16px;
|
||||
position: relative;
|
||||
z-index:50;
|
||||
}
|
||||
.redBorder{
|
||||
background-color: @red;
|
||||
}
|
||||
.greenBorder{
|
||||
background-color: @green;
|
||||
}
|
||||
.yellowBorder{
|
||||
background-color: @yellow;
|
||||
}
|
||||
|
||||
h1{
|
||||
font-family: @primaryFont;
|
||||
font-weight: 600;
|
||||
font-size: 32px;
|
||||
}
|
||||
h2{
|
||||
font-family: @primaryFont;
|
||||
font-weight: 600;
|
||||
font-size: 22px;
|
||||
line-height: 40px;
|
||||
}
|
||||
#mainHeader{
|
||||
font-size: 55px;
|
||||
}
|
||||
#introText{
|
||||
font-weight: 400;
|
||||
margin-top: 20px;
|
||||
font-size: 26px;
|
||||
line-height: 40px;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
#wrapper{
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
min-width: 768px;
|
||||
nav{
|
||||
width: 20%;
|
||||
padding-right: 20px;
|
||||
position: fixed;
|
||||
height: 100%;
|
||||
overflow-y: scroll;
|
||||
top: 0;
|
||||
z-index: 0;
|
||||
padding: 40px 20px;
|
||||
font-family: @primaryFont;
|
||||
background-color: @borderPaleColour;
|
||||
|
||||
dl{
|
||||
color: @secondaryTextColour;
|
||||
dt{
|
||||
list-style: none;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 5px;
|
||||
a{
|
||||
display: block;
|
||||
padding: 2px 0;
|
||||
border-bottom: 1px solid fade(@secondaryTextColour,20%);
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
dd{
|
||||
margin-bottom: 5px;
|
||||
padding-left: 5px;
|
||||
&:before{
|
||||
content: "- ";
|
||||
|
||||
}
|
||||
a{
|
||||
text-decoration:none;
|
||||
font-size: 12px;
|
||||
border-bottom: 1px solid transparent;
|
||||
}
|
||||
}
|
||||
a{
|
||||
-webkit-transition: all 200ms ease-in-out;
|
||||
-moz-transition: all 200ms ease-in-out;
|
||||
-o-transition: all 200ms ease-in-out;
|
||||
-ms-transition: all 200ms ease-in-out;
|
||||
transition: all 200ms ease-in-out;
|
||||
&:hover{
|
||||
color: @blue;
|
||||
border-bottom-color:@blue;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#contentWrapper{
|
||||
width: 80%;
|
||||
max-width: 1080px;
|
||||
margin-left: 20%;
|
||||
padding: 0px 40px;
|
||||
padding-top: 72px;
|
||||
}
|
||||
}
|
||||
article{
|
||||
border-top: 1px solid @borderPaleColour;
|
||||
padding: 40px 0;
|
||||
h2{
|
||||
margin-top: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
p,ul li{
|
||||
font-family: @primaryFont;
|
||||
line-height: 20px;
|
||||
font-size: 16px;
|
||||
margin-top: 10px;
|
||||
color: @secondaryTextColour;
|
||||
a{
|
||||
text-decoration: none;
|
||||
border-bottom: 1px solid @blue;
|
||||
color: @blue;
|
||||
}
|
||||
}
|
||||
|
||||
canvas{
|
||||
margin-top: 20px;
|
||||
}
|
||||
pre{
|
||||
background-color: @codeBackground;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
position: relative;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
margin: 40px 0 20px 0;
|
||||
code{
|
||||
display: block;
|
||||
}
|
||||
&:before{
|
||||
content: attr(data-type);
|
||||
position: absolute;
|
||||
font-size: 12px;
|
||||
top: -30px;
|
||||
left: 0;
|
||||
font-family: @primaryFont;
|
||||
font-weight: 400;
|
||||
display: inline-block;
|
||||
padding: 2px 5px;
|
||||
border-radius: 5px;
|
||||
background-color: @borderPaleColour;
|
||||
}
|
||||
}
|
||||
p{
|
||||
}
|
||||
+207
@@ -0,0 +1,207 @@
|
||||
var gulp = require('gulp'),
|
||||
concat = require('gulp-concat'),
|
||||
uglify = require('gulp-uglify'),
|
||||
util = require('gulp-util'),
|
||||
jshint = require('gulp-jshint'),
|
||||
size = require('gulp-size'),
|
||||
connect = require('gulp-connect'),
|
||||
replace = require('gulp-replace'),
|
||||
htmlv = require('gulp-html-validator'),
|
||||
inquirer = require('inquirer'),
|
||||
semver = require('semver'),
|
||||
exec = require('child_process').exec,
|
||||
fs = require('fs'),
|
||||
package = require('./package.json'),
|
||||
bower = require('./bower.json'),
|
||||
karma = require('gulp-karma'),
|
||||
browserify = require('browserify'),
|
||||
streamify = require('gulp-streamify'),
|
||||
source = require('vinyl-source-stream'),
|
||||
merge = require('merge-stream');
|
||||
|
||||
var srcDir = './src/';
|
||||
var outDir = './dist/';
|
||||
var testDir = './test/';
|
||||
|
||||
var preTestFiles = [
|
||||
'./node_modules/moment/min/moment.min.js',
|
||||
];
|
||||
|
||||
var testFiles = [
|
||||
'./test/mockContext.js',
|
||||
'./test/*.js'
|
||||
];
|
||||
|
||||
gulp.task('build', buildTask);
|
||||
gulp.task('coverage', coverageTask);
|
||||
gulp.task('watch', watchTask);
|
||||
gulp.task('bump', bumpTask);
|
||||
gulp.task('release', ['build'], releaseTask);
|
||||
gulp.task('jshint', jshintTask);
|
||||
gulp.task('test', ['jshint', 'validHTML', 'unittest']);
|
||||
gulp.task('size', ['library-size', 'module-sizes']);
|
||||
gulp.task('server', serverTask);
|
||||
gulp.task('validHTML', validHTMLTask);
|
||||
gulp.task('unittest', unittestTask);
|
||||
gulp.task('unittestWatch', unittestWatchTask);
|
||||
gulp.task('library-size', librarySizeTask);
|
||||
gulp.task('module-sizes', moduleSizesTask);
|
||||
gulp.task('_open', _openTask);
|
||||
gulp.task('dev', ['server', 'default']);
|
||||
|
||||
gulp.task('default', ['build', 'watch']);
|
||||
|
||||
|
||||
function buildTask() {
|
||||
|
||||
var bundled = browserify('./src/Chart.js')
|
||||
.bundle()
|
||||
.pipe(source('Chart.bundle.js'))
|
||||
.pipe(streamify(replace('{{ version }}', package.version)))
|
||||
.pipe(gulp.dest(outDir))
|
||||
.pipe(streamify(uglify({
|
||||
preserveComments: 'some'
|
||||
})))
|
||||
.pipe(streamify(concat('Chart.bundle.min.js')))
|
||||
.pipe(gulp.dest(outDir));
|
||||
|
||||
var nonBundled = browserify('./src/Chart.js')
|
||||
.ignore('moment')
|
||||
.bundle()
|
||||
.pipe(source('Chart.js'))
|
||||
.pipe(streamify(replace('{{ version }}', package.version)))
|
||||
.pipe(gulp.dest(outDir))
|
||||
.pipe(streamify(uglify({
|
||||
preserveComments: 'some'
|
||||
})))
|
||||
.pipe(streamify(concat('Chart.min.js')))
|
||||
.pipe(gulp.dest(outDir));
|
||||
|
||||
return merge(bundled, nonBundled);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Usage : gulp bump
|
||||
* Prompts: Version increment to bump
|
||||
* Output: - New version number written into package.json & bower.json
|
||||
*/
|
||||
function bumpTask(complete) {
|
||||
util.log('Current version:', util.colors.cyan(package.version));
|
||||
var choices = ['major', 'premajor', 'minor', 'preminor', 'patch', 'prepatch', 'prerelease'].map(function(versionType) {
|
||||
return versionType + ' (v' + semver.inc(package.version, versionType) + ')';
|
||||
});
|
||||
inquirer.prompt({
|
||||
type: 'list',
|
||||
name: 'version',
|
||||
message: 'What version update would you like?',
|
||||
choices: choices
|
||||
}, function(res) {
|
||||
var increment = res.version.split(' ')[0],
|
||||
newVersion = semver.inc(package.version, increment);
|
||||
|
||||
// Set the new versions into the bower/package object
|
||||
package.version = newVersion;
|
||||
bower.version = newVersion;
|
||||
|
||||
// Write these to their own files, then build the output
|
||||
fs.writeFileSync('package.json', JSON.stringify(package, null, 2));
|
||||
fs.writeFileSync('bower.json', JSON.stringify(bower, null, 2));
|
||||
|
||||
complete();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function releaseTask() {
|
||||
exec('git tag -a v' + package.version);
|
||||
}
|
||||
|
||||
|
||||
function jshintTask() {
|
||||
return gulp.src(srcDir + '**/*.js')
|
||||
.pipe(jshint('config.jshintrc'))
|
||||
.pipe(jshint.reporter('jshint-stylish'))
|
||||
.pipe(jshint.reporter('fail'));
|
||||
}
|
||||
|
||||
|
||||
function validHTMLTask() {
|
||||
return gulp.src('samples/*.html')
|
||||
.pipe(htmlv());
|
||||
}
|
||||
|
||||
|
||||
function unittestTask() {
|
||||
var files = ['./src/**/*.js'];
|
||||
Array.prototype.unshift.apply(files, preTestFiles);
|
||||
Array.prototype.push.apply(files, testFiles);
|
||||
|
||||
return gulp.src(files)
|
||||
.pipe(karma({
|
||||
configFile: 'karma.conf.ci.js',
|
||||
action: 'run'
|
||||
}));
|
||||
}
|
||||
|
||||
function unittestWatchTask() {
|
||||
var files = ['./src/**/*.js'];
|
||||
Array.prototype.unshift.apply(files, preTestFiles);
|
||||
Array.prototype.push.apply(files, testFiles);
|
||||
|
||||
return gulp.src(files)
|
||||
.pipe(karma({
|
||||
configFile: 'karma.conf.js',
|
||||
action: 'watch'
|
||||
}));
|
||||
}
|
||||
|
||||
function coverageTask() {
|
||||
var files = ['./src/**/*.js'];
|
||||
Array.prototype.unshift.apply(files, preTestFiles);
|
||||
Array.prototype.push.apply(files, testFiles);
|
||||
|
||||
return gulp.src(files)
|
||||
.pipe(karma({
|
||||
configFile: 'karma.coverage.conf.js',
|
||||
action: 'run'
|
||||
}));
|
||||
}
|
||||
|
||||
function librarySizeTask() {
|
||||
return gulp.src('dist/Chart.bundle.min.js')
|
||||
.pipe(size({
|
||||
gzip: true
|
||||
}));
|
||||
}
|
||||
|
||||
function moduleSizesTask() {
|
||||
return gulp.src(srcDir + '**/*.js')
|
||||
.pipe(uglify({
|
||||
preserveComments: 'some'
|
||||
}))
|
||||
.pipe(size({
|
||||
showFiles: true,
|
||||
gzip: true
|
||||
}));
|
||||
}
|
||||
|
||||
function watchTask() {
|
||||
if (util.env.test) {
|
||||
return gulp.watch('./src/**', ['build', 'unittest', 'unittestWatch']);
|
||||
}
|
||||
return gulp.watch('./src/**', ['build']);
|
||||
}
|
||||
|
||||
function serverTask() {
|
||||
connect.server({
|
||||
port: 8000
|
||||
});
|
||||
}
|
||||
|
||||
// Convenience task for opening the project straight from the command line
|
||||
|
||||
function _openTask() {
|
||||
exec('open http://localhost:8000');
|
||||
exec('subl .');
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
module.exports = function(config) {
|
||||
var configuration = {
|
||||
browsers: ['Firefox'],
|
||||
customLaunchers: {
|
||||
Chrome_travis_ci: {
|
||||
base: 'Chrome',
|
||||
flags: ['--no-sandbox']
|
||||
}
|
||||
},
|
||||
frameworks: ['browserify', 'jasmine'],
|
||||
reporters: ['progress', 'html'],
|
||||
preprocessors: {
|
||||
'src/**/*.js': ['browserify']
|
||||
},
|
||||
browserify: {
|
||||
debug: true
|
||||
}
|
||||
};
|
||||
|
||||
if (process.env.TRAVIS) {
|
||||
configuration.browsers.push('Chrome_travis_ci');
|
||||
}
|
||||
|
||||
config.set(configuration);
|
||||
};
|
||||
@@ -0,0 +1,14 @@
|
||||
module.exports = function(config) {
|
||||
config.set({
|
||||
browsers: ['Chrome', 'Firefox'],
|
||||
frameworks: ['browserify', 'jasmine'],
|
||||
reporters: ['progress', 'html'],
|
||||
|
||||
preprocessors: {
|
||||
'src/**/*.js': ['browserify']
|
||||
},
|
||||
browserify: {
|
||||
debug: true
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,43 @@
|
||||
module.exports = function(config) {
|
||||
var configuration = {
|
||||
browsers: ['Firefox'],
|
||||
|
||||
frameworks: ['browserify', 'jasmine'],
|
||||
|
||||
preprocessors: {
|
||||
'src/**/*.js': ['browserify']
|
||||
},
|
||||
browserify: {
|
||||
debug: true,
|
||||
transform: [['browserify-istanbul', {
|
||||
instrumenterConfig: {
|
||||
embed: true
|
||||
}
|
||||
}]]
|
||||
},
|
||||
|
||||
reporters: ['progress', 'coverage'],
|
||||
coverageReporter: {
|
||||
dir: 'coverage/',
|
||||
reporters: [
|
||||
{ type: 'html', subdir: 'report-html' },
|
||||
{ type: 'lcovonly', subdir: '.', file: 'lcov.info' }
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
// If on the CI, use the CI chrome launcher
|
||||
if (process.env.TRAVIS) {
|
||||
configuration.browsers.push('Chrome_travis_ci');
|
||||
configuration.customLaunchers = {
|
||||
Chrome_travis_ci: {
|
||||
base: 'Chrome',
|
||||
flags: ['--no-sandbox']
|
||||
}
|
||||
};
|
||||
} else {
|
||||
configuration.browsers.push('Chrome');
|
||||
}
|
||||
|
||||
config.set(configuration);
|
||||
};
|
||||
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"name": "chart.js",
|
||||
"homepage": "http://www.chartjs.org",
|
||||
"description": "Simple HTML5 charts using the canvas element.",
|
||||
"version": "2.0.0",
|
||||
"main": "src/chart.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nnnick/Chart.js.git"
|
||||
},
|
||||
"devDependencies": {
|
||||
"browserify": "^13.0.0",
|
||||
"browserify-istanbul": "^0.2.1",
|
||||
"coveralls": "^2.11.6",
|
||||
"gulp": "3.9.x",
|
||||
"gulp-concat": "~2.1.x",
|
||||
"gulp-connect": "~2.0.5",
|
||||
"gulp-html-validator": "^0.0.2",
|
||||
"gulp-jshint": "~1.5.1",
|
||||
"gulp-karma": "0.0.4",
|
||||
"gulp-replace": "^0.4.0",
|
||||
"gulp-size": "~0.4.0",
|
||||
"gulp-streamify": "^1.0.2",
|
||||
"gulp-uglify": "~0.2.x",
|
||||
"gulp-umd": "~0.2.0",
|
||||
"gulp-util": "~2.2.x",
|
||||
"inquirer": "^0.5.1",
|
||||
"jasmine": "^2.3.2",
|
||||
"jasmine-core": "^2.3.4",
|
||||
"jquery": "^2.1.4",
|
||||
"jshint-stylish": "~2.1.0",
|
||||
"karma": "^0.12.37",
|
||||
"karma-browserify": "^5.0.1",
|
||||
"karma-chrome-launcher": "^0.2.0",
|
||||
"karma-coverage": "^0.5.1",
|
||||
"karma-firefox-launcher": "^0.1.6",
|
||||
"karma-jasmine": "^0.3.6",
|
||||
"karma-jasmine-html-reporter": "^0.1.8",
|
||||
"merge-stream": "^1.0.0",
|
||||
"semver": "^3.0.1",
|
||||
"vinyl-source-stream": "^1.1.0",
|
||||
"watchify": "^3.7.0"
|
||||
},
|
||||
"spm": {
|
||||
"main": "Chart.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"chartjs-color": "^1.0.2",
|
||||
"moment": "^2.10.6"
|
||||
}
|
||||
}
|
||||
-52
@@ -1,52 +0,0 @@
|
||||
Chart.js
|
||||
=======
|
||||
*Simple HTML5 Charts using the canvas element* [chartjs.org](http://www.chartjs.org)
|
||||
|
||||
Quick FYI
|
||||
-------
|
||||
I'm currently working on a big refactor of the library into a more object oriented structure.
|
||||
|
||||
It'll have an extendable class structure for adding community developed chart types. By opening up components into Chart.js into extendable classes, it'll allow for much easier community driven library extensions rather than tacking on new features as required. The refactor will also feature a generisized version of the interaction layer introduced by Regaddi in his tooltips branch - https://github.com/nnnick/Chart.js/pull/51. On top of this, it'll include utility methods on each chart object, for updating, clearing and redrawing charts etc.
|
||||
|
||||
I haven't quite got the bandwidth right now to be juggling both issues/requests in master while redesigning all of the core code in Chart.js. By focusing on the refactor, it'll get done WAY quicker.
|
||||
|
||||
Extensibility will absolutely be at the core of the refactor, allowing for the development of complex extension modules, but also keeping a lightweight set of core code.
|
||||
|
||||
Hang tight - it'll be worth it.
|
||||
|
||||
PS. If you're interested in reviewing some code or trying out writing extensions, shoot me an email.
|
||||
|
||||
###Update - 8th September
|
||||
Just a quick update on the refactor.
|
||||
|
||||
Just wanted to let you guys know it's making really good progress, and it'll be well worth the wait.
|
||||
|
||||
The new version is being broken up into Chart type modules, with each of the current 6 chart types using documented and extendable classes and helper methods from the Chart.js core. This means the community will be able to build new chart types using existing components, or extend existing types to do something a bit different.
|
||||
|
||||
By splitting the different charts into modules will mean the ability to use AMD if appropriate, but I'll also be writing a simple web interface for concatenating chart types into a minified production ready custom build.
|
||||
|
||||
The syntax for creating charts **will not change**, so the upgrade should be a drop in replacement, but give you the ability to have a whole new level of interactivity and animated data updates.
|
||||
|
||||
Right now I've wrote 80% of the core, and refactored the Doughnut and Pie charts, and I'm a good way through the Line and Bar charts. I hope to have the new version ready to release with some new docs late September/early October.
|
||||
|
||||
I know PR and issues are racking up in the repo, and I'll do my best to sort them ASAP, but I think this update is really important for creating flexibility and extensibility to cater for these new features in an elegant way, rather than introducing scope creep into an architecture that wasn't designed to deliver this extra functionality.
|
||||
|
||||
Big thanks for all the support - it's been totally overwhelming.
|
||||
|
||||
###Another Quick Update - 16th October
|
||||
First of all - my apologies, early October has drifted away from me and we're moving towards late October. This last month has been really unexpectedly busy, and I've had a lot of stuff going on, so I haven't quite managed to find as much time to work on Chart.js as I'd hoped.
|
||||
|
||||
In terms of an updated ETA, I'm really aiming for a pre-November release, and I'll be having some late nights and a few days off to try my best to make this happen.
|
||||
|
||||
Again, really appreciate the support and cheers for your patience for the new version.
|
||||
|
||||
|
||||
Documentation
|
||||
-------
|
||||
You can find documentation at [chartjs.org/docs](http://www.chartjs.org/docs).
|
||||
|
||||
License
|
||||
-------
|
||||
Chart.js was taken down on the 19th March. It is now back online for good and IS available under MIT license.
|
||||
|
||||
Chart.js is available under the [MIT license] (http://opensource.org/licenses/MIT).
|
||||
@@ -0,0 +1,170 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title> Animation Callbacks </title>
|
||||
<script src="../../dist/Chart.bundle.js"></script>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
||||
<style>
|
||||
canvas {
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div style="width: 75%;">
|
||||
<canvas id="canvas"></canvas>
|
||||
<progress id="animationProgress" max="1" value="0" style="width: 100%"></progress>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<button id="addDataset">Add Dataset</button>
|
||||
<button id="removeDataset">Remove Dataset</button>
|
||||
<button id="addData">Add Data</button>
|
||||
<button id="removeData">Remove Data</button>
|
||||
<script>
|
||||
var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
||||
|
||||
var randomScalingFactor = function() {
|
||||
return Math.round(Math.random() * 100);
|
||||
};
|
||||
var randomColorFactor = function() {
|
||||
return Math.round(Math.random() * 255);
|
||||
};
|
||||
var randomColor = function(opacity) {
|
||||
return 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',' + (opacity || '.3') + ')';
|
||||
};
|
||||
|
||||
var $progress = $('#animationProgress');
|
||||
|
||||
var config = {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
||||
datasets: [{
|
||||
label: "My First dataset ",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
fill: false,
|
||||
borderDash: [5, 5],
|
||||
}, {
|
||||
label: "My Second dataset ",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
title:{
|
||||
display:true,
|
||||
text:"Chart.js Line Chart - Animation Progress Bar"
|
||||
},
|
||||
animation: {
|
||||
duration: 2000,
|
||||
onProgress: function(animation) {
|
||||
$progress.attr({
|
||||
value: animation.animationObject.currentStep / animation.animationObject.numSteps,
|
||||
});
|
||||
},
|
||||
onComplete: function(animation) {
|
||||
window.setTimeout(function() {
|
||||
$progress.attr({
|
||||
value: 0
|
||||
});
|
||||
}, 2000);
|
||||
}
|
||||
},
|
||||
tooltips: {
|
||||
mode: 'label',
|
||||
},
|
||||
scales: {
|
||||
xAxes: [{
|
||||
scaleLabel: {
|
||||
show: true,
|
||||
labelString: 'Month'
|
||||
}
|
||||
}],
|
||||
yAxes: [{
|
||||
scaleLabel: {
|
||||
show: true,
|
||||
labelString: 'Value'
|
||||
},
|
||||
}]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.borderColor = randomColor(0.4);
|
||||
dataset.backgroundColor = randomColor(0.5);
|
||||
dataset.pointBorderColor = randomColor(0.7);
|
||||
dataset.pointBackgroundColor = randomColor(0.5);
|
||||
dataset.pointBorderWidth = 1;
|
||||
});
|
||||
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("canvas").getContext("2d");
|
||||
window.myLine = new Chart(ctx, config);
|
||||
};
|
||||
|
||||
$('#randomizeData').click(function() {
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.data = dataset.data.map(function() {
|
||||
return randomScalingFactor();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
window.myLine.update();
|
||||
});
|
||||
|
||||
$('#addDataset').click(function() {
|
||||
var newDataset = {
|
||||
label: 'Dataset ' + config.data.datasets.length,
|
||||
borderColor: randomColor(0.4),
|
||||
backgroundColor: randomColor(0.5),
|
||||
pointBorderColor: randomColor(0.7),
|
||||
pointBackgroundColor: randomColor(0.5),
|
||||
pointBorderWidth: 1,
|
||||
data: [],
|
||||
};
|
||||
|
||||
for (var index = 0; index < config.data.labels.length; ++index) {
|
||||
newDataset.data.push(randomScalingFactor());
|
||||
}
|
||||
|
||||
config.data.datasets.push(newDataset);
|
||||
window.myLine.update();
|
||||
});
|
||||
|
||||
$('#addData').click(function() {
|
||||
if (config.data.datasets.length > 0) {
|
||||
var month = MONTHS[config.data.labels.length % MONTHS.length];
|
||||
config.data.labels.push(month);
|
||||
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.data.push(randomScalingFactor());
|
||||
});
|
||||
|
||||
window.myLine.update();
|
||||
}
|
||||
});
|
||||
|
||||
$('#removeDataset').click(function() {
|
||||
config.data.datasets.splice(0, 1);
|
||||
window.myLine.update();
|
||||
});
|
||||
|
||||
$('#removeData').click(function() {
|
||||
config.data.labels.splice(-1, 1); // remove the label first
|
||||
|
||||
config.data.datasets.forEach(function(dataset, datasetIndex) {
|
||||
dataset.data.pop();
|
||||
});
|
||||
|
||||
window.myLine.update();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,102 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Bar Chart Multi Axis</title>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
||||
<script src="../dist/Chart.bundle.js"></script>
|
||||
<style>
|
||||
canvas {
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div style="width: 75%">
|
||||
<canvas id="canvas"></canvas>
|
||||
</div>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<script>
|
||||
var randomScalingFactor = function() {
|
||||
return (Math.random() > 0.5 ? 1.0 : -1.0) * Math.round(Math.random() * 100);
|
||||
};
|
||||
var randomColorFactor = function() {
|
||||
return Math.round(Math.random() * 255);
|
||||
};
|
||||
var randomColor = function() {
|
||||
return 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',.7)';
|
||||
};
|
||||
|
||||
var barChartData = {
|
||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
||||
datasets: [{
|
||||
label: 'Dataset 1',
|
||||
backgroundColor: "rgba(220,220,220,0.5)",
|
||||
yAxisID: "y-axis-1",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}, {
|
||||
label: 'Dataset 2',
|
||||
backgroundColor: "rgba(151,187,205,0.5)",
|
||||
yAxisID: "y-axis-2",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}, {
|
||||
label: 'Dataset 3',
|
||||
backgroundColor: [randomColor(), randomColor(), randomColor(), randomColor(), randomColor(), randomColor(), randomColor()],
|
||||
yAxisID: "y-axis-1",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}]
|
||||
|
||||
};
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("canvas").getContext("2d");
|
||||
window.myBar = Chart.Bar(ctx, {
|
||||
data: barChartData,
|
||||
options: {
|
||||
responsive: true,
|
||||
hoverMode: 'label',
|
||||
hoverAnimationDuration: 400,
|
||||
stacked: false,
|
||||
title:{
|
||||
display:true,
|
||||
text:"Chart.js Bar Chart - Multi Axis"
|
||||
},
|
||||
scales: {
|
||||
yAxes: [{
|
||||
type: "linear", // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
|
||||
display: true,
|
||||
position: "left",
|
||||
id: "y-axis-1",
|
||||
}, {
|
||||
type: "linear", // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
|
||||
display: true,
|
||||
position: "right",
|
||||
id: "y-axis-2",
|
||||
gridLines: {
|
||||
drawOnChartArea: false
|
||||
}
|
||||
}],
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$('#randomizeData').click(function() {
|
||||
$.each(barChartData.datasets, function(i, dataset) {
|
||||
if (Chart.helpers.isArray(dataset.backgroundColor)) {
|
||||
dataset.backgroundColor= [randomColor(), randomColor(), randomColor(), randomColor(), randomColor(), randomColor(), randomColor()];
|
||||
} else {
|
||||
dataset.backgroundColor= randomColor();
|
||||
}
|
||||
|
||||
dataset.data = [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()];
|
||||
|
||||
});
|
||||
window.myBar.update();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,84 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Stacked Bar Chart</title>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
||||
<script src="../dist/Chart.bundle.js"></script>
|
||||
<style>
|
||||
canvas {
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div style="width: 75%">
|
||||
<canvas id="canvas"></canvas>
|
||||
</div>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<script>
|
||||
var randomScalingFactor = function() {
|
||||
return (Math.random() > 0.5 ? 1.0 : -1.0) * Math.round(Math.random() * 100);
|
||||
};
|
||||
var randomColorFactor = function() {
|
||||
return Math.round(Math.random() * 255);
|
||||
};
|
||||
|
||||
var barChartData = {
|
||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
||||
datasets: [{
|
||||
label: 'Dataset 1',
|
||||
backgroundColor: "rgba(220,220,220,0.5)",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}, {
|
||||
label: 'Dataset 2',
|
||||
backgroundColor: "rgba(151,187,205,0.5)",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}, {
|
||||
label: 'Dataset 3',
|
||||
backgroundColor: "rgba(151,187,205,0.5)",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}]
|
||||
|
||||
};
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("canvas").getContext("2d");
|
||||
window.myBar = new Chart(ctx, {
|
||||
type: 'bar',
|
||||
data: barChartData,
|
||||
options: {
|
||||
title:{
|
||||
display:true,
|
||||
text:"Chart.js Bar Chart - Stacked"
|
||||
},
|
||||
tooltips: {
|
||||
mode: 'label'
|
||||
},
|
||||
responsive: true,
|
||||
scales: {
|
||||
xAxes: [{
|
||||
stacked: true,
|
||||
}],
|
||||
yAxes: [{
|
||||
stacked: true
|
||||
}]
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$('#randomizeData').click(function() {
|
||||
$.each(barChartData.datasets, function(i, dataset) {
|
||||
dataset.backgroundColor = 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',.7)';
|
||||
dataset.data = [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()];
|
||||
|
||||
});
|
||||
window.myBar.update();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
+137
-32
@@ -1,39 +1,144 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Bar Chart</title>
|
||||
<script src="../Chart.js"></script>
|
||||
<meta name = "viewport" content = "initial-scale = 1, user-scalable = no">
|
||||
<style>
|
||||
canvas{
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="canvas" height="450" width="600"></canvas>
|
||||
|
||||
<head>
|
||||
<title>Bar Chart</title>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
||||
<script src="../dist/Chart.bundle.js"></script>
|
||||
<style>
|
||||
canvas {
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<script>
|
||||
<body>
|
||||
<div id="container" style="width: 75%;">
|
||||
<canvas id="canvas"></canvas>
|
||||
</div>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<button id="addDataset">Add Dataset</button>
|
||||
<button id="removeDataset">Remove Dataset</button>
|
||||
<button id="addData">Add Data</button>
|
||||
<button id="removeData">Remove Data</button>
|
||||
<script>
|
||||
var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
||||
|
||||
var barChartData = {
|
||||
labels : ["January","February","March","April","May","June","July"],
|
||||
datasets : [
|
||||
{
|
||||
fillColor : "rgba(220,220,220,0.5)",
|
||||
strokeColor : "rgba(220,220,220,1)",
|
||||
data : [65,59,90,81,56,55,40]
|
||||
},
|
||||
{
|
||||
fillColor : "rgba(151,187,205,0.5)",
|
||||
strokeColor : "rgba(151,187,205,1)",
|
||||
data : [28,48,40,19,96,27,100]
|
||||
}
|
||||
]
|
||||
|
||||
}
|
||||
var randomScalingFactor = function() {
|
||||
return (Math.random() > 0.5 ? 1.0 : -1.0) * Math.round(Math.random() * 100);
|
||||
};
|
||||
var randomColorFactor = function() {
|
||||
return Math.round(Math.random() * 255);
|
||||
};
|
||||
var randomColor = function() {
|
||||
return 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',.7)';
|
||||
};
|
||||
|
||||
var barChartData = {
|
||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
||||
datasets: [{
|
||||
label: 'Dataset 1',
|
||||
backgroundColor: "rgba(220,220,220,0.5)",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}, {
|
||||
hidden: true,
|
||||
label: 'Dataset 2',
|
||||
backgroundColor: "rgba(151,187,205,0.5)",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}, {
|
||||
label: 'Dataset 3',
|
||||
backgroundColor: "rgba(151,187,205,0.5)",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}]
|
||||
|
||||
};
|
||||
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("canvas").getContext("2d");
|
||||
window.myBar = new Chart(ctx, {
|
||||
type: 'bar',
|
||||
data: barChartData,
|
||||
options: {
|
||||
// Elements options apply to all of the options unless overridden in a dataset
|
||||
// In this case, we are setting the border of each bar to be 2px wide and green
|
||||
elements: {
|
||||
rectangle: {
|
||||
borderWidth: 2,
|
||||
borderColor: 'rgb(0, 255, 0)',
|
||||
borderSkipped: 'bottom'
|
||||
}
|
||||
},
|
||||
responsive: true,
|
||||
legend: {
|
||||
position: 'top',
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Chart.js Bar Chart'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
$('#randomizeData').click(function() {
|
||||
var zero = Math.random() < 0.2 ? true : false;
|
||||
$.each(barChartData.datasets, function(i, dataset) {
|
||||
dataset.backgroundColor = randomColor();
|
||||
dataset.data = dataset.data.map(function() {
|
||||
return zero ? 0.0 : randomScalingFactor();
|
||||
});
|
||||
|
||||
});
|
||||
window.myBar.update();
|
||||
});
|
||||
|
||||
$('#addDataset').click(function() {
|
||||
var newDataset = {
|
||||
label: 'Dataset ' + barChartData.datasets.length,
|
||||
backgroundColor: randomColor(),
|
||||
data: []
|
||||
};
|
||||
|
||||
for (var index = 0; index < barChartData.labels.length; ++index) {
|
||||
newDataset.data.push(randomScalingFactor());
|
||||
}
|
||||
|
||||
barChartData.datasets.push(newDataset);
|
||||
window.myBar.update();
|
||||
});
|
||||
|
||||
$('#addData').click(function() {
|
||||
if (barChartData.datasets.length > 0) {
|
||||
var month = MONTHS[barChartData.labels.length % MONTHS.length];
|
||||
barChartData.labels.push(month);
|
||||
|
||||
for (var index = 0; index < barChartData.datasets.length; ++index) {
|
||||
//window.myBar.addData(randomScalingFactor(), index);
|
||||
barChartData.datasets[index].data.push(randomScalingFactor());
|
||||
}
|
||||
|
||||
window.myBar.update();
|
||||
}
|
||||
});
|
||||
|
||||
$('#removeDataset').click(function() {
|
||||
barChartData.datasets.splice(0, 1);
|
||||
window.myBar.update();
|
||||
});
|
||||
|
||||
$('#removeData').click(function() {
|
||||
barChartData.labels.splice(-1, 1); // remove the label first
|
||||
|
||||
barChartData.datasets.forEach(function(dataset, datasetIndex) {
|
||||
dataset.data.pop();
|
||||
});
|
||||
|
||||
window.myBar.update();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
var myLine = new Chart(document.getElementById("canvas").getContext("2d")).Bar(barChartData);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Bubble Chart</title>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
||||
<script src="../dist/Chart.bundle.js"></script>
|
||||
<style type="text/css">
|
||||
canvas{
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container" style="width: 75%;">
|
||||
<canvas id="canvas"></canvas>
|
||||
</div>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<button id="addDataset">Add Dataset</button>
|
||||
<button id="removeDataset">Remove Dataset</button>
|
||||
<button id="addData">Add Data</button>
|
||||
<button id="removeData">Remove Data</button>
|
||||
<script>
|
||||
var DEFAULT_DATASET_SIZE = 7;
|
||||
|
||||
var addedCount = 0;
|
||||
|
||||
var randomScalingFactor = function() {
|
||||
return (Math.random() > 0.5 ? 1.0 : -1.0) * Math.round(Math.random() * 100);
|
||||
};
|
||||
var randomColorFactor = function() {
|
||||
return Math.round(Math.random() * 255);
|
||||
};
|
||||
var randomColor = function() {
|
||||
return 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',.7)';
|
||||
};
|
||||
|
||||
var bubbleChartData = {
|
||||
animation: {
|
||||
duration: 10000
|
||||
},
|
||||
datasets: [{
|
||||
label: "My First dataset",
|
||||
backgroundColor: randomColor(),
|
||||
data: [{
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
r: Math.abs(randomScalingFactor()) / 5,
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
r: Math.abs(randomScalingFactor()) / 5,
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
r: Math.abs(randomScalingFactor()) / 5,
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
r: Math.abs(randomScalingFactor()) / 5,
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
r: Math.abs(randomScalingFactor()) / 5,
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
r: Math.abs(randomScalingFactor()) / 5,
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
r: Math.abs(randomScalingFactor()) / 5,
|
||||
}]
|
||||
}, {
|
||||
label: "My Second dataset",
|
||||
backgroundColor: randomColor(),
|
||||
data: [{
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
r: Math.abs(randomScalingFactor()) / 5,
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
r: Math.abs(randomScalingFactor()) / 5,
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
r: Math.abs(randomScalingFactor()) / 5,
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
r: Math.abs(randomScalingFactor()) / 5,
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
r: Math.abs(randomScalingFactor()) / 5,
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
r: Math.abs(randomScalingFactor()) / 5,
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
r: Math.abs(randomScalingFactor()) / 5,
|
||||
}]
|
||||
}]
|
||||
};
|
||||
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("canvas").getContext("2d");
|
||||
window.myChart = new Chart(ctx, {
|
||||
type: 'bubble',
|
||||
data: bubbleChartData,
|
||||
options: {
|
||||
responsive: true,
|
||||
title:{
|
||||
display:true,
|
||||
text:'Chart.js Bubble Chart'
|
||||
},
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$('#randomizeData').click(function() {
|
||||
var zero = Math.random() < 0.2 ? true : false;
|
||||
$.each(bubbleChartData.datasets, function(i, dataset) {
|
||||
dataset.backgroundColor = randomColor();
|
||||
dataset.data = dataset.data.map(function() {
|
||||
return {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
r: Math.abs(randomScalingFactor()) / 5,
|
||||
};
|
||||
});
|
||||
});
|
||||
window.myChart.update();
|
||||
});
|
||||
|
||||
$('#addDataset').click(function() {
|
||||
++addedCount;
|
||||
var newDataset = {
|
||||
label: "My added dataset " + addedCount,
|
||||
backgroundColor: randomColor(),
|
||||
data: []
|
||||
};
|
||||
|
||||
for (var index = 0; index < DEFAULT_DATASET_SIZE; ++index) {
|
||||
newDataset.data.push({
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
r: Math.abs(randomScalingFactor()) / 5,
|
||||
});
|
||||
}
|
||||
|
||||
bubbleChartData.datasets.push(newDataset);
|
||||
window.myChart.update();
|
||||
});
|
||||
|
||||
$('#addData').click(function() {
|
||||
if (bubbleChartData.datasets.length > 0) {
|
||||
for (var index = 0; index < bubbleChartData.datasets.length; ++index) {
|
||||
bubbleChartData.datasets[index].data.push({
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
r: Math.abs(randomScalingFactor()) / 5,
|
||||
});
|
||||
}
|
||||
|
||||
window.myChart.update();
|
||||
}
|
||||
});
|
||||
|
||||
$('#removeDataset').click(function() {
|
||||
bubbleChartData.datasets.splice(0, 1);
|
||||
window.myChart.update();
|
||||
});
|
||||
|
||||
$('#removeData').click(function() {
|
||||
|
||||
bubbleChartData.datasets.forEach(function(dataset, datasetIndex) {
|
||||
dataset.data.pop();
|
||||
});
|
||||
|
||||
window.myChart.update();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,80 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Combo Bar-Line Chart</title>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
||||
<script src="../dist/Chart.bundle.js"></script>
|
||||
<style>
|
||||
canvas {
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div style="width: 75%">
|
||||
<canvas id="canvas"></canvas>
|
||||
</div>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<script>
|
||||
var randomScalingFactor = function() {
|
||||
return (Math.random() > 0.5 ? 1.0 : -1.0) * Math.round(Math.random() * 100);
|
||||
};
|
||||
var randomColorFactor = function() {
|
||||
return Math.round(Math.random() * 255);
|
||||
};
|
||||
|
||||
var barChartData = {
|
||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
||||
datasets: [{
|
||||
type: 'bar',
|
||||
label: 'Dataset 1',
|
||||
backgroundColor: "rgba(151,187,205,0.5)",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
borderColor: 'white',
|
||||
borderWidth: 2
|
||||
}, {
|
||||
type: 'line',
|
||||
label: 'Dataset 2',
|
||||
backgroundColor: "rgba(151,187,205,0.5)",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
borderColor: 'white',
|
||||
borderWidth: 2
|
||||
}, {
|
||||
type: 'bar',
|
||||
label: 'Dataset 3',
|
||||
backgroundColor: "rgba(220,220,220,0.5)",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}, ]
|
||||
|
||||
};
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("canvas").getContext("2d");
|
||||
window.myBar = new Chart(ctx, {
|
||||
type: 'bar',
|
||||
data: barChartData,
|
||||
options: {
|
||||
responsive: true,
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Chart.js Combo Bar Line Chart'
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$('#randomizeData').click(function() {
|
||||
$.each(barChartData.datasets, function(i, dataset) {
|
||||
dataset.backgroundColor = 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',.7)';
|
||||
dataset.data = [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()];
|
||||
|
||||
});
|
||||
window.myBar.update();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
+169
-39
@@ -1,46 +1,176 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Doughnut Chart</title>
|
||||
<script src="../Chart.js"></script>
|
||||
<meta name = "viewport" content = "initial-scale = 1, user-scalable = no">
|
||||
<style>
|
||||
canvas{
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="canvas" height="450" width="450"></canvas>
|
||||
|
||||
<head>
|
||||
<title>Doughnut Chart</title>
|
||||
<script src="../dist/Chart.bundle.js"></script>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
||||
<style>
|
||||
canvas {
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<script>
|
||||
<body>
|
||||
<div id="canvas-holder" style="width:75%">
|
||||
<canvas id="chart-area" />
|
||||
</div>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<button id="addDataset">Add Dataset</button>
|
||||
<button id="removeDataset">Remove Dataset</button>
|
||||
<button id="addData">Add Data</button>
|
||||
<button id="removeData">Remove Data</button>
|
||||
<script>
|
||||
var randomScalingFactor = function() {
|
||||
return Math.round(Math.random() * 100);
|
||||
};
|
||||
var randomColorFactor = function() {
|
||||
return Math.round(Math.random() * 255);
|
||||
};
|
||||
var randomColor = function(opacity) {
|
||||
return 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',' + (opacity || '.3') + ')';
|
||||
};
|
||||
|
||||
var doughnutData = [
|
||||
{
|
||||
value: 30,
|
||||
color:"#F7464A"
|
||||
},
|
||||
{
|
||||
value : 50,
|
||||
color : "#46BFBD"
|
||||
},
|
||||
{
|
||||
value : 100,
|
||||
color : "#FDB45C"
|
||||
},
|
||||
{
|
||||
value : 40,
|
||||
color : "#949FB1"
|
||||
},
|
||||
{
|
||||
value : 120,
|
||||
color : "#4D5360"
|
||||
}
|
||||
|
||||
];
|
||||
var config = {
|
||||
type: 'doughnut',
|
||||
data: {
|
||||
datasets: [{
|
||||
data: [
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
],
|
||||
backgroundColor: [
|
||||
"#F7464A",
|
||||
"#46BFBD",
|
||||
"#FDB45C",
|
||||
"#949FB1",
|
||||
"#4D5360",
|
||||
],
|
||||
label: 'Dataset 1'
|
||||
}, {
|
||||
hidden: true,
|
||||
data: [
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
],
|
||||
backgroundColor: [
|
||||
"#F7464A",
|
||||
"#46BFBD",
|
||||
"#FDB45C",
|
||||
"#949FB1",
|
||||
"#4D5360",
|
||||
],
|
||||
label: 'Dataset 2'
|
||||
}, {
|
||||
data: [
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
],
|
||||
backgroundColor: [
|
||||
"#F7464A",
|
||||
"#46BFBD",
|
||||
"#FDB45C",
|
||||
"#949FB1",
|
||||
"#4D5360",
|
||||
],
|
||||
label: 'Dataset 3'
|
||||
}],
|
||||
labels: [
|
||||
"Red",
|
||||
"Green",
|
||||
"Yellow",
|
||||
"Grey",
|
||||
"Dark Grey"
|
||||
]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
legend: {
|
||||
position: 'top',
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Chart.js Doughnut Chart'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("chart-area").getContext("2d");
|
||||
window.myDoughnut = new Chart(ctx, config);
|
||||
};
|
||||
|
||||
$('#randomizeData').click(function() {
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.data = dataset.data.map(function() {
|
||||
return randomScalingFactor();
|
||||
});
|
||||
|
||||
dataset.backgroundColor = dataset.backgroundColor.map(function() {
|
||||
return randomColor(0.7);
|
||||
});
|
||||
});
|
||||
|
||||
window.myDoughnut.update();
|
||||
});
|
||||
|
||||
$('#addDataset').click(function() {
|
||||
var newDataset = {
|
||||
backgroundColor: [],
|
||||
data: [],
|
||||
label: 'New dataset ' + config.data.datasets.length,
|
||||
};
|
||||
|
||||
for (var index = 0; index < config.data.labels.length; ++index) {
|
||||
newDataset.data.push(randomScalingFactor());
|
||||
newDataset.backgroundColor.push(randomColor(0.7));
|
||||
}
|
||||
|
||||
config.data.datasets.push(newDataset);
|
||||
window.myDoughnut.update();
|
||||
});
|
||||
|
||||
$('#addData').click(function() {
|
||||
if (config.data.datasets.length > 0) {
|
||||
config.data.labels.push('data #' + config.data.labels.length);
|
||||
|
||||
$.each(config.data.datasets, function(index, dataset) {
|
||||
dataset.data.push(randomScalingFactor());
|
||||
dataset.backgroundColor.push(randomColor(0.7));
|
||||
});
|
||||
|
||||
window.myDoughnut.update();
|
||||
}
|
||||
});
|
||||
|
||||
$('#removeDataset').click(function() {
|
||||
config.data.datasets.splice(0, 1);
|
||||
window.myDoughnut.update();
|
||||
});
|
||||
|
||||
$('#removeData').click(function() {
|
||||
config.data.labels.splice(-1, 1); // remove the label first
|
||||
|
||||
config.data.datasets.forEach(function(dataset, datasetIndex) {
|
||||
dataset.data.pop();
|
||||
dataset.backgroundColor.pop();
|
||||
});
|
||||
|
||||
window.myDoughnut.update();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
var myDoughnut = new Chart(document.getElementById("canvas").getContext("2d")).Doughnut(doughnutData);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Line Chart with Custom Tooltips</title>
|
||||
<script src="../dist/Chart.bundle.js"></script>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
||||
<style>
|
||||
canvas{
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
#chartjs-tooltip {
|
||||
opacity: 1;
|
||||
position: absolute;
|
||||
background: rgba(0, 0, 0, .7);
|
||||
color: white;
|
||||
border-radius: 3px;
|
||||
-webkit-transition: all .1s ease;
|
||||
transition: all .1s ease;
|
||||
pointer-events: none;
|
||||
-webkit-transform: translate(-50%, 0);
|
||||
transform: translate(-50%, 0);
|
||||
}
|
||||
|
||||
.chartjs-tooltip-key {
|
||||
display: inline-block;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="canvas-holder1" style="width:75%;">
|
||||
<canvas id="chart1"/>
|
||||
</div>
|
||||
<script>
|
||||
window.count = 0;
|
||||
Chart.defaults.global.pointHitDetectionRadius = 1;
|
||||
var customTooltips = function(tooltip) {
|
||||
|
||||
// Tooltip Element
|
||||
var tooltipEl = $('#chartjs-tooltip');
|
||||
|
||||
if (!tooltipEl[0]) {
|
||||
$('body').append('<div id="chartjs-tooltip"></div>');
|
||||
tooltipEl = $('#chartjs-tooltip');
|
||||
}
|
||||
|
||||
// Hide if no tooltip
|
||||
if (!tooltip.opacity) {
|
||||
tooltipEl.css({
|
||||
opacity: 0
|
||||
});
|
||||
$('.chartjs-wrap canvas')
|
||||
.each(function(index, el) {
|
||||
$(el).css('cursor', 'default');
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
$(this._chart.canvas).css('cursor', 'pointer');
|
||||
|
||||
// Set caret Position
|
||||
tooltipEl.removeClass('above below no-transform');
|
||||
if (tooltip.yAlign) {
|
||||
tooltipEl.addClass(tooltip.yAlign);
|
||||
} else {
|
||||
tooltipEl.addClass('no-transform');
|
||||
}
|
||||
|
||||
// Set Text
|
||||
if (tooltip.body) {
|
||||
var innerHtml = [
|
||||
(tooltip.beforeTitle || []).join('\n'), (tooltip.title || []).join('\n'), (tooltip.afterTitle || []).join('\n'), (tooltip.beforeBody || []).join('\n'), (tooltip.body || []).join('\n'), (tooltip.afterBody || []).join('\n'), (tooltip.beforeFooter || [])
|
||||
.join('\n'), (tooltip.footer || []).join('\n'), (tooltip.afterFooter || []).join('\n')
|
||||
];
|
||||
tooltipEl.html(innerHtml.join('\n'));
|
||||
}
|
||||
|
||||
// Find Y Location on page
|
||||
var top = 0;
|
||||
if (tooltip.yAlign) {
|
||||
if (tooltip.yAlign == 'above') {
|
||||
top = tooltip.y - tooltip.caretHeight - tooltip.caretPadding;
|
||||
} else {
|
||||
top = tooltip.y + tooltip.caretHeight + tooltip.caretPadding;
|
||||
}
|
||||
}
|
||||
|
||||
var offset = $(this._chart.canvas).offset();
|
||||
|
||||
// Display, position, and set styles for font
|
||||
tooltipEl.css({
|
||||
opacity: 1,
|
||||
width: tooltip.width ? (tooltip.width + 'px') : 'auto',
|
||||
left: offset.left + tooltip.x + 'px',
|
||||
top: offset.top + top + 'px',
|
||||
fontFamily: tooltip._fontFamily,
|
||||
fontSize: tooltip.fontSize,
|
||||
fontStyle: tooltip._fontStyle,
|
||||
padding: tooltip.yPadding + 'px ' + tooltip.xPadding + 'px',
|
||||
});
|
||||
};
|
||||
var randomScalingFactor = function() {
|
||||
return Math.round(Math.random() * 100);
|
||||
};
|
||||
var lineChartData = {
|
||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
||||
datasets: [{
|
||||
label: "My First dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}, {
|
||||
label: "My Second dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}]
|
||||
};
|
||||
|
||||
window.onload = function() {
|
||||
var chartEl = document.getElementById("chart1");
|
||||
window.myLine = new Chart(chartEl, {
|
||||
type: 'line',
|
||||
data: lineChartData,
|
||||
options: {
|
||||
title:{
|
||||
display:true,
|
||||
text:'Chart.js Line Chart - Custom Tooltips'
|
||||
},
|
||||
tooltips: {
|
||||
enabled: false,
|
||||
custom: customTooltips
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,171 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Line Chart</title>
|
||||
<script src="../dist/Chart.bundle.js"></script>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
||||
<style>
|
||||
canvas {
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div style="width:75%;">
|
||||
<canvas id="canvas"></canvas>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<button id="addDataset">Add Dataset</button>
|
||||
<button id="removeDataset">Remove Dataset</button>
|
||||
<button id="addData">Add Data</button>
|
||||
<button id="removeData">Remove Data</button>
|
||||
<script>
|
||||
var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
||||
var randomScalingFactor = function() {
|
||||
return Math.round(Math.random() * 100 * (Math.random() > 0.5 ? -1 : 1));
|
||||
};
|
||||
var randomColorFactor = function() {
|
||||
return Math.round(Math.random() * 255);
|
||||
};
|
||||
var randomColor = function(opacity) {
|
||||
return 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',' + (opacity || '.3') + ')';
|
||||
};
|
||||
|
||||
var config = {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
||||
datasets: [{
|
||||
label: "My First dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
fill: false,
|
||||
borderDash: [5, 5],
|
||||
}, {
|
||||
label: "My Second dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
fill: false,
|
||||
borderDash: [5, 5],
|
||||
}, {
|
||||
label: "My Third dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
fill: false,
|
||||
}, {
|
||||
label: "My Fourth dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
fill: false,
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
legend: {
|
||||
position: 'bottom',
|
||||
},
|
||||
hover: {
|
||||
mode: 'label'
|
||||
},
|
||||
scales: {
|
||||
xAxes: [{
|
||||
display: true,
|
||||
scaleLabel: {
|
||||
display: true,
|
||||
labelString: 'Month'
|
||||
}
|
||||
}],
|
||||
yAxes: [{
|
||||
display: true,
|
||||
scaleLabel: {
|
||||
display: true,
|
||||
labelString: 'Value'
|
||||
}
|
||||
}]
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Chart.js Line Chart - Legend'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
var background = randomColor(0.5);
|
||||
dataset.borderColor = background;
|
||||
dataset.backgroundColor = background;
|
||||
dataset.pointBorderColor = background;
|
||||
dataset.pointBackgroundColor = background;
|
||||
dataset.pointBorderWidth = 1;
|
||||
});
|
||||
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("canvas").getContext("2d");
|
||||
window.myLine = new Chart(ctx, config);
|
||||
};
|
||||
|
||||
$('#randomizeData').click(function() {
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.data = dataset.data.map(function() {
|
||||
return randomScalingFactor();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
window.myLine.update();
|
||||
});
|
||||
|
||||
$('#addDataset').click(function() {
|
||||
var background = randomColor(0.5);
|
||||
var newDataset = {
|
||||
label: 'Dataset ' + config.data.datasets.length,
|
||||
borderColor: background,
|
||||
backgroundColor: background,
|
||||
pointBorderColor: background,
|
||||
pointBackgroundColor: background,
|
||||
pointBorderWidth: 1,
|
||||
fill: false,
|
||||
data: [],
|
||||
};
|
||||
|
||||
for (var index = 0; index < config.data.labels.length; ++index) {
|
||||
newDataset.data.push(randomScalingFactor());
|
||||
}
|
||||
|
||||
config.data.datasets.push(newDataset);
|
||||
window.myLine.update();
|
||||
});
|
||||
|
||||
$('#addData').click(function() {
|
||||
if (config.data.datasets.length > 0) {
|
||||
var month = MONTHS[config.data.labels.length % MONTHS.length];
|
||||
config.data.labels.push(month);
|
||||
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.data.push(randomScalingFactor());
|
||||
});
|
||||
|
||||
window.myLine.update();
|
||||
}
|
||||
});
|
||||
|
||||
$('#removeDataset').click(function() {
|
||||
config.data.datasets.splice(0, 1);
|
||||
window.myLine.update();
|
||||
});
|
||||
|
||||
$('#removeData').click(function() {
|
||||
config.data.labels.splice(-1, 1); // remove the label first
|
||||
|
||||
config.data.datasets.forEach(function(dataset, datasetIndex) {
|
||||
dataset.data.pop();
|
||||
});
|
||||
|
||||
window.myLine.update();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,152 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Line Chart</title>
|
||||
<script src="../dist/Chart.bundle.js"></script>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
||||
<style>
|
||||
canvas {
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div style="width:75%;">
|
||||
<canvas id="canvas"></canvas>
|
||||
</div>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<button id="addDataset">Add Dataset</button>
|
||||
<button id="removeDataset">Remove Dataset</button>
|
||||
<button id="addData">Add Data</button>
|
||||
<button id="removeData">Remove Data</button>
|
||||
<script>
|
||||
var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
||||
|
||||
var randomScalingFactor = function() {
|
||||
return Math.ceil(Math.random() * 10.0) * Math.pow(10, Math.ceil(Math.random() * 5));
|
||||
};
|
||||
var randomColorFactor = function() {
|
||||
return Math.round(Math.random() * 255);
|
||||
};
|
||||
var randomColor = function(opacity) {
|
||||
return 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',' + (opacity || '.3') + ')';
|
||||
};
|
||||
|
||||
var config = {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
||||
datasets: [{
|
||||
label: "My First dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
fill: false,
|
||||
borderDash: [5, 5],
|
||||
}, {
|
||||
label: "My Second dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
title:{
|
||||
display:true,
|
||||
text:'Chart.js Line Chart - Logarithmic'
|
||||
},
|
||||
scales: {
|
||||
xAxes: [{
|
||||
display: true,
|
||||
scaleLabel: {
|
||||
display: true,
|
||||
labelString: 'x axis'
|
||||
}
|
||||
}],
|
||||
yAxes: [{
|
||||
display: true,
|
||||
type: 'logarithmic',
|
||||
scaleLabel: {
|
||||
display: true,
|
||||
labelString: 'y axis'
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.borderColor = randomColor(0.4);
|
||||
dataset.backgroundColor = randomColor(0.5);
|
||||
dataset.pointBorderColor = randomColor(0.7);
|
||||
dataset.pointBackgroundColor = randomColor(0.5);
|
||||
dataset.pointBorderWidth = 1;
|
||||
});
|
||||
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("canvas").getContext("2d");
|
||||
window.myLine = new Chart(ctx, config);
|
||||
};
|
||||
|
||||
$('#randomizeData').click(function() {
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.data = dataset.data.map(function() {
|
||||
return randomScalingFactor();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
window.myLine.update();
|
||||
});
|
||||
|
||||
$('#addDataset').click(function() {
|
||||
var newDataset = {
|
||||
label: 'Dataset ' + config.data.datasets.length,
|
||||
borderColor: randomColor(0.4),
|
||||
backgroundColor: randomColor(0.5),
|
||||
pointBorderColor: randomColor(0.7),
|
||||
pointBackgroundColor: randomColor(0.5),
|
||||
pointBorderWidth: 1,
|
||||
data: [],
|
||||
};
|
||||
|
||||
for (var index = 0; index < config.data.labels.length; ++index) {
|
||||
newDataset.data.push(randomScalingFactor());
|
||||
}
|
||||
|
||||
config.data.datasets.push(newDataset);
|
||||
window.myLine.update();
|
||||
});
|
||||
|
||||
$('#addData').click(function() {
|
||||
if (config.data.datasets.length > 0) {
|
||||
var month = MONTHS[config.data.labels.length % MONTHS.length];
|
||||
config.data.labels.push(month);
|
||||
|
||||
for (var index = 0; index < config.data.datasets.length; ++index) {
|
||||
config.data.datasets[index].data.push(randomScalingFactor());
|
||||
}
|
||||
|
||||
window.myLine.update();
|
||||
}
|
||||
});
|
||||
|
||||
$('#removeDataset').click(function() {
|
||||
config.data.datasets.splice(0, 1);
|
||||
window.myLine.update();
|
||||
});
|
||||
|
||||
$('#removeData').click(function() {
|
||||
config.data.labels.splice(-1, 1); // remove the label first
|
||||
|
||||
config.data.datasets.forEach(function(dataset, datasetIndex) {
|
||||
dataset.data.pop();
|
||||
});
|
||||
|
||||
window.myLine.update();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,101 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Line Chart Multiple Axes</title>
|
||||
<script src="../dist/Chart.bundle.js"></script>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
||||
<style>
|
||||
canvas {
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div style="width:75%;">
|
||||
<canvas id="canvas"></canvas>
|
||||
</div>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<script>
|
||||
var randomScalingFactor = function() {
|
||||
return Math.round(Math.random() * 100 * (Math.random() > 0.5 ? -1 : 1));
|
||||
};
|
||||
var randomColor = function(opacity) {
|
||||
return 'rgba(' + Math.round(Math.random() * 255) + ',' + Math.round(Math.random() * 255) + ',' + Math.round(Math.random() * 255) + ',' + (opacity || '.3') + ')';
|
||||
};
|
||||
|
||||
var lineChartData = {
|
||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
||||
datasets: [{
|
||||
label: "My First dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
yAxisID: "y-axis-1",
|
||||
}, {
|
||||
label: "My Second dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
yAxisID: "y-axis-2"
|
||||
}]
|
||||
};
|
||||
|
||||
$.each(lineChartData.datasets, function(i, dataset) {
|
||||
dataset.borderColor = randomColor(0.4);
|
||||
dataset.backgroundColor = randomColor(1);
|
||||
dataset.pointBorderColor = randomColor(0.7);
|
||||
dataset.pointBackgroundColor = randomColor(0.5);
|
||||
dataset.pointBorderWidth = 1;
|
||||
});
|
||||
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("canvas").getContext("2d");
|
||||
window.myLine = Chart.Line(ctx, {
|
||||
data: lineChartData,
|
||||
options: {
|
||||
responsive: true,
|
||||
hoverMode: 'label',
|
||||
stacked: false,
|
||||
title:{
|
||||
display:true,
|
||||
text:'Chart.js Line Chart - Multi Axis'
|
||||
},
|
||||
scales: {
|
||||
xAxes: [{
|
||||
display: true,
|
||||
gridLines: {
|
||||
offsetGridLines: false
|
||||
}
|
||||
}],
|
||||
yAxes: [{
|
||||
type: "linear", // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
|
||||
display: true,
|
||||
position: "left",
|
||||
id: "y-axis-1",
|
||||
}, {
|
||||
type: "linear", // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
|
||||
display: true,
|
||||
position: "right",
|
||||
id: "y-axis-2",
|
||||
|
||||
// grid line settings
|
||||
gridLines: {
|
||||
drawOnChartArea: false, // only want the grid lines for one axis to show up
|
||||
},
|
||||
}],
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$('#randomizeData').click(function() {
|
||||
lineChartData.datasets[0].data = [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()];
|
||||
|
||||
lineChartData.datasets[1].data = [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()];
|
||||
|
||||
window.myLine.update();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,164 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Line Chart</title>
|
||||
<script src="../dist/Chart.bundle.js"></script>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
||||
<style>
|
||||
canvas {
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div style="width:75%;">
|
||||
<canvas id="canvas"></canvas>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<button id="addDataset">Add Dataset</button>
|
||||
<button id="removeDataset">Remove Dataset</button>
|
||||
<button id="addData">Add Data</button>
|
||||
<button id="removeData">Remove Data</button>
|
||||
<script>
|
||||
var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
||||
|
||||
var randomScalingFactor = function() {
|
||||
return Math.round(Math.random() * 100);
|
||||
//return 0;
|
||||
};
|
||||
var randomColorFactor = function() {
|
||||
return Math.round(Math.random() * 255);
|
||||
};
|
||||
var randomColor = function(opacity) {
|
||||
return 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',' + (opacity || '.3') + ')';
|
||||
};
|
||||
|
||||
var config = {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
||||
datasets: [{
|
||||
label: "My First dataset",
|
||||
|
||||
// Skip a point in the middle
|
||||
data: [randomScalingFactor(), randomScalingFactor(), NaN, randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
fill: true,
|
||||
borderDash: [5, 5],
|
||||
}, {
|
||||
label: "My Second dataset",
|
||||
|
||||
// Skip first and last points
|
||||
data: [NaN, randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), NaN],
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
title:{
|
||||
display:true,
|
||||
text:'Chart.js Line Chart - Skip Points'
|
||||
},
|
||||
tooltips: {
|
||||
mode: 'label',
|
||||
},
|
||||
hover: {
|
||||
mode: 'label'
|
||||
},
|
||||
scales: {
|
||||
xAxes: [{
|
||||
display: true,
|
||||
scaleLabel: {
|
||||
display: true,
|
||||
labelString: 'Month'
|
||||
}
|
||||
}],
|
||||
yAxes: [{
|
||||
display: true,
|
||||
scaleLabel: {
|
||||
display: true,
|
||||
labelString: 'Value'
|
||||
},
|
||||
}]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.borderColor = randomColor(0.4);
|
||||
dataset.backgroundColor = randomColor(0.5);
|
||||
dataset.pointBorderColor = randomColor(0.7);
|
||||
dataset.pointBackgroundColor = randomColor(0.5);
|
||||
dataset.pointBorderWidth = 1;
|
||||
});
|
||||
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("canvas").getContext("2d");
|
||||
window.myLine = new Chart(ctx, config);
|
||||
};
|
||||
|
||||
$('#randomizeData').click(function() {
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.data = dataset.data.map(function() {
|
||||
return randomScalingFactor();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
window.myLine.update();
|
||||
});
|
||||
|
||||
$('#addDataset').click(function() {
|
||||
var newDataset = {
|
||||
label: 'Dataset ' + config.data.datasets.length,
|
||||
borderColor: randomColor(0.4),
|
||||
backgroundColor: randomColor(0.5),
|
||||
pointBorderColor: randomColor(0.7),
|
||||
pointBackgroundColor: randomColor(0.5),
|
||||
pointBorderWidth: 1,
|
||||
data: [],
|
||||
};
|
||||
|
||||
for (var index = 0; index < config.data.labels.length; ++index) {
|
||||
newDataset.data.push(randomScalingFactor());
|
||||
}
|
||||
|
||||
config.data.datasets.push(newDataset);
|
||||
window.myLine.update();
|
||||
});
|
||||
|
||||
$('#addData').click(function() {
|
||||
if (config.data.datasets.length > 0) {
|
||||
var month = MONTHS[config.data.labels.length % MONTHS.length];
|
||||
config.data.labels.push(month);
|
||||
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.data.push(randomScalingFactor());
|
||||
});
|
||||
|
||||
window.myLine.update();
|
||||
}
|
||||
});
|
||||
|
||||
$('#removeDataset').click(function() {
|
||||
config.data.datasets.splice(0, 1);
|
||||
window.myLine.update();
|
||||
});
|
||||
|
||||
$('#removeData').click(function() {
|
||||
config.data.labels.splice(-1, 1); // remove the label first
|
||||
|
||||
config.data.datasets.forEach(function(dataset, datasetIndex) {
|
||||
dataset.data.pop();
|
||||
});
|
||||
|
||||
window.myLine.update();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,163 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Line Chart</title>
|
||||
<script src="../dist/Chart.bundle.js"></script>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
||||
<style>
|
||||
canvas {
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div style="width:75%;">
|
||||
<canvas id="canvas"></canvas>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<button id="addDataset">Add Dataset</button>
|
||||
<button id="removeDataset">Remove Dataset</button>
|
||||
<button id="addData">Add Data</button>
|
||||
<button id="removeData">Remove Data</button>
|
||||
<script>
|
||||
var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
||||
|
||||
var randomScalingFactor = function() {
|
||||
return Math.round(Math.random() * 100 * (Math.random() > 0.5 ? -1 : 1));
|
||||
};
|
||||
var randomColorFactor = function() {
|
||||
return Math.round(Math.random() * 255);
|
||||
};
|
||||
var randomColor = function(opacity) {
|
||||
return 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',' + (opacity || '1') + ')';
|
||||
};
|
||||
|
||||
var config = {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
||||
datasets: [{
|
||||
label: "My First dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
}, {
|
||||
label: "My Second dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
}, {
|
||||
label: "My Third dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
}, {
|
||||
label: "My Third dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
title:{
|
||||
display:true,
|
||||
text:"Chart.js Line Chart - Stacked Area"
|
||||
},
|
||||
tooltips: {
|
||||
mode: 'label',
|
||||
},
|
||||
hover: {
|
||||
mode: 'label'
|
||||
},
|
||||
scales: {
|
||||
xAxes: [{
|
||||
scaleLabel: {
|
||||
display: true,
|
||||
labelString: 'Month'
|
||||
}
|
||||
}],
|
||||
yAxes: [{
|
||||
stacked: true,
|
||||
scaleLabel: {
|
||||
display: true,
|
||||
labelString: 'Value'
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
var color = randomColor(1);
|
||||
dataset.borderColor = color;
|
||||
dataset.backgroundColor = color;
|
||||
dataset.pointBorderColor = color;
|
||||
dataset.pointBackgroundColor = color;
|
||||
dataset.pointBorderWidth = 1;
|
||||
});
|
||||
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("canvas").getContext("2d");
|
||||
window.myLine = new Chart(ctx, config);
|
||||
};
|
||||
|
||||
$('#randomizeData').click(function() {
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.data = dataset.data.map(function() {
|
||||
return randomScalingFactor();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
window.myLine.update();
|
||||
});
|
||||
|
||||
$('#addDataset').click(function() {
|
||||
var newDataset = {
|
||||
label: 'Dataset ' + config.data.datasets.length,
|
||||
borderColor: randomColor(0.4),
|
||||
backgroundColor: randomColor(0.5),
|
||||
pointBorderColor: randomColor(0.7),
|
||||
pointBackgroundColor: randomColor(0.5),
|
||||
pointBorderWidth: 1,
|
||||
data: [],
|
||||
};
|
||||
|
||||
for (var index = 0; index < config.data.labels.length; ++index) {
|
||||
newDataset.data.push(randomScalingFactor());
|
||||
}
|
||||
|
||||
config.data.datasets.push(newDataset);
|
||||
window.myLine.update();
|
||||
});
|
||||
|
||||
$('#addData').click(function() {
|
||||
if (config.data.datasets.length > 0) {
|
||||
var month = MONTHS[config.data.labels.length % MONTHS.length];
|
||||
config.data.labels.push(month);
|
||||
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.data.push(randomScalingFactor());
|
||||
});
|
||||
|
||||
window.myLine.update();
|
||||
}
|
||||
});
|
||||
|
||||
$('#removeDataset').click(function() {
|
||||
config.data.datasets.splice(0, 1);
|
||||
window.myLine.update();
|
||||
});
|
||||
|
||||
$('#removeData').click(function() {
|
||||
config.data.labels.splice(-1, 1); // remove the label first
|
||||
|
||||
config.data.datasets.forEach(function(dataset, datasetIndex) {
|
||||
dataset.data.pop();
|
||||
});
|
||||
|
||||
window.myLine.update();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,151 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Chart with xAxis Filtering</title>
|
||||
<script src="../dist/Chart.bundle.js"></script>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
||||
<style>
|
||||
canvas {
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div style="width:75%;">
|
||||
<canvas id="canvas"></canvas>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<button id="addDataset">Add Dataset</button>
|
||||
<button id="removeDataset">Remove Dataset</button>
|
||||
<button id="addData">Add Data</button>
|
||||
<button id="removeData">Remove Data</button>
|
||||
<script>
|
||||
var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
||||
|
||||
var randomScalingFactor = function() {
|
||||
return Math.round(Math.random() * 50 * (Math.random() > 0.5 ? 1 : 1)) + 50;
|
||||
};
|
||||
var randomColorFactor = function() {
|
||||
return Math.round(Math.random() * 255);
|
||||
};
|
||||
var randomColor = function(opacity) {
|
||||
return 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',' + (opacity || '.3') + ')';
|
||||
};
|
||||
|
||||
var config = {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
||||
datasets: [{
|
||||
label: "My First dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
fill: false,
|
||||
borderDash: [5, 5],
|
||||
}, {
|
||||
label: "My Second dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
title:{
|
||||
display:true,
|
||||
text:"Chart.js Line Chart - X-Axis Filter"
|
||||
},
|
||||
scales: {
|
||||
xAxes: [{
|
||||
display: true,
|
||||
ticks: {
|
||||
userCallback: function(dataLabel, index) {
|
||||
return index % 2 === 0 ? dataLabel : '';
|
||||
}
|
||||
}
|
||||
}],
|
||||
yAxes: [{
|
||||
display: true,
|
||||
beginAtZero: false
|
||||
}]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.borderColor = randomColor(0.4);
|
||||
dataset.backgroundColor = randomColor(0.5);
|
||||
dataset.pointBorderColor = randomColor(0.7);
|
||||
dataset.pointBackgroundColor = randomColor(0.5);
|
||||
dataset.pointBorderWidth = 1;
|
||||
});
|
||||
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("canvas").getContext("2d");
|
||||
window.myLine = new Chart(ctx, config);
|
||||
};
|
||||
|
||||
$('#randomizeData').click(function() {
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.data = dataset.data.map(function() {
|
||||
return randomScalingFactor();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
window.myLine.update();
|
||||
});
|
||||
|
||||
$('#addDataset').click(function() {
|
||||
var newDataset = {
|
||||
label: 'Dataset ' + config.data.datasets.length,
|
||||
borderColor: randomColor(0.4),
|
||||
backgroundColor: randomColor(0.5),
|
||||
pointBorderColor: randomColor(0.7),
|
||||
pointBackgroundColor: randomColor(0.5),
|
||||
pointBorderWidth: 1,
|
||||
data: [],
|
||||
};
|
||||
|
||||
for (var index = 0; index < config.data.labels.length; ++index) {
|
||||
newDataset.data.push(randomScalingFactor());
|
||||
}
|
||||
|
||||
config.data.datasets.push(newDataset);
|
||||
window.myLine.update();
|
||||
});
|
||||
|
||||
$('#addData').click(function() {
|
||||
if (config.data.datasets.length > 0) {
|
||||
var month = MONTHS[config.data.labels.length % MONTHS.length];
|
||||
config.data.labels.push(month);
|
||||
|
||||
for (var index = 0; index < config.data.datasets.length; ++index) {
|
||||
config.data.datasets[index].data.push(randomScalingFactor());
|
||||
}
|
||||
|
||||
window.myLine.update();
|
||||
}
|
||||
});
|
||||
|
||||
$('#removeDataset').click(function() {
|
||||
config.data.datasets.splice(0, 1);
|
||||
window.myLine.update();
|
||||
});
|
||||
|
||||
$('#removeData').click(function() {
|
||||
config.data.labels.splice(-1, 1); // remove the label first
|
||||
|
||||
config.data.datasets.forEach(function(dataset, datasetIndex) {
|
||||
dataset.data.pop();
|
||||
});
|
||||
|
||||
window.myLine.update();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
+211
-36
@@ -1,43 +1,218 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Line Chart</title>
|
||||
<script src="../Chart.js"></script>
|
||||
<meta name = "viewport" content = "initial-scale = 1, user-scalable = no">
|
||||
<style>
|
||||
canvas{
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="canvas" height="450" width="600"></canvas>
|
||||
|
||||
<head>
|
||||
<title>Line Chart</title>
|
||||
<script src="../dist/Chart.bundle.js"></script>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
||||
<style>
|
||||
canvas{
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<script>
|
||||
<body>
|
||||
<div style="width:75%;">
|
||||
<canvas id="canvas"></canvas>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<button id="changeDataObject">Change Data Object</button>
|
||||
<button id="addDataset">Add Dataset</button>
|
||||
<button id="removeDataset">Remove Dataset</button>
|
||||
<button id="addData">Add Data</button>
|
||||
<button id="removeData">Remove Data</button>
|
||||
<script>
|
||||
var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
||||
|
||||
var randomScalingFactor = function() {
|
||||
return Math.round(Math.random() * 100);
|
||||
//return 0;
|
||||
};
|
||||
var randomColorFactor = function() {
|
||||
return Math.round(Math.random() * 255);
|
||||
};
|
||||
var randomColor = function(opacity) {
|
||||
return 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',' + (opacity || '.3') + ')';
|
||||
};
|
||||
|
||||
var lineChartData = {
|
||||
labels : ["January","February","March","April","May","June","July"],
|
||||
datasets : [
|
||||
{
|
||||
fillColor : "rgba(220,220,220,0.5)",
|
||||
strokeColor : "rgba(220,220,220,1)",
|
||||
pointColor : "rgba(220,220,220,1)",
|
||||
pointStrokeColor : "#fff",
|
||||
data : [65,59,90,81,56,55,40]
|
||||
},
|
||||
{
|
||||
fillColor : "rgba(151,187,205,0.5)",
|
||||
strokeColor : "rgba(151,187,205,1)",
|
||||
pointColor : "rgba(151,187,205,1)",
|
||||
pointStrokeColor : "#fff",
|
||||
data : [28,48,40,19,96,27,100]
|
||||
}
|
||||
]
|
||||
|
||||
}
|
||||
var config = {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
||||
datasets: [{
|
||||
label: "My First dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
fill: false,
|
||||
borderDash: [5, 5],
|
||||
}, {
|
||||
hidden: true,
|
||||
label: 'hidden dataset',
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
}, {
|
||||
label: "My Second dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
title:{
|
||||
display:true,
|
||||
text:'Chart.js Line Chart'
|
||||
},
|
||||
tooltips: {
|
||||
mode: 'label',
|
||||
callbacks: {
|
||||
// beforeTitle: function() {
|
||||
// return '...beforeTitle';
|
||||
// },
|
||||
// afterTitle: function() {
|
||||
// return '...afterTitle';
|
||||
// },
|
||||
// beforeBody: function() {
|
||||
// return '...beforeBody';
|
||||
// },
|
||||
// afterBody: function() {
|
||||
// return '...afterBody';
|
||||
// },
|
||||
// beforeFooter: function() {
|
||||
// return '...beforeFooter';
|
||||
// },
|
||||
// footer: function() {
|
||||
// return 'Footer';
|
||||
// },
|
||||
// afterFooter: function() {
|
||||
// return '...afterFooter';
|
||||
// },
|
||||
}
|
||||
},
|
||||
hover: {
|
||||
mode: 'dataset'
|
||||
},
|
||||
scales: {
|
||||
xAxes: [{
|
||||
display: true,
|
||||
scaleLabel: {
|
||||
show: true,
|
||||
labelString: 'Month'
|
||||
}
|
||||
}],
|
||||
yAxes: [{
|
||||
display: true,
|
||||
scaleLabel: {
|
||||
show: true,
|
||||
labelString: 'Value'
|
||||
},
|
||||
ticks: {
|
||||
suggestedMin: -10,
|
||||
suggestedMax: 250,
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.borderColor = randomColor(0.4);
|
||||
dataset.backgroundColor = randomColor(0.5);
|
||||
dataset.pointBorderColor = randomColor(0.7);
|
||||
dataset.pointBackgroundColor = randomColor(0.5);
|
||||
dataset.pointBorderWidth = 1;
|
||||
});
|
||||
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("canvas").getContext("2d");
|
||||
window.myLine = new Chart(ctx, config);
|
||||
};
|
||||
|
||||
$('#randomizeData').click(function() {
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.data = dataset.data.map(function() {
|
||||
return randomScalingFactor();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
window.myLine.update();
|
||||
});
|
||||
|
||||
$('#changeDataObject').click(function() {
|
||||
config.data = {
|
||||
labels: ["July", "August", "September", "October", "November", "December"],
|
||||
datasets: [{
|
||||
label: "My First dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
fill: false,
|
||||
}, {
|
||||
label: "My Second dataset",
|
||||
fill: false,
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
}]
|
||||
};
|
||||
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.borderColor = randomColor(0.4);
|
||||
dataset.backgroundColor = randomColor(0.5);
|
||||
dataset.pointBorderColor = randomColor(0.7);
|
||||
dataset.pointBackgroundColor = randomColor(0.5);
|
||||
dataset.pointBorderWidth = 1;
|
||||
});
|
||||
|
||||
// Update the chart
|
||||
window.myLine.update();
|
||||
});
|
||||
|
||||
$('#addDataset').click(function() {
|
||||
var newDataset = {
|
||||
label: 'Dataset ' + config.data.datasets.length,
|
||||
borderColor: randomColor(0.4),
|
||||
backgroundColor: randomColor(0.5),
|
||||
pointBorderColor: randomColor(0.7),
|
||||
pointBackgroundColor: randomColor(0.5),
|
||||
pointBorderWidth: 1,
|
||||
data: [],
|
||||
};
|
||||
|
||||
for (var index = 0; index < config.data.labels.length; ++index) {
|
||||
newDataset.data.push(randomScalingFactor());
|
||||
}
|
||||
|
||||
config.data.datasets.push(newDataset);
|
||||
window.myLine.update();
|
||||
});
|
||||
|
||||
$('#addData').click(function() {
|
||||
if (config.data.datasets.length > 0) {
|
||||
var month = MONTHS[config.data.labels.length % MONTHS.length];
|
||||
config.data.labels.push(month);
|
||||
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.data.push(randomScalingFactor());
|
||||
});
|
||||
|
||||
window.myLine.update();
|
||||
}
|
||||
});
|
||||
|
||||
$('#removeDataset').click(function() {
|
||||
config.data.datasets.splice(0, 1);
|
||||
window.myLine.update();
|
||||
});
|
||||
|
||||
$('#removeData').click(function() {
|
||||
config.data.labels.splice(-1, 1); // remove the label first
|
||||
|
||||
config.data.datasets.forEach(function(dataset, datasetIndex) {
|
||||
dataset.data.pop();
|
||||
});
|
||||
|
||||
window.myLine.update();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
var myLine = new Chart(document.getElementById("canvas").getContext("2d")).Line(lineChartData);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+115
-31
@@ -1,38 +1,122 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Radar Chart</title>
|
||||
<script src="../Chart.js"></script>
|
||||
<meta name = "viewport" content = "initial-scale = 1, user-scalable = no">
|
||||
<style>
|
||||
canvas{
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="canvas" height="450" width="450"></canvas>
|
||||
|
||||
<head>
|
||||
<title>Pie Chart</title>
|
||||
<script src="../dist/Chart.bundle.js"></script>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
||||
</head>
|
||||
|
||||
<script>
|
||||
<body>
|
||||
<div id="canvas-holder" style="width:50%">
|
||||
<canvas id="chart-area" width="300" height="300" />
|
||||
</div>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<button id="addDataset">Add Dataset</button>
|
||||
<button id="removeDataset">Remove Dataset</button>
|
||||
<script>
|
||||
var randomScalingFactor = function() {
|
||||
return Math.round(Math.random() * 100);
|
||||
};
|
||||
var randomColorFactor = function() {
|
||||
return Math.round(Math.random() * 255);
|
||||
};
|
||||
var randomColor = function(opacity) {
|
||||
return 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',' + (opacity || '.3') + ')';
|
||||
};
|
||||
|
||||
var pieData = [
|
||||
{
|
||||
value: 30,
|
||||
color:"#F38630"
|
||||
},
|
||||
{
|
||||
value : 50,
|
||||
color : "#E0E4CC"
|
||||
},
|
||||
{
|
||||
value : 100,
|
||||
color : "#69D2E7"
|
||||
}
|
||||
|
||||
];
|
||||
var config = {
|
||||
type: 'pie',
|
||||
data: {
|
||||
datasets: [{
|
||||
data: [
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
],
|
||||
backgroundColor: [
|
||||
"#F7464A",
|
||||
"#46BFBD",
|
||||
"#FDB45C",
|
||||
"#949FB1",
|
||||
"#4D5360",
|
||||
],
|
||||
}, {
|
||||
data: [
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
],
|
||||
backgroundColor: [
|
||||
"#F7464A",
|
||||
"#46BFBD",
|
||||
"#FDB45C",
|
||||
"#949FB1",
|
||||
"#4D5360",
|
||||
],
|
||||
}, {
|
||||
data: [
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
],
|
||||
backgroundColor: [
|
||||
"#F7464A",
|
||||
"#46BFBD",
|
||||
"#FDB45C",
|
||||
"#949FB1",
|
||||
"#4D5360",
|
||||
],
|
||||
}],
|
||||
labels: [
|
||||
"Red",
|
||||
"Green",
|
||||
"Yellow",
|
||||
"Grey",
|
||||
"Dark Grey"
|
||||
]
|
||||
},
|
||||
options: {
|
||||
responsive: true
|
||||
}
|
||||
};
|
||||
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("chart-area").getContext("2d");
|
||||
window.myPie = new Chart(ctx, config);
|
||||
};
|
||||
|
||||
$('#randomizeData').click(function() {
|
||||
$.each(config.data.datasets, function(i, piece) {
|
||||
$.each(piece.data, function(j, value) {
|
||||
config.data.datasets[i].data[j] = randomScalingFactor();
|
||||
//config.data.datasets.backgroundColor[i] = 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',.7)';
|
||||
});
|
||||
});
|
||||
window.myPie.update();
|
||||
});
|
||||
|
||||
$('#addDataset').click(function() {
|
||||
var newDataset = {
|
||||
backgroundColor: [randomColor(0.7), randomColor(0.7), randomColor(0.7), randomColor(0.7), randomColor(0.7)],
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
};
|
||||
|
||||
config.data.datasets.push(newDataset);
|
||||
window.myPie.update();
|
||||
});
|
||||
|
||||
$('#removeDataset').click(function() {
|
||||
config.data.datasets.splice(0, 1);
|
||||
window.myPie.update();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
var myPie = new Chart(document.getElementById("canvas").getContext("2d")).Pie(pieData);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Polar Area Chart</title>
|
||||
<script src="../dist/Chart.bundle.js"></script>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
||||
<style>
|
||||
canvas {
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="canvas-holder" style="width:75%">
|
||||
<canvas id="chart-area"></canvas>
|
||||
</div>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<button id="addData">Add Data</button>
|
||||
<button id="removeData">Remove Data</button>
|
||||
<script>
|
||||
var randomScalingFactor = function() {
|
||||
return Math.round(Math.random() * 100);
|
||||
};
|
||||
var randomColorFactor = function() {
|
||||
return Math.round(Math.random() * 255);
|
||||
};
|
||||
var randomColor = function(opacity) {
|
||||
return 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',' + (opacity || '.3') + ')';
|
||||
};
|
||||
|
||||
var config = {
|
||||
data: {
|
||||
datasets: [{
|
||||
data: [
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
],
|
||||
backgroundColor: [
|
||||
"#F7464A",
|
||||
"#46BFBD",
|
||||
"#FDB45C",
|
||||
"#949FB1",
|
||||
"#4D5360",
|
||||
],
|
||||
label: 'My dataset' // for legend
|
||||
}],
|
||||
labels: [
|
||||
"Red",
|
||||
"Green",
|
||||
"Yellow",
|
||||
"Grey",
|
||||
"Dark Grey"
|
||||
]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
legend: {
|
||||
position: 'top',
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Chart.js Polar Area Chart'
|
||||
},
|
||||
scale: {
|
||||
ticks: {
|
||||
beginAtZero: true
|
||||
},
|
||||
reverse: false
|
||||
},
|
||||
animateRotate:false
|
||||
}
|
||||
};
|
||||
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("chart-area");
|
||||
window.myPolarArea = Chart.PolarArea(ctx, config);
|
||||
};
|
||||
|
||||
$('#randomizeData').click(function() {
|
||||
$.each(config.data.datasets, function(i, piece) {
|
||||
$.each(piece.data, function(j, value) {
|
||||
config.data.datasets[i].data[j] = randomScalingFactor();
|
||||
config.data.datasets[i].backgroundColor[j] = randomColor();
|
||||
});
|
||||
});
|
||||
window.myPolarArea.update();
|
||||
});
|
||||
|
||||
$('#addData').click(function() {
|
||||
if (config.data.datasets.length > 0) {
|
||||
config.data.labels.push('dataset #' + config.data.labels.length);
|
||||
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.backgroundColor.push(randomColor());
|
||||
dataset.data.push(randomScalingFactor());
|
||||
});
|
||||
|
||||
window.myPolarArea.update();
|
||||
}
|
||||
});
|
||||
|
||||
$('#removeData').click(function() {
|
||||
config.data.labels.pop(); // remove the label first
|
||||
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.backgroundColor.pop();
|
||||
dataset.data.pop();
|
||||
});
|
||||
|
||||
window.myPolarArea.update();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,44 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Polar Area Chart</title>
|
||||
<script src="../Chart.js"></script>
|
||||
<meta name = "viewport" content = "initial-scale = 1, user-scalable = no">
|
||||
<style>
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="canvas" height="400" width="400"></canvas>
|
||||
|
||||
|
||||
<script>
|
||||
var chartData = [
|
||||
{
|
||||
value : Math.random(),
|
||||
color: "#D97041"
|
||||
},
|
||||
{
|
||||
value : Math.random(),
|
||||
color: "#C7604C"
|
||||
},
|
||||
{
|
||||
value : Math.random(),
|
||||
color: "#21323D"
|
||||
},
|
||||
{
|
||||
value : Math.random(),
|
||||
color: "#9D9B7F"
|
||||
},
|
||||
{
|
||||
value : Math.random(),
|
||||
color: "#7D4F6D"
|
||||
},
|
||||
{
|
||||
value : Math.random(),
|
||||
color: "#584A5E"
|
||||
}
|
||||
];
|
||||
var myPolarArea = new Chart(document.getElementById("canvas").getContext("2d")).PolarArea(chartData);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,145 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Radar Chart</title>
|
||||
<script src="../dist/Chart.bundle.js"></script>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
||||
<style>
|
||||
canvas {
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div style="width:75%">
|
||||
<canvas id="canvas"></canvas>
|
||||
</div>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<button id="addDataset">Add Dataset</button>
|
||||
<button id="removeDataset">Remove Dataset</button>
|
||||
<button id="addData">Add Data</button>
|
||||
<button id="removeData">Remove Data</button>
|
||||
<script>
|
||||
var randomScalingFactor = function() {
|
||||
return Math.round(Math.random() * 100);
|
||||
};
|
||||
var randomColorFactor = function() {
|
||||
return Math.round(Math.random() * 255);
|
||||
};
|
||||
var randomColor = function(opacity) {
|
||||
return 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',' + (opacity || '.3') + ')';
|
||||
};
|
||||
|
||||
var config = {
|
||||
type: 'radar',
|
||||
data: {
|
||||
labels: ["Eating", "Drinking", "Sleeping", "Designing", "Coding", "Cycling", "Running"],
|
||||
datasets: [{
|
||||
label: "Skip first dataset",
|
||||
borderColor: 'rgb(255, 0, 0)',
|
||||
backgroundColor: "rgba(255,255,0,0.5)",
|
||||
pointBackgroundColor: "rgba(220,220,220,1)",
|
||||
data: [NaN, randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}, {
|
||||
label: "Skip mid dataset",
|
||||
borderColor: 'rgb(255, 0, 255)',
|
||||
backgroundColor: "rgba(0, 255, 0, 0.5)",
|
||||
pointBackgroundColor: "rgba(151,187,205,1)",
|
||||
hoverPointBackgroundColor: "#fff",
|
||||
pointHighlightStroke: "rgba(151,187,205,1)",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), NaN, randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
},{
|
||||
label: "Skip last dataset",
|
||||
borderColor: 'rgb(0, 255, 255)',
|
||||
backgroundColor: "rgba(0, 0, 255, 0.5)",
|
||||
pointBackgroundColor: "rgba(151,187,205,1)",
|
||||
hoverPointBackgroundColor: "#fff",
|
||||
pointHighlightStroke: "rgba(151,187,205,1)",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), NaN]
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
title:{
|
||||
display:true,
|
||||
text:"Chart.js Radar Chart - Skip Points"
|
||||
},
|
||||
elements: {
|
||||
line: {
|
||||
tension: 0.0,
|
||||
}
|
||||
},
|
||||
scale: {
|
||||
beginAtZero: true,
|
||||
reverse: false
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
window.onload = function() {
|
||||
window.myRadar = new Chart(document.getElementById("canvas"), config);
|
||||
};
|
||||
|
||||
$('#randomizeData').click(function() {
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.data = dataset.data.map(function() {
|
||||
return randomScalingFactor();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
window.myRadar.update();
|
||||
});
|
||||
|
||||
$('#addDataset').click(function() {
|
||||
var newDataset = {
|
||||
label: 'Dataset ' + config.data.datasets.length,
|
||||
borderColor: randomColor(0.4),
|
||||
backgroundColor: randomColor(0.5),
|
||||
pointBorderColor: randomColor(0.7),
|
||||
pointBackgroundColor: randomColor(0.5),
|
||||
pointBorderWidth: 1,
|
||||
data: [],
|
||||
};
|
||||
|
||||
for (var index = 0; index < config.data.labels.length; ++index) {
|
||||
newDataset.data.push(randomScalingFactor());
|
||||
}
|
||||
|
||||
config.data.datasets.push(newDataset);
|
||||
window.myRadar.update();
|
||||
});
|
||||
|
||||
$('#addData').click(function() {
|
||||
if (config.data.datasets.length > 0) {
|
||||
config.data.labels.push('dataset #' + config.data.labels.length);
|
||||
|
||||
$.each(config.data.datasets, function (i, dataset) {
|
||||
dataset.data.push(randomScalingFactor());
|
||||
});
|
||||
|
||||
window.myRadar.update();
|
||||
}
|
||||
});
|
||||
|
||||
$('#removeDataset').click(function() {
|
||||
config.data.datasets.splice(0, 1);
|
||||
window.myRadar.update();
|
||||
});
|
||||
|
||||
$('#removeData').click(function() {
|
||||
config.data.labels.pop(); // remove the label first
|
||||
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.data.pop();
|
||||
});
|
||||
|
||||
window.myRadar.update();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
+132
-36
@@ -1,43 +1,139 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Radar Chart</title>
|
||||
<script src="../Chart.js"></script>
|
||||
<meta name = "viewport" content = "initial-scale = 1, user-scalable = no">
|
||||
<style>
|
||||
canvas{
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="canvas" height="450" width="450"></canvas>
|
||||
|
||||
<head>
|
||||
<title>Radar Chart</title>
|
||||
<script src="../dist/Chart.bundle.js"></script>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
||||
<style>
|
||||
canvas {
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<script>
|
||||
<body>
|
||||
<div style="width:75%">
|
||||
<canvas id="canvas"></canvas>
|
||||
</div>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<button id="addDataset">Add Dataset</button>
|
||||
<button id="removeDataset">Remove Dataset</button>
|
||||
<button id="addData">Add Data</button>
|
||||
<button id="removeData">Remove Data</button>
|
||||
<script>
|
||||
var randomScalingFactor = function() {
|
||||
return Math.round(Math.random() * 100);
|
||||
};
|
||||
var randomColorFactor = function() {
|
||||
return Math.round(Math.random() * 255);
|
||||
};
|
||||
var randomColor = function(opacity) {
|
||||
return 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',' + (opacity || '.3') + ')';
|
||||
};
|
||||
|
||||
var radarChartData = {
|
||||
labels : ["Eating","Drinking","Sleeping","Designing","Coding","Partying","Running"],
|
||||
datasets : [
|
||||
{
|
||||
fillColor : "rgba(220,220,220,0.5)",
|
||||
strokeColor : "rgba(220,220,220,1)",
|
||||
pointColor : "rgba(220,220,220,1)",
|
||||
pointStrokeColor : "#fff",
|
||||
data : [65,59,90,81,56,55,40]
|
||||
},
|
||||
{
|
||||
fillColor : "rgba(151,187,205,0.5)",
|
||||
strokeColor : "rgba(151,187,205,1)",
|
||||
pointColor : "rgba(151,187,205,1)",
|
||||
pointStrokeColor : "#fff",
|
||||
data : [28,48,40,19,96,27,100]
|
||||
}
|
||||
]
|
||||
|
||||
}
|
||||
var config = {
|
||||
type: 'radar',
|
||||
data: {
|
||||
labels: ["Eating", "Drinking", "Sleeping", "Designing", "Coding", "Cycling", "Running"],
|
||||
datasets: [{
|
||||
label: "My First dataset",
|
||||
backgroundColor: "rgba(220,220,220,0.2)",
|
||||
pointBackgroundColor: "rgba(220,220,220,1)",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}, {
|
||||
label: 'Hidden dataset',
|
||||
hidden: true,
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
}, {
|
||||
label: "My Second dataset",
|
||||
backgroundColor: "rgba(151,187,205,0.2)",
|
||||
pointBackgroundColor: "rgba(151,187,205,1)",
|
||||
hoverPointBackgroundColor: "#fff",
|
||||
pointHighlightStroke: "rgba(151,187,205,1)",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
},]
|
||||
},
|
||||
options: {
|
||||
legend: {
|
||||
position: 'top',
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Chart.js Radar Chart'
|
||||
},
|
||||
scale: {
|
||||
reverse: false,
|
||||
ticks: {
|
||||
beginAtZero: true
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
window.onload = function() {
|
||||
window.myRadar = new Chart(document.getElementById("canvas"), config);
|
||||
};
|
||||
|
||||
$('#randomizeData').click(function() {
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.data = dataset.data.map(function() {
|
||||
return randomScalingFactor();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
window.myRadar.update();
|
||||
});
|
||||
|
||||
$('#addDataset').click(function() {
|
||||
var newDataset = {
|
||||
label: 'Dataset ' + config.data.datasets.length,
|
||||
borderColor: randomColor(0.4),
|
||||
backgroundColor: randomColor(0.5),
|
||||
pointBorderColor: randomColor(0.7),
|
||||
pointBackgroundColor: randomColor(0.5),
|
||||
pointBorderWidth: 1,
|
||||
data: [],
|
||||
};
|
||||
|
||||
for (var index = 0; index < config.data.labels.length; ++index) {
|
||||
newDataset.data.push(randomScalingFactor());
|
||||
}
|
||||
|
||||
config.data.datasets.push(newDataset);
|
||||
window.myRadar.update();
|
||||
});
|
||||
|
||||
$('#addData').click(function() {
|
||||
if (config.data.datasets.length > 0) {
|
||||
config.data.labels.push('dataset #' + config.data.labels.length);
|
||||
|
||||
$.each(config.data.datasets, function (i, dataset) {
|
||||
dataset.data.push(randomScalingFactor());
|
||||
});
|
||||
|
||||
window.myRadar.update();
|
||||
}
|
||||
});
|
||||
|
||||
$('#removeDataset').click(function() {
|
||||
config.data.datasets.splice(0, 1);
|
||||
window.myRadar.update();
|
||||
});
|
||||
|
||||
$('#removeData').click(function() {
|
||||
config.data.labels.pop(); // remove the label first
|
||||
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.data.pop();
|
||||
});
|
||||
|
||||
window.myRadar.update();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
var myRadar = new Chart(document.getElementById("canvas").getContext("2d")).Radar(radarChartData,{scaleShowLabels : false, pointLabelFontSize : 10});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Scatter Chart</title>
|
||||
<script src="../dist/Chart.bundle.js"></script>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
||||
<style>
|
||||
canvas {
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div style="width:75%">
|
||||
<div>
|
||||
<canvas id="canvas"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
var randomScalingFactor = function() {
|
||||
return Math.round(Math.random() * 10.0) * Math.pow(10, Math.ceil(Math.random() * 5));
|
||||
};
|
||||
var randomColor = function(opacity) {
|
||||
return 'rgba(' + Math.round(Math.random() * 255) + ',' + Math.round(Math.random() * 255) + ',' + Math.round(Math.random() * 255) + ',' + (opacity || '.3') + ')';
|
||||
};
|
||||
|
||||
var scatterChartData = {
|
||||
datasets: [{
|
||||
label: "V(node2)",
|
||||
data: [{
|
||||
x: 1,
|
||||
y: -1.711e-2,
|
||||
}, {
|
||||
x: 1.26,
|
||||
y: -2.708e-2,
|
||||
}, {
|
||||
x: 1.58,
|
||||
y: -4.285e-2,
|
||||
}, {
|
||||
x: 2.0,
|
||||
y: -6.772e-2,
|
||||
}, {
|
||||
x: 2.51,
|
||||
y: -1.068e-1,
|
||||
}, {
|
||||
x: 3.16,
|
||||
y: -1.681e-1,
|
||||
}, {
|
||||
x: 3.98,
|
||||
y: -2.635e-1,
|
||||
}, {
|
||||
x: 5.01,
|
||||
y: -4.106e-1,
|
||||
}, {
|
||||
x: 6.31,
|
||||
y: -6.339e-1,
|
||||
}, {
|
||||
x: 7.94,
|
||||
y: -9.659e-1,
|
||||
}, {
|
||||
x: 10.00,
|
||||
y: -1.445,
|
||||
}, {
|
||||
x: 12.6,
|
||||
y: -2.110,
|
||||
}, {
|
||||
x: 15.8,
|
||||
y: -2.992,
|
||||
}, {
|
||||
x: 20.0,
|
||||
y: -4.102,
|
||||
}, {
|
||||
x: 25.1,
|
||||
y: -5.429,
|
||||
}, {
|
||||
x: 31.6,
|
||||
y: -6.944,
|
||||
}, {
|
||||
x: 39.8,
|
||||
y: -8.607,
|
||||
}, {
|
||||
x: 50.1,
|
||||
y: -1.038e1,
|
||||
}, {
|
||||
x: 63.1,
|
||||
y: -1.223e1,
|
||||
}, {
|
||||
x: 79.4,
|
||||
y: -1.413e1,
|
||||
}, {
|
||||
x: 100.00,
|
||||
y: -1.607e1,
|
||||
}, {
|
||||
x: 126,
|
||||
y: -1.803e1,
|
||||
}, {
|
||||
x: 158,
|
||||
y: -2e1,
|
||||
}, {
|
||||
x: 200,
|
||||
y: -2.199e1,
|
||||
}, {
|
||||
x: 251,
|
||||
y: -2.398e1,
|
||||
}, {
|
||||
x: 316,
|
||||
y: -2.597e1,
|
||||
}, {
|
||||
x: 398,
|
||||
y: -2.797e1,
|
||||
}, {
|
||||
x: 501,
|
||||
y: -2.996e1,
|
||||
}, {
|
||||
x: 631,
|
||||
y: -3.196e1,
|
||||
}, {
|
||||
x: 794,
|
||||
y: -3.396e1,
|
||||
}, {
|
||||
x: 1000,
|
||||
y: -3.596e1,
|
||||
},]
|
||||
}]
|
||||
};
|
||||
|
||||
$.each(scatterChartData.datasets, function(i, dataset) {
|
||||
dataset.borderColor = randomColor(0.4);
|
||||
dataset.backgroundColor = randomColor(0.1);
|
||||
dataset.pointBorderColor = randomColor(0.7);
|
||||
dataset.pointBackgroundColor = randomColor(0.5);
|
||||
dataset.pointBorderWidth = 1;
|
||||
});
|
||||
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("canvas").getContext("2d");
|
||||
window.myScatter = Chart.Scatter(ctx, {
|
||||
data: scatterChartData,
|
||||
options: {
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Chart.js Scatter Chart - Logarithmic X-Axis'
|
||||
},
|
||||
scales: {
|
||||
xAxes: [{
|
||||
type: 'logarithmic',
|
||||
position: 'bottom',
|
||||
ticks: {
|
||||
userCallback: function(tick) {
|
||||
var remain = tick / (Math.pow(10, Math.floor(Chart.helpers.log10(tick))));
|
||||
if (remain === 1 || remain === 2 || remain === 5) {
|
||||
return tick.toString() + "Hz";
|
||||
}
|
||||
return '';
|
||||
},
|
||||
},
|
||||
scaleLabel: {
|
||||
labelString: 'Frequency',
|
||||
display: true,
|
||||
}
|
||||
}],
|
||||
yAxes: [{
|
||||
type: 'linear',
|
||||
ticks: {
|
||||
userCallback: function(tick) {
|
||||
return tick.toString() + "dB";
|
||||
}
|
||||
},
|
||||
scaleLabel: {
|
||||
labelString: 'Voltage',
|
||||
display: true
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,186 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Scatter Chart Multi Axis</title>
|
||||
<script src="../dist/Chart.bundle.js"></script>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
||||
<style>
|
||||
canvas {
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div style="width:75%">
|
||||
<div>
|
||||
<canvas id="canvas"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<script>
|
||||
var randomScalingFactor = function() {
|
||||
return (Math.random() > 0.5 ? 1.0 : -1.0) * Math.round(Math.random() * 100);
|
||||
};
|
||||
var randomColor = function(opacity) {
|
||||
return 'rgba(' + Math.round(Math.random() * 255) + ',' + Math.round(Math.random() * 255) + ',' + Math.round(Math.random() * 255) + ',' + (opacity || '.3') + ')';
|
||||
};
|
||||
|
||||
var scatterChartData = {
|
||||
datasets: [{
|
||||
label: "My First dataset",
|
||||
xAxisID: "x-axis-1",
|
||||
yAxisID: "y-axis-1",
|
||||
data: [{
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}]
|
||||
}, {
|
||||
label: "My Second dataset",
|
||||
xAxisID: "x-axis-1",
|
||||
yAxisID: "y-axis-2",
|
||||
data: [{
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}]
|
||||
}]
|
||||
};
|
||||
|
||||
$.each(scatterChartData.datasets, function(i, dataset) {
|
||||
dataset.borderColor = randomColor(0.4);
|
||||
dataset.backgroundColor = randomColor(0.1);
|
||||
dataset.pointBorderColor = randomColor(0.7);
|
||||
dataset.pointBackgroundColor = randomColor(0.5);
|
||||
dataset.pointBorderWidth = 1;
|
||||
});
|
||||
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("canvas").getContext("2d");
|
||||
window.myScatter = Chart.Scatter(ctx, {
|
||||
data: scatterChartData,
|
||||
options: {
|
||||
responsive: true,
|
||||
hoverMode: 'single',
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Chart.js Scatter Chart - Multi Axis'
|
||||
},
|
||||
scales: {
|
||||
xAxes: [{
|
||||
position: "bottom",
|
||||
gridLines: {
|
||||
zeroLineColor: "rgba(0,0,0,1)"
|
||||
}
|
||||
}],
|
||||
yAxes: [{
|
||||
type: "linear", // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
|
||||
display: true,
|
||||
position: "left",
|
||||
id: "y-axis-1",
|
||||
}, {
|
||||
type: "linear", // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
|
||||
display: true,
|
||||
position: "right",
|
||||
reverse: true,
|
||||
id: "y-axis-2",
|
||||
|
||||
// grid line settings
|
||||
gridLines: {
|
||||
drawOnChartArea: false, // only want the grid lines for one axis to show up
|
||||
},
|
||||
}],
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$('#randomizeData').click(function() {
|
||||
scatterChartData.datasets[0].data = [{
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}];
|
||||
scatterChartData.datasets[1].data = [{
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}];
|
||||
window.myScatter.update();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,177 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Scatter Chart</title>
|
||||
<script src="../dist/Chart.bundle.js"></script>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
||||
<style>
|
||||
canvas {
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div style="width:75%">
|
||||
<div>
|
||||
<canvas id="canvas"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<script>
|
||||
var randomScalingFactor = function() {
|
||||
return (Math.random() > 0.5 ? 1.0 : -1.0) * Math.round(Math.random() * 100);
|
||||
};
|
||||
var randomColor = function(opacity) {
|
||||
return 'rgba(' + Math.round(Math.random() * 255) + ',' + Math.round(Math.random() * 255) + ',' + Math.round(Math.random() * 255) + ',' + (opacity || '.3') + ')';
|
||||
};
|
||||
|
||||
var scatterChartData = {
|
||||
datasets: [{
|
||||
label: "My First dataset",
|
||||
data: [{
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}]
|
||||
}, {
|
||||
label: "My Second dataset",
|
||||
data: [{
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}]
|
||||
}]
|
||||
};
|
||||
|
||||
$.each(scatterChartData.datasets, function(i, dataset) {
|
||||
dataset.borderColor = randomColor(0.4);
|
||||
dataset.backgroundColor = randomColor(0.1);
|
||||
dataset.pointBorderColor = randomColor(0.7);
|
||||
dataset.pointBackgroundColor = randomColor(0.5);
|
||||
dataset.pointBorderWidth = 1;
|
||||
});
|
||||
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("canvas").getContext("2d");
|
||||
window.myScatter = Chart.Scatter(ctx, {
|
||||
data: scatterChartData,
|
||||
options: {
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Chart.js Scatter Chart'
|
||||
},
|
||||
scales: {
|
||||
xAxes: [{
|
||||
position: 'top',
|
||||
gridLines: {
|
||||
zeroLineColor: "rgba(0,255,0,1)"
|
||||
},
|
||||
scaleLabel: {
|
||||
display: true,
|
||||
labelString: 'x axis'
|
||||
}
|
||||
}],
|
||||
yAxes: [{
|
||||
position: 'right',
|
||||
gridLines: {
|
||||
zeroLineColor: "rgba(0,255,0,1)"
|
||||
},
|
||||
scaleLabel: {
|
||||
display: true,
|
||||
labelString: 'y axis'
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$('#randomizeData').click(function() {
|
||||
scatterChartData.datasets[0].data = [{
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}];
|
||||
scatterChartData.datasets[1].data = [{
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}]
|
||||
window.myScatter.update();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,155 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Doughnut Chart</title>
|
||||
<script src="../Chart.js"></script>
|
||||
<meta name = "viewport" content = "initial-scale = 1, user-scalable = no">
|
||||
<style>
|
||||
canvas{
|
||||
float: left;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div style="width:600px;height:600px;">
|
||||
<canvas id="doughnut" height="300" width="200"></canvas>
|
||||
<canvas id="line" height="300" width="200"></canvas>
|
||||
<canvas id="polarArea" height="300" width="200"></canvas>
|
||||
<canvas id="bar" height="300" width="200"></canvas>
|
||||
<canvas id="pie" height="300" width="200"></canvas>
|
||||
<canvas id="radar" height="300" width="200"></canvas>
|
||||
</div>
|
||||
|
||||
|
||||
<script>
|
||||
|
||||
var doughnutData = [
|
||||
{
|
||||
value: 30,
|
||||
color:"#F7464A"
|
||||
},
|
||||
{
|
||||
value : 50,
|
||||
color : "#46BFBD"
|
||||
},
|
||||
{
|
||||
value : 100,
|
||||
color : "#FDB45C"
|
||||
},
|
||||
{
|
||||
value : 40,
|
||||
color : "#949FB1"
|
||||
},
|
||||
{
|
||||
value : 120,
|
||||
color : "#4D5360"
|
||||
}
|
||||
|
||||
];
|
||||
var lineChartData = {
|
||||
labels : ["","","","","","",""],
|
||||
datasets : [
|
||||
{
|
||||
fillColor : "rgba(220,220,220,0.5)",
|
||||
strokeColor : "rgba(220,220,220,1)",
|
||||
pointColor : "rgba(220,220,220,1)",
|
||||
pointStrokeColor : "#fff",
|
||||
data : [65,59,90,81,56,55,40]
|
||||
},
|
||||
{
|
||||
fillColor : "rgba(151,187,205,0.5)",
|
||||
strokeColor : "rgba(151,187,205,1)",
|
||||
pointColor : "rgba(151,187,205,1)",
|
||||
pointStrokeColor : "#fff",
|
||||
data : [28,48,40,19,96,27,100]
|
||||
}
|
||||
]
|
||||
|
||||
};
|
||||
var pieData = [
|
||||
{
|
||||
value: 30,
|
||||
color:"#F38630"
|
||||
},
|
||||
{
|
||||
value : 50,
|
||||
color : "#E0E4CC"
|
||||
},
|
||||
{
|
||||
value : 100,
|
||||
color : "#69D2E7"
|
||||
}
|
||||
|
||||
];
|
||||
var barChartData = {
|
||||
labels : ["January","February","March","April","May","June","July"],
|
||||
datasets : [
|
||||
{
|
||||
fillColor : "rgba(220,220,220,0.5)",
|
||||
strokeColor : "rgba(220,220,220,1)",
|
||||
data : [65,59,90,81,56,55,40]
|
||||
},
|
||||
{
|
||||
fillColor : "rgba(151,187,205,0.5)",
|
||||
strokeColor : "rgba(151,187,205,1)",
|
||||
data : [28,48,40,19,96,27,100]
|
||||
}
|
||||
]
|
||||
|
||||
};
|
||||
var chartData = [
|
||||
{
|
||||
value : Math.random(),
|
||||
color: "#D97041"
|
||||
},
|
||||
{
|
||||
value : Math.random(),
|
||||
color: "#C7604C"
|
||||
},
|
||||
{
|
||||
value : Math.random(),
|
||||
color: "#21323D"
|
||||
},
|
||||
{
|
||||
value : Math.random(),
|
||||
color: "#9D9B7F"
|
||||
},
|
||||
{
|
||||
value : Math.random(),
|
||||
color: "#7D4F6D"
|
||||
},
|
||||
{
|
||||
value : Math.random(),
|
||||
color: "#584A5E"
|
||||
}
|
||||
];
|
||||
var radarChartData = {
|
||||
labels : ["","","","","","",""],
|
||||
datasets : [
|
||||
{
|
||||
fillColor : "rgba(220,220,220,0.5)",
|
||||
strokeColor : "rgba(220,220,220,1)",
|
||||
pointColor : "rgba(220,220,220,1)",
|
||||
pointStrokeColor : "#fff",
|
||||
data : [65,59,90,81,56,55,40]
|
||||
},
|
||||
{
|
||||
fillColor : "rgba(151,187,205,0.5)",
|
||||
strokeColor : "rgba(151,187,205,1)",
|
||||
pointColor : "rgba(151,187,205,1)",
|
||||
pointStrokeColor : "#fff",
|
||||
data : [28,48,40,19,96,27,100]
|
||||
}
|
||||
]
|
||||
|
||||
};
|
||||
new Chart(document.getElementById("doughnut").getContext("2d")).Doughnut(doughnutData);
|
||||
new Chart(document.getElementById("line").getContext("2d")).Line(lineChartData);
|
||||
new Chart(document.getElementById("radar").getContext("2d")).Radar(radarChartData);
|
||||
new Chart(document.getElementById("polarArea").getContext("2d")).PolarArea(chartData);
|
||||
new Chart(document.getElementById("bar").getContext("2d")).Bar(barChartData);
|
||||
new Chart(document.getElementById("pie").getContext("2d")).Pie(pieData);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,165 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Line Chart - Combo Time Scale</title>
|
||||
<script src="../../node_modules/moment/min/moment.min.js"></script>
|
||||
<script src="../../dist/Chart.bundle.js"></script>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
||||
<style>
|
||||
canvas {
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div style="width:75%;">
|
||||
<canvas id="canvas"></canvas>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<button id="addDataset">Add Dataset</button>
|
||||
<button id="removeDataset">Remove Dataset</button>
|
||||
<button id="addData">Add Data</button>
|
||||
<button id="removeData">Remove Data</button>
|
||||
<script>
|
||||
var timeFormat = 'MM/DD/YYYY HH:mm';
|
||||
|
||||
function randomScalingFactor() {
|
||||
return Math.round(Math.random() * 100 * (Math.random() > 0.5 ? -1 : 1));
|
||||
}
|
||||
|
||||
function randomColorFactor() {
|
||||
return Math.round(Math.random() * 255);
|
||||
}
|
||||
|
||||
function randomColor(opacity) {
|
||||
return 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',' + (opacity || '.3') + ')';
|
||||
}
|
||||
|
||||
function newDateString(days) {
|
||||
return moment().add(days, 'd').format(timeFormat);
|
||||
}
|
||||
|
||||
var config = {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: [newDateString(0), newDateString(1), newDateString(2), newDateString(3), newDateString(4), newDateString(5), newDateString(6)],
|
||||
datasets: [{
|
||||
type: 'bar',
|
||||
label: 'Dataset 1',
|
||||
backgroundColor: "rgba(151,187,205,0.5)",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
borderColor: 'white',
|
||||
borderWidth: 2
|
||||
}, {
|
||||
type: 'bar',
|
||||
label: 'Dataset 2',
|
||||
backgroundColor: "rgba(151,187,205,0.5)",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
borderColor: 'white',
|
||||
borderWidth: 2
|
||||
}, {
|
||||
type: 'line',
|
||||
label: 'Dataset 3',
|
||||
backgroundColor: "rgba(220,220,220,0.5)",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}, ]
|
||||
},
|
||||
options: {
|
||||
showLines: true,
|
||||
responsive: true,
|
||||
title:{
|
||||
display:true,
|
||||
text:"Chart.js Combo Time Scale"
|
||||
},
|
||||
scales: {
|
||||
xAxes: [{
|
||||
type: "time",
|
||||
display: true,
|
||||
time: {
|
||||
format: timeFormat,
|
||||
// round: 'day'
|
||||
}
|
||||
}],
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.borderColor = randomColor(0.4);
|
||||
dataset.backgroundColor = randomColor(0.5);
|
||||
dataset.pointBorderColor = randomColor(0.7);
|
||||
dataset.pointBackgroundColor = randomColor(0.5);
|
||||
dataset.pointBorderWidth = 1;
|
||||
});
|
||||
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("canvas").getContext("2d");
|
||||
window.myLine = new Chart(ctx, config);
|
||||
|
||||
};
|
||||
|
||||
$('#randomizeData').click(function() {
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.data = dataset.data.map(function() {
|
||||
return randomScalingFactor();
|
||||
});
|
||||
});
|
||||
|
||||
window.myLine.update();
|
||||
});
|
||||
|
||||
$('#addDataset').click(function() {
|
||||
var newDataset = {
|
||||
label: 'Dataset ' + config.data.datasets.length,
|
||||
borderColor: randomColor(0.4),
|
||||
backgroundColor: randomColor(0.5),
|
||||
pointBorderColor: randomColor(0.7),
|
||||
pointBackgroundColor: randomColor(0.5),
|
||||
pointBorderWidth: 1,
|
||||
data: [],
|
||||
};
|
||||
|
||||
for (var index = 0; index < config.data.labels.length; ++index) {
|
||||
newDataset.data.push(randomScalingFactor());
|
||||
}
|
||||
|
||||
config.data.datasets.push(newDataset);
|
||||
window.myLine.update();
|
||||
});
|
||||
|
||||
$('#addData').click(function() {
|
||||
if (config.data.datasets.length > 0) {
|
||||
config.data.labels.push(newDateString(config.data.labels.length));
|
||||
|
||||
for (var index = 0; index < config.data.datasets.length; ++index) {
|
||||
config.data.datasets[index].data.push(randomScalingFactor());
|
||||
}
|
||||
|
||||
window.myLine.update();
|
||||
}
|
||||
});
|
||||
|
||||
$('#removeDataset').click(function() {
|
||||
config.data.datasets.splice(0, 1);
|
||||
window.myLine.update();
|
||||
});
|
||||
|
||||
$('#removeData').click(function() {
|
||||
config.data.labels.splice(-1, 1); // remove the label first
|
||||
|
||||
config.data.datasets.forEach(function(dataset, datasetIndex) {
|
||||
config.data.datasets[datasetIndex].data.pop();
|
||||
});
|
||||
|
||||
window.myLine.update();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,164 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Time Scale Point Data</title>
|
||||
<script src="../../node_modules/moment/min/moment.min.js"></script>
|
||||
<script src="../../dist/Chart.bundle.js"></script>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
||||
<style>
|
||||
canvas {
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div style="width:75%;">
|
||||
<canvas id="canvas"></canvas>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<button id="addData">Add Data</button>
|
||||
<button id="removeData">Remove Data</button>
|
||||
<script>
|
||||
function randomScalingFactor() {
|
||||
return Math.round(Math.random() * 100 * (Math.random() > 0.5 ? -1 : 1));
|
||||
}
|
||||
|
||||
function randomColorFactor() {
|
||||
return Math.round(Math.random() * 255);
|
||||
}
|
||||
|
||||
function randomColor(opacity) {
|
||||
return 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',' + (opacity || '.3') + ')';
|
||||
}
|
||||
|
||||
function newDate(days) {
|
||||
return moment().add(days, 'd').toDate();
|
||||
}
|
||||
|
||||
function newDateString(days) {
|
||||
return moment().add(days, 'd').format();
|
||||
}
|
||||
|
||||
var config = {
|
||||
type: 'line',
|
||||
data: {
|
||||
datasets: [{
|
||||
label: "Dataset with string point data",
|
||||
data: [{
|
||||
x: newDateString(0),
|
||||
y: randomScalingFactor()
|
||||
}, {
|
||||
x: newDateString(2),
|
||||
y: randomScalingFactor()
|
||||
}, {
|
||||
x: newDateString(4),
|
||||
y: randomScalingFactor()
|
||||
}, {
|
||||
x: newDateString(5),
|
||||
y: randomScalingFactor()
|
||||
}],
|
||||
fill: false
|
||||
}, {
|
||||
label: "Dataset with date object point data",
|
||||
data: [{
|
||||
x: newDate(0),
|
||||
y: randomScalingFactor()
|
||||
}, {
|
||||
x: newDate(2),
|
||||
y: randomScalingFactor()
|
||||
}, {
|
||||
x: newDate(4),
|
||||
y: randomScalingFactor()
|
||||
}, {
|
||||
x: newDate(5),
|
||||
y: randomScalingFactor()
|
||||
}],
|
||||
fill: false
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
title:{
|
||||
display:true,
|
||||
text:"Chart.js Time Point Data"
|
||||
},
|
||||
scales: {
|
||||
xAxes: [{
|
||||
type: "time",
|
||||
display: true,
|
||||
scaleLabel: {
|
||||
display: true,
|
||||
labelString: 'Date'
|
||||
}
|
||||
}, ],
|
||||
yAxes: [{
|
||||
display: true,
|
||||
scaleLabel: {
|
||||
display: true,
|
||||
labelString: 'value'
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.borderColor = randomColor(0.4);
|
||||
dataset.backgroundColor = randomColor(0.5);
|
||||
dataset.pointBorderColor = randomColor(0.7);
|
||||
dataset.pointBackgroundColor = randomColor(0.5);
|
||||
dataset.pointBorderWidth = 1;
|
||||
});
|
||||
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("canvas").getContext("2d");
|
||||
window.myLine = new Chart(ctx, config);
|
||||
|
||||
};
|
||||
|
||||
$('#randomizeData').click(function() {
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
$.each(dataset.data, function(j, dataObj) {
|
||||
dataObj.y = randomScalingFactor();
|
||||
});
|
||||
});
|
||||
|
||||
window.myLine.update();
|
||||
});
|
||||
|
||||
$('#addData').click(function() {
|
||||
if (config.data.datasets.length > 0) {
|
||||
var lastTime = myLine.scales['x-axis-0'].labelMoments[0].length ? myLine.scales['x-axis-0'].labelMoments[0][myLine.scales['x-axis-0'].labelMoments[0].length - 1] : moment();
|
||||
var newTime = lastTime
|
||||
.clone()
|
||||
.add(1, 'day')
|
||||
.format('MM/DD/YYYY HH:mm');
|
||||
|
||||
for (var index = 0; index < config.data.datasets.length; ++index) {
|
||||
config.data.datasets[index].data.push({
|
||||
x: newTime,
|
||||
y: randomScalingFactor()
|
||||
});
|
||||
}
|
||||
|
||||
window.myLine.update();
|
||||
}
|
||||
});
|
||||
|
||||
$('#removeData').click(function() {
|
||||
config.data.datasets.forEach(function(dataset, datasetIndex) {
|
||||
dataset.data.pop();
|
||||
});
|
||||
|
||||
window.myLine.update();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,198 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Line Chart</title>
|
||||
<script src="../../node_modules/moment/min/moment.min.js"></script>
|
||||
<script src="../../dist/Chart.bundle.js"></script>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
||||
<style>
|
||||
canvas {
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div style="width:75%;">
|
||||
<canvas id="canvas"></canvas>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<button id="addDataset">Add Dataset</button>
|
||||
<button id="removeDataset">Remove Dataset</button>
|
||||
<button id="addData">Add Data</button>
|
||||
<button id="removeData">Remove Data</button>
|
||||
<script>
|
||||
var timeFormat = 'MM/DD/YYYY HH:mm';
|
||||
|
||||
function randomScalingFactor() {
|
||||
return Math.round(Math.random() * 100 * (Math.random() > 0.5 ? -1 : 1));
|
||||
}
|
||||
|
||||
function randomColorFactor() {
|
||||
return Math.round(Math.random() * 255);
|
||||
}
|
||||
|
||||
function randomColor(opacity) {
|
||||
return 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',' + (opacity || '.3') + ')';
|
||||
}
|
||||
|
||||
function newDate(days) {
|
||||
return moment().add(days, 'd').toDate();
|
||||
}
|
||||
|
||||
function newDateString(days) {
|
||||
return moment().add(days, 'd').format(timeFormat);
|
||||
}
|
||||
|
||||
function newTimestamp(days) {
|
||||
return moment().add(days, 'd').unix();
|
||||
}
|
||||
|
||||
var config = {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: [newDate(0), newDate(1), newDate(2), newDate(3), newDate(4), newDate(5), newDate(6)], // Date Objects
|
||||
datasets: [{
|
||||
label: "My First dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
fill: false,
|
||||
borderDash: [5, 5],
|
||||
}, {
|
||||
label: "My Second dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
}, {
|
||||
label: "Dataset with point data",
|
||||
data: [{
|
||||
x: newDateString(0),
|
||||
y: randomScalingFactor()
|
||||
}, {
|
||||
x: newDateString(5),
|
||||
y: randomScalingFactor()
|
||||
}, {
|
||||
x: newDateString(7),
|
||||
y: randomScalingFactor()
|
||||
}, {
|
||||
x: newDateString(15),
|
||||
y: randomScalingFactor()
|
||||
}],
|
||||
fill: false
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
title:{
|
||||
display:true,
|
||||
text:"Chart.js Time Scale"
|
||||
},
|
||||
scales: {
|
||||
xAxes: [{
|
||||
type: "time",
|
||||
time: {
|
||||
format: timeFormat,
|
||||
// round: 'day'
|
||||
tooltipFormat: 'll HH:mm'
|
||||
},
|
||||
scaleLabel: {
|
||||
display: true,
|
||||
labelString: 'Date'
|
||||
}
|
||||
}, ],
|
||||
yAxes: [{
|
||||
scaleLabel: {
|
||||
display: true,
|
||||
labelString: 'value'
|
||||
}
|
||||
}]
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.borderColor = randomColor(0.4);
|
||||
dataset.backgroundColor = randomColor(0.5);
|
||||
dataset.pointBorderColor = randomColor(0.7);
|
||||
dataset.pointBackgroundColor = randomColor(0.5);
|
||||
dataset.pointBorderWidth = 1;
|
||||
});
|
||||
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("canvas").getContext("2d");
|
||||
window.myLine = new Chart(ctx, config);
|
||||
|
||||
};
|
||||
|
||||
$('#randomizeData').click(function() {
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
$.each(dataset.data, function(j, dataObj) {
|
||||
if (typeof dataObj === 'object') {
|
||||
dataObj.y = randomScalingFactor();
|
||||
} else {
|
||||
dataset.data[j] = randomScalingFactor();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
window.myLine.update();
|
||||
});
|
||||
|
||||
$('#addDataset').click(function() {
|
||||
var newDataset = {
|
||||
label: 'Dataset ' + config.data.datasets.length,
|
||||
borderColor: randomColor(0.4),
|
||||
backgroundColor: randomColor(0.5),
|
||||
pointBorderColor: randomColor(0.7),
|
||||
pointBackgroundColor: randomColor(0.5),
|
||||
pointBorderWidth: 1,
|
||||
data: [],
|
||||
};
|
||||
|
||||
for (var index = 0; index < config.data.labels.length; ++index) {
|
||||
newDataset.data.push(randomScalingFactor());
|
||||
}
|
||||
|
||||
config.data.datasets.push(newDataset);
|
||||
window.myLine.update();
|
||||
});
|
||||
|
||||
$('#addData').click(function() {
|
||||
if (config.data.datasets.length > 0) {
|
||||
config.data.labels.push(newDate(config.data.labels.length));
|
||||
|
||||
for (var index = 0; index < config.data.datasets.length; ++index) {
|
||||
if (typeof config.data.datasets[index].data[0] === "object") {
|
||||
config.data.datasets[index].data.push({
|
||||
x: newDate(config.data.datasets[index].data.length),
|
||||
y: randomScalingFactor(),
|
||||
});
|
||||
} else {
|
||||
config.data.datasets[index].data.push(randomScalingFactor());
|
||||
}
|
||||
}
|
||||
|
||||
window.myLine.update();
|
||||
}
|
||||
});
|
||||
|
||||
$('#removeDataset').click(function() {
|
||||
config.data.datasets.splice(0, 1);
|
||||
window.myLine.update();
|
||||
});
|
||||
|
||||
$('#removeData').click(function() {
|
||||
config.data.labels.splice(-1, 1); // remove the label first
|
||||
|
||||
config.data.datasets.forEach(function(dataset, datasetIndex) {
|
||||
dataset.data.pop();
|
||||
});
|
||||
|
||||
window.myLine.update();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,183 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Line Chart</title>
|
||||
<script src="../dist/Chart.bundle.js"></script>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
||||
<style>
|
||||
canvas {
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div style="width:75%;">
|
||||
<canvas id="canvas"></canvas>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<button id="addDataset">Add Dataset</button>
|
||||
<button id="removeDataset">Remove Dataset</button>
|
||||
<button id="addData">Add Data</button>
|
||||
<button id="removeData">Remove Data</button>
|
||||
<script>
|
||||
var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
||||
|
||||
var randomScalingFactor = function() {
|
||||
return Math.round(Math.random() * 100 * (Math.random() > 0.5 ? -1 : 1));
|
||||
};
|
||||
var randomColorFactor = function() {
|
||||
return Math.round(Math.random() * 255);
|
||||
};
|
||||
var randomColor = function(opacity) {
|
||||
return 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',' + (opacity || '.3') + ')';
|
||||
};
|
||||
|
||||
var config = {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
||||
datasets: [{
|
||||
label: "My First dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
fill: false,
|
||||
borderDash: [5, 5],
|
||||
}, {
|
||||
label: "My Second dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
title:{
|
||||
display:true,
|
||||
text:"Chart.js Line Chart - Tooltip Hooks"
|
||||
},
|
||||
tooltips: {
|
||||
mode: 'label',
|
||||
callbacks: {
|
||||
beforeTitle: function() {
|
||||
return '...beforeTitle';
|
||||
},
|
||||
afterTitle: function() {
|
||||
return '...afterTitle';
|
||||
},
|
||||
beforeBody: function() {
|
||||
return '...beforeBody';
|
||||
},
|
||||
afterBody: function() {
|
||||
return '...afterBody';
|
||||
},
|
||||
beforeFooter: function() {
|
||||
return '...beforeFooter';
|
||||
},
|
||||
footer: function() {
|
||||
return 'Footer';
|
||||
},
|
||||
afterFooter: function() {
|
||||
return '...afterFooter';
|
||||
},
|
||||
}
|
||||
},
|
||||
hover: {
|
||||
mode: 'label'
|
||||
},
|
||||
scales: {
|
||||
xAxes: [{
|
||||
display: true,
|
||||
scaleLabel: {
|
||||
show: true,
|
||||
labelString: 'Month'
|
||||
}
|
||||
}],
|
||||
yAxes: [{
|
||||
display: true,
|
||||
scaleLabel: {
|
||||
show: true,
|
||||
labelString: 'Value'
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.borderColor = randomColor(0.4);
|
||||
dataset.backgroundColor = randomColor(0.5);
|
||||
dataset.pointBorderColor = randomColor(0.7);
|
||||
dataset.pointBackgroundColor = randomColor(0.5);
|
||||
dataset.pointBorderWidth = 1;
|
||||
});
|
||||
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("canvas").getContext("2d");
|
||||
window.myLine = new Chart(ctx, config);
|
||||
|
||||
};
|
||||
|
||||
$('#randomizeData').click(function() {
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.data = dataset.data.map(function() {
|
||||
return randomScalingFactor();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
window.myLine.update();
|
||||
});
|
||||
|
||||
$('#addDataset').click(function() {
|
||||
var newDataset = {
|
||||
label: 'Dataset ' + config.data.datasets.length,
|
||||
borderColor: randomColor(0.4),
|
||||
backgroundColor: randomColor(0.5),
|
||||
pointBorderColor: randomColor(0.7),
|
||||
pointBackgroundColor: randomColor(0.5),
|
||||
pointBorderWidth: 1,
|
||||
data: [],
|
||||
};
|
||||
|
||||
for (var index = 0; index < config.data.labels.length; ++index) {
|
||||
newDataset.data.push(randomScalingFactor());
|
||||
}
|
||||
|
||||
config.data.datasets.push(newDataset);
|
||||
window.myLine.update();
|
||||
});
|
||||
|
||||
$('#addData').click(function() {
|
||||
if (config.data.datasets.length > 0) {
|
||||
var month = MONTHS[config.data.labels.length % MONTHS.length];
|
||||
config.data.labels.push(month);
|
||||
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.data.push(randomScalingFactor());
|
||||
});
|
||||
|
||||
window.myLine.update();
|
||||
}
|
||||
});
|
||||
|
||||
$('#removeDataset').click(function() {
|
||||
config.data.datasets.splice(0, 1);
|
||||
window.myLine.update();
|
||||
});
|
||||
|
||||
$('#removeData').click(function() {
|
||||
config.data.labels.splice(-1, 1); // remove the label first
|
||||
|
||||
config.data.datasets.forEach(function(dataset, datasetIndex) {
|
||||
dataset.data.pop();
|
||||
});
|
||||
|
||||
window.myLine.update();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Arquivo binário não exibido.
|
Antes Largura: | Altura: | Tamanho: 78 KiB |
externo
-1443
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
externo
-320
@@ -1,320 +0,0 @@
|
||||
$(window).load(function() {
|
||||
var lineChartData = {
|
||||
labels : ["January","February","March","April","May","June","July"],
|
||||
datasets : [
|
||||
{
|
||||
fillColor : "rgba(220,220,220,0.5)",
|
||||
strokeColor : "rgba(220,220,220,1)",
|
||||
pointColor : "rgba(220,220,220,1)",
|
||||
pointStrokeColor : "#fff",
|
||||
data : [65,59,90,81,56,55,40]
|
||||
},
|
||||
{
|
||||
fillColor : "rgba(151,187,205,0.5)",
|
||||
strokeColor : "rgba(151,187,205,1)",
|
||||
pointColor : "rgba(151,187,205,1)",
|
||||
pointStrokeColor : "#fff",
|
||||
data : [28,48,40,19,96,27,100]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
var barChartData = {
|
||||
labels : ["January","February","March","April","May","June","July"],
|
||||
datasets : [
|
||||
{
|
||||
fillColor : "rgba(220,220,220,0.5)",
|
||||
strokeColor : "rgba(220,220,220,1)",
|
||||
data : [65,59,90,81,56,55,40]
|
||||
},
|
||||
{
|
||||
fillColor : "rgba(151,187,205,0.5)",
|
||||
strokeColor : "rgba(151,187,205,1)",
|
||||
data : [28,48,40,19,96,27,100]
|
||||
}
|
||||
]
|
||||
|
||||
};
|
||||
|
||||
var radarChartData = {
|
||||
labels : ["A","B","C","D","E","F","G"],
|
||||
datasets : [
|
||||
{
|
||||
fillColor : "rgba(220,220,220,0.5)",
|
||||
strokeColor : "rgba(220,220,220,1)",
|
||||
pointColor : "rgba(220,220,220,1)",
|
||||
pointStrokeColor : "#fff",
|
||||
data : [65,59,90,81,56,55,40]
|
||||
},
|
||||
{
|
||||
fillColor : "rgba(151,187,205,0.5)",
|
||||
strokeColor : "rgba(151,187,205,1)",
|
||||
pointColor : "rgba(151,187,205,1)",
|
||||
pointStrokeColor : "#fff",
|
||||
data : [28,48,40,19,96,27,100]
|
||||
}
|
||||
]
|
||||
|
||||
};
|
||||
var pieChartData = [
|
||||
{
|
||||
value: 30,
|
||||
color:"#F38630"
|
||||
},
|
||||
{
|
||||
value : 50,
|
||||
color : "#E0E4CC"
|
||||
},
|
||||
{
|
||||
value : 100,
|
||||
color : "#69D2E7"
|
||||
}
|
||||
|
||||
];
|
||||
var polarAreaChartData = [
|
||||
{
|
||||
value : 62,
|
||||
color: "#D97041"
|
||||
},
|
||||
{
|
||||
value : 70,
|
||||
color: "#C7604C"
|
||||
},
|
||||
{
|
||||
value : 41,
|
||||
color: "#21323D"
|
||||
},
|
||||
{
|
||||
value : 24,
|
||||
color: "#9D9B7F"
|
||||
},
|
||||
{
|
||||
value : 55,
|
||||
color: "#7D4F6D"
|
||||
},
|
||||
{
|
||||
value : 18,
|
||||
color: "#584A5E"
|
||||
}
|
||||
];
|
||||
var doughnutChartData = [
|
||||
{
|
||||
value: 30,
|
||||
color:"#F7464A"
|
||||
},
|
||||
{
|
||||
value : 50,
|
||||
color : "#46BFBD"
|
||||
},
|
||||
{
|
||||
value : 100,
|
||||
color : "#FDB45C"
|
||||
},
|
||||
{
|
||||
value : 40,
|
||||
color : "#949FB1"
|
||||
},
|
||||
{
|
||||
value : 120,
|
||||
color : "#4D5360"
|
||||
}
|
||||
|
||||
];
|
||||
|
||||
var globalGraphSettings = {animation : Modernizr.canvas};
|
||||
|
||||
setIntroChart();
|
||||
|
||||
function setIntroChart(){
|
||||
var ctx = document.getElementById("introChart").getContext("2d");
|
||||
|
||||
new Chart(ctx).Line(lineChartData,{animation: Modernizr.canvas, scaleShowLabels : false, scaleFontColor : "#767C8D"});
|
||||
};
|
||||
|
||||
function showLineChart(){
|
||||
var ctx = document.getElementById("lineChartCanvas").getContext("2d");
|
||||
new Chart(ctx).Line(lineChartData,globalGraphSettings);
|
||||
};
|
||||
function showBarChart(){
|
||||
var ctx = document.getElementById("barChartCanvas").getContext("2d");
|
||||
new Chart(ctx).Bar(barChartData,globalGraphSettings);
|
||||
};
|
||||
function showRadarChart(){
|
||||
var ctx = document.getElementById("radarChartCanvas").getContext("2d");
|
||||
new Chart(ctx).Radar(radarChartData,globalGraphSettings);
|
||||
}
|
||||
function showPolarAreaChart(){
|
||||
var ctx = document.getElementById("polarAreaChartCanvas").getContext("2d");
|
||||
new Chart(ctx).PolarArea(polarAreaChartData,globalGraphSettings);
|
||||
}
|
||||
function showPieChart(){
|
||||
var ctx = document.getElementById("pieChartCanvas").getContext("2d");
|
||||
new Chart(ctx).Pie(pieChartData,globalGraphSettings);
|
||||
};
|
||||
function showDoughnutChart(){
|
||||
var ctx = document.getElementById("doughnutChartCanvas").getContext("2d");
|
||||
new Chart(ctx).Doughnut(doughnutChartData,globalGraphSettings);
|
||||
};
|
||||
|
||||
var graphInitDelay = 300;
|
||||
|
||||
//Set up each of the inview events here.
|
||||
$("#lineChart").on("inview",function(){
|
||||
var $this = $(this);
|
||||
$this.removeClass("hidden").off("inview");
|
||||
setTimeout(showLineChart,graphInitDelay);
|
||||
});
|
||||
$("#barChart").on("inview",function(){
|
||||
var $this = $(this);
|
||||
$this.removeClass("hidden").off("inview");
|
||||
setTimeout(showBarChart,graphInitDelay);
|
||||
});
|
||||
|
||||
$("#radarChart").on("inview",function(){
|
||||
var $this = $(this);
|
||||
$this.removeClass("hidden").off("inview");
|
||||
setTimeout(showRadarChart,graphInitDelay);
|
||||
});
|
||||
$("#pieChart").on("inview",function(){
|
||||
var $this = $(this);
|
||||
$this.removeClass("hidden").off("inview");
|
||||
setTimeout(showPieChart,graphInitDelay);
|
||||
});
|
||||
$("#polarAreaChart").on("inview",function(){
|
||||
var $this = $(this);
|
||||
$this.removeClass("hidden").off("inview");
|
||||
setTimeout(showPolarAreaChart,graphInitDelay);
|
||||
});
|
||||
$("#doughnutChart").on("inview",function(){
|
||||
var $this = $(this);
|
||||
$this.removeClass("hidden").off("inview");
|
||||
setTimeout(showDoughnutChart,graphInitDelay);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
* author Christopher Blum
|
||||
* - based on the idea of Remy Sharp, http://remysharp.com/2009/01/26/element-in-view-event-plugin/
|
||||
* - forked from http://github.com/zuk/jquery.inview/
|
||||
*/
|
||||
(function ($) {
|
||||
var inviewObjects = {}, viewportSize, viewportOffset,
|
||||
d = document, w = window, documentElement = d.documentElement, expando = $.expando;
|
||||
|
||||
$.event.special.inview = {
|
||||
add: function(data) {
|
||||
inviewObjects[data.guid + "-" + this[expando]] = { data: data, $element: $(this) };
|
||||
},
|
||||
|
||||
remove: function(data) {
|
||||
try { delete inviewObjects[data.guid + "-" + this[expando]]; } catch(e) {}
|
||||
}
|
||||
};
|
||||
|
||||
function getViewportSize() {
|
||||
var mode, domObject, size = { height: w.innerHeight, width: w.innerWidth };
|
||||
|
||||
// if this is correct then return it. iPad has compat Mode, so will
|
||||
// go into check clientHeight/clientWidth (which has the wrong value).
|
||||
if (!size.height) {
|
||||
mode = d.compatMode;
|
||||
if (mode || !$.support.boxModel) { // IE, Gecko
|
||||
domObject = mode === 'CSS1Compat' ?
|
||||
documentElement : // Standards
|
||||
d.body; // Quirks
|
||||
size = {
|
||||
height: domObject.clientHeight,
|
||||
width: domObject.clientWidth
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
function getViewportOffset() {
|
||||
return {
|
||||
top: w.pageYOffset || documentElement.scrollTop || d.body.scrollTop,
|
||||
left: w.pageXOffset || documentElement.scrollLeft || d.body.scrollLeft
|
||||
};
|
||||
}
|
||||
|
||||
function checkInView() {
|
||||
var $elements = $(), elementsLength, i = 0;
|
||||
|
||||
$.each(inviewObjects, function(i, inviewObject) {
|
||||
var selector = inviewObject.data.selector,
|
||||
$element = inviewObject.$element;
|
||||
$elements = $elements.add(selector ? $element.find(selector) : $element);
|
||||
});
|
||||
|
||||
elementsLength = $elements.length;
|
||||
if (elementsLength) {
|
||||
viewportSize = viewportSize || getViewportSize();
|
||||
viewportOffset = viewportOffset || getViewportOffset();
|
||||
|
||||
for (; i<elementsLength; i++) {
|
||||
// Ignore elements that are not in the DOM tree
|
||||
if (!$.contains(documentElement, $elements[i])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var $element = $($elements[i]),
|
||||
elementSize = { height: $element.height(), width: $element.width() },
|
||||
elementOffset = $element.offset(),
|
||||
inView = $element.data('inview'),
|
||||
visiblePartX,
|
||||
visiblePartY,
|
||||
visiblePartsMerged;
|
||||
|
||||
// Don't ask me why because I haven't figured out yet:
|
||||
// viewportOffset and viewportSize are sometimes suddenly null in Firefox 5.
|
||||
// Even though it sounds weird:
|
||||
// It seems that the execution of this function is interferred by the onresize/onscroll event
|
||||
// where viewportOffset and viewportSize are unset
|
||||
if (!viewportOffset || !viewportSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (elementOffset.top + elementSize.height > viewportOffset.top &&
|
||||
elementOffset.top < viewportOffset.top + viewportSize.height &&
|
||||
elementOffset.left + elementSize.width > viewportOffset.left &&
|
||||
elementOffset.left < viewportOffset.left + viewportSize.width) {
|
||||
visiblePartX = (viewportOffset.left > elementOffset.left ?
|
||||
'right' : (viewportOffset.left + viewportSize.width) < (elementOffset.left + elementSize.width) ?
|
||||
'left' : 'both');
|
||||
visiblePartY = (viewportOffset.top > elementOffset.top ?
|
||||
'bottom' : (viewportOffset.top + viewportSize.height) < (elementOffset.top + elementSize.height) ?
|
||||
'top' : 'both');
|
||||
visiblePartsMerged = visiblePartX + "-" + visiblePartY;
|
||||
if (!inView || inView !== visiblePartsMerged) {
|
||||
$element.data('inview', visiblePartsMerged).trigger('inview', [true, visiblePartX, visiblePartY]);
|
||||
}
|
||||
} else if (inView) {
|
||||
$element.data('inview', false).trigger('inview', [false]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$(w).bind("scroll resize", function() {
|
||||
viewportSize = viewportOffset = null;
|
||||
});
|
||||
|
||||
// IE < 9 scrolls to focused elements without firing the "scroll" event
|
||||
if (!documentElement.addEventListener && documentElement.attachEvent) {
|
||||
documentElement.attachEvent("onfocusin", function() {
|
||||
viewportOffset = null;
|
||||
});
|
||||
}
|
||||
|
||||
// Use setInterval in order to also make sure this captures elements within
|
||||
// "overflow:scroll" elements or elements that appeared in the dom tree due to
|
||||
// dom manipulation and reflow
|
||||
// old: $(window).scroll(checkInView);
|
||||
//
|
||||
// By the way, iOS (iPad, iPhone, ...) seems to not execute, or at least delays
|
||||
// intervals while the user scrolls. Therefore the inview event might fire a bit late there
|
||||
setInterval(checkInView, 250);
|
||||
})(jQuery);
|
||||
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
Arquivo binário não exibido.
|
Antes Largura: | Altura: | Tamanho: 82 KiB |
Arquivo binário não exibido.
|
Antes Largura: | Altura: | Tamanho: 47 KiB |
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
@@ -1,205 +0,0 @@
|
||||
* {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
color: inherit;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
text-rendering: optimizeLegibility;
|
||||
}
|
||||
body {
|
||||
color: #282b36;
|
||||
border-top: 8px solid #282b36;
|
||||
}
|
||||
canvas {
|
||||
font-family: "proxima-nova", sans-serif sans-serif;
|
||||
}
|
||||
.redBorder,
|
||||
.greenBorder,
|
||||
.yellowBorder {
|
||||
width: 33.33%;
|
||||
float: left;
|
||||
height: 8px;
|
||||
}
|
||||
.redBorder {
|
||||
background-color: #f33e6f;
|
||||
}
|
||||
.greenBorder {
|
||||
background-color: #46bfbd;
|
||||
}
|
||||
.yellowBorder {
|
||||
background-color: #fdb45c;
|
||||
}
|
||||
h1 {
|
||||
font-family: "proxima-nova", sans-serif;
|
||||
font-weight: 600;
|
||||
font-size: 55px;
|
||||
margin-top: 40px;
|
||||
}
|
||||
h2 {
|
||||
font-family: "proxima-nova", sans-serif;
|
||||
font-weight: 400;
|
||||
margin-top: 20px;
|
||||
font-size: 26px;
|
||||
line-height: 40px;
|
||||
}
|
||||
h3 {
|
||||
font-family: "proxima-nova", sans-serif;
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
margin: 20px 0;
|
||||
}
|
||||
h3 a {
|
||||
color: #2d91ea;
|
||||
text-decoration: none;
|
||||
border-bottom: 1px solid #2d91ea;
|
||||
}
|
||||
p {
|
||||
font-family: "proxima-nova", sans-serif;
|
||||
line-height: 24px;
|
||||
font-size: 18px;
|
||||
color: #767c8d;
|
||||
}
|
||||
.btn {
|
||||
display: inline-block;
|
||||
padding: 20px;
|
||||
font-family: "proxima-nova", sans-serif;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
border-radius: 5px;
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
-webkit-transition-property: background-color box-shadow;
|
||||
-webkit-transition-duration: 200ms;
|
||||
-webkit-transition-timing-function: ease-in-out;
|
||||
-moz-transition-property: background-color box-shadow;
|
||||
-moz-transition-duration: 200ms;
|
||||
-moz-transition-timing-function: ease-in-out;
|
||||
-ms-transition-property: background-color box-shadow;
|
||||
-ms-transition-duration: 200ms;
|
||||
-ms-transition-timing-function: ease-in-out;
|
||||
-o-transition-property: background-color box-shadow;
|
||||
-o-transition-duration: 200ms;
|
||||
-o-transition-timing-function: ease-in-out;
|
||||
transition-property: background-color box-shadow;
|
||||
transition-duration: 200ms;
|
||||
transition-timing-function: ease-in-out;
|
||||
}
|
||||
.btn:active {
|
||||
box-shadow: inset 1px 1px 4px rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
.btn.red {
|
||||
background-color: #f33e6f;
|
||||
}
|
||||
.btn.red:hover {
|
||||
background-color: #f2265d;
|
||||
}
|
||||
.btn.blue {
|
||||
background-color: #2d91ea;
|
||||
}
|
||||
.btn.blue:hover {
|
||||
background-color: #1785e6;
|
||||
}
|
||||
header {
|
||||
width: 978px;
|
||||
margin: 20px auto;
|
||||
display: block;
|
||||
position: relative;
|
||||
}
|
||||
header hgroup {
|
||||
width: 50%;
|
||||
padding: 20px 0;
|
||||
}
|
||||
header #introChart {
|
||||
position: absolute;
|
||||
top: 60px;
|
||||
right: 0;
|
||||
}
|
||||
header .btn {
|
||||
margin-right: 10px;
|
||||
width: 180px;
|
||||
}
|
||||
footer {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
background-color: #ebebeb;
|
||||
}
|
||||
footer p {
|
||||
color: #767c8d;
|
||||
font-family: "proxima-nova", sans-serif;
|
||||
font-size: 16px;
|
||||
padding: 20px 0;
|
||||
}
|
||||
section {
|
||||
width: 978px;
|
||||
margin: 40px auto;
|
||||
}
|
||||
section:before {
|
||||
content: '';
|
||||
width: 600px;
|
||||
margin: 0 auto;
|
||||
border-top: 1px solid #ebebeb;
|
||||
height: 20px;
|
||||
display: block;
|
||||
}
|
||||
section:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
*section {
|
||||
zoom: 1;
|
||||
}
|
||||
#features article {
|
||||
width: 33.33%;
|
||||
float: left;
|
||||
}
|
||||
#features article p {
|
||||
display: block;
|
||||
width: 90%;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
}
|
||||
#features article img {
|
||||
width: 250px;
|
||||
height: 250px;
|
||||
margin: 0 auto;
|
||||
display: block;
|
||||
}
|
||||
#examples article {
|
||||
-webkit-transition: opacity 200ms ease-in-out;
|
||||
-ms-transition: opacity 200ms ease-in-out;
|
||||
-moz-transition: opacity 200ms ease-in-out;
|
||||
-o-transition: opacity 200ms ease-in-out;
|
||||
transition: opacity 200ms ease-in-out;
|
||||
position: relative;
|
||||
margin-top: 20px;
|
||||
clear: both;
|
||||
}
|
||||
#examples article:after {
|
||||
content: '';
|
||||
width: 600px;
|
||||
padding-top: 40px;
|
||||
margin: 40px auto;
|
||||
border-bottom: 1px solid #ebebeb;
|
||||
height: 20px;
|
||||
display: block;
|
||||
clear: both;
|
||||
}
|
||||
#examples article p {
|
||||
margin-top: 10px;
|
||||
}
|
||||
#examples article .half {
|
||||
width: 50%;
|
||||
float: left;
|
||||
}
|
||||
#examples article .canvasWrapper {
|
||||
float: left;
|
||||
width: 449px;
|
||||
padding: 0 20px;
|
||||
}
|
||||
#examples h3 {
|
||||
clear: both;
|
||||
}
|
||||
#examples .hidden {
|
||||
opacity: 0;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*!
|
||||
* Chart.js
|
||||
* http://chartjs.org/
|
||||
* Version: {{ version }}
|
||||
*
|
||||
* Copyright 2015 Nick Downie
|
||||
* Released under the MIT license
|
||||
* https://github.com/nnnick/Chart.js/blob/master/LICENSE.md
|
||||
*/
|
||||
|
||||
|
||||
var Chart = require('./core/core.js')();
|
||||
|
||||
require('./core/core.helpers')(Chart);
|
||||
require('./core/core.element')(Chart);
|
||||
require('./core/core.animation')(Chart);
|
||||
require('./core/core.controller')(Chart);
|
||||
require('./core/core.datasetController')(Chart);
|
||||
require('./core/core.layoutService')(Chart);
|
||||
require('./core/core.legend')(Chart);
|
||||
require('./core/core.scale')(Chart);
|
||||
require('./core/core.scaleService')(Chart);
|
||||
require('./core/core.title')(Chart);
|
||||
require('./core/core.tooltip')(Chart);
|
||||
|
||||
require('./controllers/controller.bar')(Chart);
|
||||
require('./controllers/controller.bubble')(Chart);
|
||||
require('./controllers/controller.doughnut')(Chart);
|
||||
require('./controllers/controller.line')(Chart);
|
||||
require('./controllers/controller.polarArea')(Chart);
|
||||
require('./controllers/controller.radar')(Chart);
|
||||
|
||||
require('./scales/scale.category')(Chart);
|
||||
require('./scales/scale.linear')(Chart);
|
||||
require('./scales/scale.logarithmic')(Chart);
|
||||
require('./scales/scale.radialLinear')(Chart);
|
||||
require('./scales/scale.time')(Chart);
|
||||
|
||||
require('./elements/element.arc')(Chart);
|
||||
require('./elements/element.line')(Chart);
|
||||
require('./elements/element.point')(Chart);
|
||||
require('./elements/element.rectangle')(Chart);
|
||||
|
||||
require('./charts/Chart.Bar')(Chart);
|
||||
require('./charts/Chart.Bubble')(Chart);
|
||||
require('./charts/Chart.Doughnut')(Chart);
|
||||
require('./charts/Chart.Line')(Chart);
|
||||
require('./charts/Chart.PolarArea')(Chart);
|
||||
require('./charts/Chart.Radar')(Chart);
|
||||
require('./charts/Chart.Scatter')(Chart);
|
||||
|
||||
window.Chart = module.exports = Chart;
|
||||
@@ -0,0 +1,11 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = function(Chart) {
|
||||
|
||||
Chart.Bar = function(context, config) {
|
||||
config.type = 'bar';
|
||||
|
||||
return new Chart(context, config);
|
||||
};
|
||||
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = function(Chart) {
|
||||
|
||||
Chart.Bubble = function(context, config) {
|
||||
config.type = 'bubble';
|
||||
return new Chart(context, config);
|
||||
};
|
||||
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = function(Chart) {
|
||||
|
||||
Chart.Doughnut = function(context, config) {
|
||||
config.type = 'doughnut';
|
||||
|
||||
return new Chart(context, config);
|
||||
};
|
||||
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = function(Chart) {
|
||||
|
||||
Chart.Line = function(context, config) {
|
||||
config.type = 'line';
|
||||
|
||||
return new Chart(context, config);
|
||||
};
|
||||
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = function(Chart) {
|
||||
|
||||
Chart.PolarArea = function(context, config) {
|
||||
config.type = 'polarArea';
|
||||
|
||||
return new Chart(context, config);
|
||||
};
|
||||
|
||||
};
|
||||
@@ -0,0 +1,18 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = function(Chart) {
|
||||
|
||||
var helpers = Chart.helpers;
|
||||
|
||||
var defaultConfig = {
|
||||
aspectRatio: 1
|
||||
};
|
||||
|
||||
Chart.Radar = function(context, config) {
|
||||
config.options = helpers.configMerge(defaultConfig, config.options);
|
||||
config.type = 'radar';
|
||||
|
||||
return new Chart(context, config);
|
||||
};
|
||||
|
||||
};
|
||||
@@ -0,0 +1,47 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = function(Chart) {
|
||||
|
||||
var defaultConfig = {
|
||||
hover: {
|
||||
mode: 'single'
|
||||
},
|
||||
|
||||
scales: {
|
||||
xAxes: [{
|
||||
type: "linear", // scatter should not use a category axis
|
||||
position: "bottom",
|
||||
id: "x-axis-1" // need an ID so datasets can reference the scale
|
||||
}],
|
||||
yAxes: [{
|
||||
type: "linear",
|
||||
position: "left",
|
||||
id: "y-axis-1"
|
||||
}]
|
||||
},
|
||||
|
||||
tooltips: {
|
||||
callbacks: {
|
||||
title: function(tooltipItems, data) {
|
||||
// Title doesn't make sense for scatter since we format the data as a point
|
||||
return '';
|
||||
},
|
||||
label: function(tooltipItem, data) {
|
||||
return '(' + tooltipItem.xLabel + ', ' + tooltipItem.yLabel + ')';
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Register the default config for this type
|
||||
Chart.defaults.scatter = defaultConfig;
|
||||
|
||||
// Scatter charts use line controllers
|
||||
Chart.controllers.scatter = Chart.controllers.line;
|
||||
|
||||
Chart.Scatter = function(context, config) {
|
||||
config.type = 'scatter';
|
||||
return new Chart(context, config);
|
||||
};
|
||||
|
||||
};
|
||||
@@ -0,0 +1,306 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = function(Chart) {
|
||||
|
||||
var helpers = Chart.helpers;
|
||||
|
||||
Chart.defaults.bar = {
|
||||
hover: {
|
||||
mode: "label"
|
||||
},
|
||||
|
||||
scales: {
|
||||
xAxes: [{
|
||||
type: "category",
|
||||
|
||||
// Specific to Bar Controller
|
||||
categoryPercentage: 0.8,
|
||||
barPercentage: 0.9,
|
||||
|
||||
// grid line settings
|
||||
gridLines: {
|
||||
offsetGridLines: true
|
||||
}
|
||||
}],
|
||||
yAxes: [{
|
||||
type: "linear"
|
||||
}]
|
||||
}
|
||||
};
|
||||
|
||||
Chart.controllers.bar = Chart.DatasetController.extend({
|
||||
initialize: function(chart, datasetIndex) {
|
||||
Chart.DatasetController.prototype.initialize.call(this, chart, datasetIndex);
|
||||
|
||||
// Use this to indicate that this is a bar dataset.
|
||||
this.getDataset().bar = true;
|
||||
},
|
||||
// Get the number of datasets that display bars. We use this to correctly calculate the bar width
|
||||
getBarCount: function getBarCount() {
|
||||
var barCount = 0;
|
||||
helpers.each(this.chart.data.datasets, function(dataset) {
|
||||
if (helpers.isDatasetVisible(dataset) && dataset.bar) {
|
||||
++barCount;
|
||||
}
|
||||
});
|
||||
return barCount;
|
||||
},
|
||||
|
||||
addElements: function() {
|
||||
this.getDataset().metaData = this.getDataset().metaData || [];
|
||||
helpers.each(this.getDataset().data, function(value, index) {
|
||||
this.getDataset().metaData[index] = this.getDataset().metaData[index] || new Chart.elements.Rectangle({
|
||||
_chart: this.chart.chart,
|
||||
_datasetIndex: this.index,
|
||||
_index: index
|
||||
});
|
||||
}, this);
|
||||
},
|
||||
addElementAndReset: function(index) {
|
||||
this.getDataset().metaData = this.getDataset().metaData || [];
|
||||
var rectangle = new Chart.elements.Rectangle({
|
||||
_chart: this.chart.chart,
|
||||
_datasetIndex: this.index,
|
||||
_index: index
|
||||
});
|
||||
|
||||
var numBars = this.getBarCount();
|
||||
|
||||
this.updateElement(rectangle, index, true, numBars);
|
||||
this.getDataset().metaData.splice(index, 0, rectangle);
|
||||
},
|
||||
|
||||
update: function update(reset) {
|
||||
var numBars = this.getBarCount();
|
||||
|
||||
helpers.each(this.getDataset().metaData, function(rectangle, index) {
|
||||
this.updateElement(rectangle, index, reset, numBars);
|
||||
}, this);
|
||||
},
|
||||
|
||||
updateElement: function updateElement(rectangle, index, reset, numBars) {
|
||||
|
||||
var xScale = this.getScaleForId(this.getDataset().xAxisID);
|
||||
var yScale = this.getScaleForId(this.getDataset().yAxisID);
|
||||
|
||||
var yScalePoint;
|
||||
|
||||
if (yScale.min < 0 && yScale.max < 0) {
|
||||
// all less than 0. use the top
|
||||
yScalePoint = yScale.getPixelForValue(yScale.max);
|
||||
} else if (yScale.min > 0 && yScale.max > 0) {
|
||||
yScalePoint = yScale.getPixelForValue(yScale.min);
|
||||
} else {
|
||||
yScalePoint = yScale.getPixelForValue(0);
|
||||
}
|
||||
|
||||
helpers.extend(rectangle, {
|
||||
// Utility
|
||||
_chart: this.chart.chart,
|
||||
_xScale: xScale,
|
||||
_yScale: yScale,
|
||||
_datasetIndex: this.index,
|
||||
_index: index,
|
||||
|
||||
|
||||
// Desired view properties
|
||||
_model: {
|
||||
x: this.calculateBarX(index, this.index),
|
||||
y: reset ? yScalePoint : this.calculateBarY(index, this.index),
|
||||
|
||||
// Tooltip
|
||||
label: this.chart.data.labels[index],
|
||||
datasetLabel: this.getDataset().label,
|
||||
|
||||
// Appearance
|
||||
base: reset ? yScalePoint : this.calculateBarBase(this.index, index),
|
||||
width: this.calculateBarWidth(numBars),
|
||||
backgroundColor: rectangle.custom && rectangle.custom.backgroundColor ? rectangle.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().backgroundColor, index, this.chart.options.elements.rectangle.backgroundColor),
|
||||
borderSkipped: rectangle.custom && rectangle.custom.borderSkipped ? rectangle.custom.borderSkipped : this.chart.options.elements.rectangle.borderSkipped,
|
||||
borderColor: rectangle.custom && rectangle.custom.borderColor ? rectangle.custom.borderColor : helpers.getValueAtIndexOrDefault(this.getDataset().borderColor, index, this.chart.options.elements.rectangle.borderColor),
|
||||
borderWidth: rectangle.custom && rectangle.custom.borderWidth ? rectangle.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.getDataset().borderWidth, index, this.chart.options.elements.rectangle.borderWidth)
|
||||
}
|
||||
});
|
||||
rectangle.pivot();
|
||||
},
|
||||
|
||||
calculateBarBase: function(datasetIndex, index) {
|
||||
|
||||
var xScale = this.getScaleForId(this.getDataset().xAxisID);
|
||||
var yScale = this.getScaleForId(this.getDataset().yAxisID);
|
||||
|
||||
var base = 0;
|
||||
|
||||
if (yScale.options.stacked) {
|
||||
|
||||
var value = this.chart.data.datasets[datasetIndex].data[index];
|
||||
|
||||
if (value < 0) {
|
||||
for (var i = 0; i < datasetIndex; i++) {
|
||||
var negDS = this.chart.data.datasets[i];
|
||||
if (helpers.isDatasetVisible(negDS) && negDS.yAxisID === yScale.id && negDS.bar) {
|
||||
base += negDS.data[index] < 0 ? negDS.data[index] : 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (var j = 0; j < datasetIndex; j++) {
|
||||
var posDS = this.chart.data.datasets[j];
|
||||
if (helpers.isDatasetVisible(posDS) && posDS.yAxisID === yScale.id && posDS.bar) {
|
||||
base += posDS.data[index] > 0 ? posDS.data[index] : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return yScale.getPixelForValue(base);
|
||||
}
|
||||
|
||||
base = yScale.getPixelForValue(yScale.min);
|
||||
|
||||
if (yScale.beginAtZero || ((yScale.min <= 0 && yScale.max >= 0) || (yScale.min >= 0 && yScale.max <= 0))) {
|
||||
base = yScale.getPixelForValue(0, 0);
|
||||
//base += yScale.options.gridLines.lineWidth;
|
||||
} else if (yScale.min < 0 && yScale.max < 0) {
|
||||
// All values are negative. Use the top as the base
|
||||
base = yScale.getPixelForValue(yScale.max);
|
||||
}
|
||||
|
||||
return base;
|
||||
|
||||
},
|
||||
|
||||
getRuler: function() {
|
||||
|
||||
var xScale = this.getScaleForId(this.getDataset().xAxisID);
|
||||
var yScale = this.getScaleForId(this.getDataset().yAxisID);
|
||||
var datasetCount = this.getBarCount();
|
||||
|
||||
var tickWidth = (function() {
|
||||
var min = xScale.getPixelForTick(1) - xScale.getPixelForTick(0);
|
||||
for (var i = 2; i < this.getDataset().data.length; i++) {
|
||||
min = Math.min(xScale.getPixelForTick(i) - xScale.getPixelForTick(i - 1), min);
|
||||
}
|
||||
return min;
|
||||
}).call(this);
|
||||
var categoryWidth = tickWidth * xScale.options.categoryPercentage;
|
||||
var categorySpacing = (tickWidth - (tickWidth * xScale.options.categoryPercentage)) / 2;
|
||||
var fullBarWidth = categoryWidth / datasetCount;
|
||||
var barWidth = fullBarWidth * xScale.options.barPercentage;
|
||||
var barSpacing = fullBarWidth - (fullBarWidth * xScale.options.barPercentage);
|
||||
|
||||
return {
|
||||
datasetCount: datasetCount,
|
||||
tickWidth: tickWidth,
|
||||
categoryWidth: categoryWidth,
|
||||
categorySpacing: categorySpacing,
|
||||
fullBarWidth: fullBarWidth,
|
||||
barWidth: barWidth,
|
||||
barSpacing: barSpacing
|
||||
};
|
||||
},
|
||||
|
||||
calculateBarWidth: function() {
|
||||
var xScale = this.getScaleForId(this.getDataset().xAxisID);
|
||||
var ruler = this.getRuler();
|
||||
return xScale.options.stacked ? ruler.categoryWidth : ruler.barWidth;
|
||||
},
|
||||
|
||||
// Get bar index from the given dataset index accounting for the fact that not all bars are visible
|
||||
getBarIndex: function(datasetIndex) {
|
||||
var barIndex = 0;
|
||||
|
||||
for (var j = 0; j < datasetIndex; ++j) {
|
||||
if (helpers.isDatasetVisible(this.chart.data.datasets[j]) && this.chart.data.datasets[j].bar) {
|
||||
++barIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return barIndex;
|
||||
},
|
||||
|
||||
calculateBarX: function(index, datasetIndex) {
|
||||
|
||||
var yScale = this.getScaleForId(this.getDataset().yAxisID);
|
||||
var xScale = this.getScaleForId(this.getDataset().xAxisID);
|
||||
var barIndex = this.getBarIndex(datasetIndex);
|
||||
|
||||
var ruler = this.getRuler();
|
||||
var leftTick = xScale.getPixelForValue(null, index, datasetIndex, this.chart.isCombo);
|
||||
leftTick -= this.chart.isCombo ? (ruler.tickWidth / 2) : 0;
|
||||
|
||||
if (xScale.options.stacked) {
|
||||
return leftTick + (ruler.categoryWidth / 2) + ruler.categorySpacing;
|
||||
}
|
||||
|
||||
return leftTick +
|
||||
(ruler.barWidth / 2) +
|
||||
ruler.categorySpacing +
|
||||
(ruler.barWidth * barIndex) +
|
||||
(ruler.barSpacing / 2) +
|
||||
(ruler.barSpacing * barIndex);
|
||||
},
|
||||
|
||||
calculateBarY: function(index, datasetIndex) {
|
||||
|
||||
var xScale = this.getScaleForId(this.getDataset().xAxisID);
|
||||
var yScale = this.getScaleForId(this.getDataset().yAxisID);
|
||||
|
||||
var value = this.getDataset().data[index];
|
||||
|
||||
if (yScale.options.stacked) {
|
||||
|
||||
var sumPos = 0,
|
||||
sumNeg = 0;
|
||||
|
||||
for (var i = 0; i < datasetIndex; i++) {
|
||||
var ds = this.chart.data.datasets[i];
|
||||
if (helpers.isDatasetVisible(ds) && ds.bar && ds.yAxisID === yScale.id) {
|
||||
if (ds.data[index] < 0) {
|
||||
sumNeg += ds.data[index] || 0;
|
||||
} else {
|
||||
sumPos += ds.data[index] || 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (value < 0) {
|
||||
return yScale.getPixelForValue(sumNeg + value);
|
||||
} else {
|
||||
return yScale.getPixelForValue(sumPos + value);
|
||||
}
|
||||
|
||||
return yScale.getPixelForValue(value);
|
||||
}
|
||||
|
||||
return yScale.getPixelForValue(value);
|
||||
},
|
||||
|
||||
draw: function(ease) {
|
||||
var easingDecimal = ease || 1;
|
||||
helpers.each(this.getDataset().metaData, function(rectangle, index) {
|
||||
var d = this.getDataset().data[index];
|
||||
if (d !== null && d !== undefined && !isNaN(d)) {
|
||||
rectangle.transition(easingDecimal).draw();
|
||||
}
|
||||
}, this);
|
||||
},
|
||||
|
||||
setHoverStyle: function(rectangle) {
|
||||
var dataset = this.chart.data.datasets[rectangle._datasetIndex];
|
||||
var index = rectangle._index;
|
||||
|
||||
rectangle._model.backgroundColor = rectangle.custom && rectangle.custom.hoverBackgroundColor ? rectangle.custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.hoverBackgroundColor, index, helpers.color(rectangle._model.backgroundColor).saturate(0.5).darken(0.1).rgbString());
|
||||
rectangle._model.borderColor = rectangle.custom && rectangle.custom.hoverBorderColor ? rectangle.custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.hoverBorderColor, index, helpers.color(rectangle._model.borderColor).saturate(0.5).darken(0.1).rgbString());
|
||||
rectangle._model.borderWidth = rectangle.custom && rectangle.custom.hoverBorderWidth ? rectangle.custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.hoverBorderWidth, index, rectangle._model.borderWidth);
|
||||
},
|
||||
|
||||
removeHoverStyle: function(rectangle) {
|
||||
var dataset = this.chart.data.datasets[rectangle._datasetIndex];
|
||||
var index = rectangle._index;
|
||||
|
||||
rectangle._model.backgroundColor = rectangle.custom && rectangle.custom.backgroundColor ? rectangle.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().backgroundColor, index, this.chart.options.elements.rectangle.backgroundColor);
|
||||
rectangle._model.borderColor = rectangle.custom && rectangle.custom.borderColor ? rectangle.custom.borderColor : helpers.getValueAtIndexOrDefault(this.getDataset().borderColor, index, this.chart.options.elements.rectangle.borderColor);
|
||||
rectangle._model.borderWidth = rectangle.custom && rectangle.custom.borderWidth ? rectangle.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.getDataset().borderWidth, index, this.chart.options.elements.rectangle.borderWidth);
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,168 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = function(Chart) {
|
||||
|
||||
var helpers = Chart.helpers;
|
||||
|
||||
Chart.defaults.bubble = {
|
||||
hover: {
|
||||
mode: "single"
|
||||
},
|
||||
|
||||
scales: {
|
||||
xAxes: [{
|
||||
type: "linear", // bubble should probably use a linear scale by default
|
||||
position: "bottom",
|
||||
id: "x-axis-0" // need an ID so datasets can reference the scale
|
||||
}],
|
||||
yAxes: [{
|
||||
type: "linear",
|
||||
position: "left",
|
||||
id: "y-axis-0"
|
||||
}]
|
||||
},
|
||||
|
||||
tooltips: {
|
||||
callbacks: {
|
||||
title: function(tooltipItems, data) {
|
||||
// Title doesn't make sense for scatter since we format the data as a point
|
||||
return '';
|
||||
},
|
||||
label: function(tooltipItem, data) {
|
||||
var datasetLabel = data.datasets[tooltipItem.datasetIndex].label || '';
|
||||
var dataPoint = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
|
||||
return datasetLabel + ': (' + dataPoint.x + ', ' + dataPoint.y + ', ' + dataPoint.r + ')';
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Chart.controllers.bubble = Chart.DatasetController.extend({
|
||||
addElements: function() {
|
||||
|
||||
this.getDataset().metaData = this.getDataset().metaData || [];
|
||||
|
||||
helpers.each(this.getDataset().data, function(value, index) {
|
||||
this.getDataset().metaData[index] = this.getDataset().metaData[index] || new Chart.elements.Point({
|
||||
_chart: this.chart.chart,
|
||||
_datasetIndex: this.index,
|
||||
_index: index
|
||||
});
|
||||
}, this);
|
||||
},
|
||||
addElementAndReset: function(index) {
|
||||
this.getDataset().metaData = this.getDataset().metaData || [];
|
||||
var point = new Chart.elements.Point({
|
||||
_chart: this.chart.chart,
|
||||
_datasetIndex: this.index,
|
||||
_index: index
|
||||
});
|
||||
|
||||
// Reset the point
|
||||
this.updateElement(point, index, true);
|
||||
|
||||
// Add to the points array
|
||||
this.getDataset().metaData.splice(index, 0, point);
|
||||
},
|
||||
|
||||
update: function update(reset) {
|
||||
var points = this.getDataset().metaData;
|
||||
|
||||
var yScale = this.getScaleForId(this.getDataset().yAxisID);
|
||||
var xScale = this.getScaleForId(this.getDataset().xAxisID);
|
||||
var scaleBase;
|
||||
|
||||
if (yScale.min < 0 && yScale.max < 0) {
|
||||
scaleBase = yScale.getPixelForValue(yScale.max);
|
||||
} else if (yScale.min > 0 && yScale.max > 0) {
|
||||
scaleBase = yScale.getPixelForValue(yScale.min);
|
||||
} else {
|
||||
scaleBase = yScale.getPixelForValue(0);
|
||||
}
|
||||
|
||||
// Update Points
|
||||
helpers.each(points, function(point, index) {
|
||||
this.updateElement(point, index, reset);
|
||||
}, this);
|
||||
|
||||
},
|
||||
|
||||
updateElement: function(point, index, reset) {
|
||||
var yScale = this.getScaleForId(this.getDataset().yAxisID);
|
||||
var xScale = this.getScaleForId(this.getDataset().xAxisID);
|
||||
var scaleBase;
|
||||
|
||||
if (yScale.min < 0 && yScale.max < 0) {
|
||||
scaleBase = yScale.getPixelForValue(yScale.max);
|
||||
} else if (yScale.min > 0 && yScale.max > 0) {
|
||||
scaleBase = yScale.getPixelForValue(yScale.min);
|
||||
} else {
|
||||
scaleBase = yScale.getPixelForValue(0);
|
||||
}
|
||||
|
||||
helpers.extend(point, {
|
||||
// Utility
|
||||
_chart: this.chart.chart,
|
||||
_xScale: xScale,
|
||||
_yScale: yScale,
|
||||
_datasetIndex: this.index,
|
||||
_index: index,
|
||||
|
||||
// Desired view properties
|
||||
_model: {
|
||||
x: reset ? xScale.getPixelForDecimal(0.5) : xScale.getPixelForValue(this.getDataset().data[index], index, this.index, this.chart.isCombo),
|
||||
y: reset ? scaleBase : yScale.getPixelForValue(this.getDataset().data[index], index, this.index),
|
||||
// Appearance
|
||||
radius: reset ? 0 : point.custom && point.custom.radius ? point.custom.radius : this.getRadius(this.getDataset().data[index]),
|
||||
backgroundColor: point.custom && point.custom.backgroundColor ? point.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().backgroundColor, index, this.chart.options.elements.point.backgroundColor),
|
||||
borderColor: point.custom && point.custom.borderColor ? point.custom.borderColor : helpers.getValueAtIndexOrDefault(this.getDataset().borderColor, index, this.chart.options.elements.point.borderColor),
|
||||
borderWidth: point.custom && point.custom.borderWidth ? point.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.getDataset().borderWidth, index, this.chart.options.elements.point.borderWidth),
|
||||
|
||||
// Tooltip
|
||||
hitRadius: point.custom && point.custom.hitRadius ? point.custom.hitRadius : helpers.getValueAtIndexOrDefault(this.getDataset().hitRadius, index, this.chart.options.elements.point.hitRadius)
|
||||
}
|
||||
});
|
||||
|
||||
point._model.skip = point.custom && point.custom.skip ? point.custom.skip : (isNaN(point._model.x) || isNaN(point._model.y));
|
||||
|
||||
point.pivot();
|
||||
},
|
||||
|
||||
getRadius: function(value) {
|
||||
return value.r || this.chart.options.elements.point.radius;
|
||||
},
|
||||
|
||||
draw: function(ease) {
|
||||
var easingDecimal = ease || 1;
|
||||
|
||||
// Transition and Draw the Points
|
||||
helpers.each(this.getDataset().metaData, function(point, index) {
|
||||
point.transition(easingDecimal);
|
||||
point.draw();
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
setHoverStyle: function(point) {
|
||||
// Point
|
||||
var dataset = this.chart.data.datasets[point._datasetIndex];
|
||||
var index = point._index;
|
||||
|
||||
point._model.radius = point.custom && point.custom.hoverRadius ? point.custom.hoverRadius : (helpers.getValueAtIndexOrDefault(dataset.hoverRadius, index, this.chart.options.elements.point.hoverRadius)) + this.getRadius(this.getDataset().data[point._index]);
|
||||
point._model.backgroundColor = point.custom && point.custom.hoverBackgroundColor ? point.custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.hoverBackgroundColor, index, helpers.color(point._model.backgroundColor).saturate(0.5).darken(0.1).rgbString());
|
||||
point._model.borderColor = point.custom && point.custom.hoverBorderColor ? point.custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.hoverBorderColor, index, helpers.color(point._model.borderColor).saturate(0.5).darken(0.1).rgbString());
|
||||
point._model.borderWidth = point.custom && point.custom.hoverBorderWidth ? point.custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.hoverBorderWidth, index, point._model.borderWidth);
|
||||
},
|
||||
|
||||
removeHoverStyle: function(point) {
|
||||
var dataset = this.chart.data.datasets[point._datasetIndex];
|
||||
var index = point._index;
|
||||
|
||||
point._model.radius = point.custom && point.custom.radius ? point.custom.radius : this.getRadius(this.getDataset().data[point._index]);
|
||||
point._model.backgroundColor = point.custom && point.custom.backgroundColor ? point.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().backgroundColor, index, this.chart.options.elements.point.backgroundColor);
|
||||
point._model.borderColor = point.custom && point.custom.borderColor ? point.custom.borderColor : helpers.getValueAtIndexOrDefault(this.getDataset().borderColor, index, this.chart.options.elements.point.borderColor);
|
||||
point._model.borderWidth = point.custom && point.custom.borderWidth ? point.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.getDataset().borderWidth, index, this.chart.options.elements.point.borderWidth);
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,249 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = function(Chart) {
|
||||
|
||||
var helpers = Chart.helpers;
|
||||
|
||||
Chart.defaults.doughnut = {
|
||||
animation: {
|
||||
//Boolean - Whether we animate the rotation of the Doughnut
|
||||
animateRotate: true,
|
||||
//Boolean - Whether we animate scaling the Doughnut from the centre
|
||||
animateScale: false
|
||||
},
|
||||
aspectRatio: 1,
|
||||
hover: {
|
||||
mode: 'single'
|
||||
},
|
||||
legendCallback: function(chart) {
|
||||
var text = [];
|
||||
text.push('<ul class="' + chart.id + '-legend">');
|
||||
|
||||
if (chart.data.datasets.length) {
|
||||
for (var i = 0; i < chart.data.datasets[0].data.length; ++i) {
|
||||
text.push('<li><span style="background-color:' + chart.data.datasets[0].backgroundColor[i] + '">');
|
||||
if (chart.data.labels[i]) {
|
||||
text.push(chart.data.labels[i]);
|
||||
}
|
||||
text.push('</span></li>');
|
||||
}
|
||||
}
|
||||
|
||||
text.push('</ul>');
|
||||
return text.join("");
|
||||
},
|
||||
legend: {
|
||||
labels: {
|
||||
generateLabels: function(data) {
|
||||
if (data.labels.length && data.datasets.length) {
|
||||
return data.labels.map(function(label, i) {
|
||||
return {
|
||||
text: label,
|
||||
fillStyle: data.datasets[0].backgroundColor[i],
|
||||
hidden: isNaN(data.datasets[0].data[i]),
|
||||
|
||||
// Extra data used for toggling the correct item
|
||||
index: i
|
||||
};
|
||||
});
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
},
|
||||
onClick: function(e, legendItem) {
|
||||
helpers.each(this.chart.data.datasets, function(dataset) {
|
||||
dataset.metaHiddenData = dataset.metaHiddenData || [];
|
||||
var idx = legendItem.index;
|
||||
|
||||
if (!isNaN(dataset.data[idx])) {
|
||||
dataset.metaHiddenData[idx] = dataset.data[idx];
|
||||
dataset.data[idx] = NaN;
|
||||
} else if (!isNaN(dataset.metaHiddenData[idx])) {
|
||||
dataset.data[idx] = dataset.metaHiddenData[idx];
|
||||
}
|
||||
});
|
||||
|
||||
this.chart.update();
|
||||
}
|
||||
},
|
||||
|
||||
//The percentage of the chart that we cut out of the middle.
|
||||
cutoutPercentage: 50,
|
||||
|
||||
// Need to override these to give a nice default
|
||||
tooltips: {
|
||||
callbacks: {
|
||||
title: function() {
|
||||
return '';
|
||||
},
|
||||
label: function(tooltipItem, data) {
|
||||
return data.labels[tooltipItem.index] + ': ' + data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Chart.defaults.pie = helpers.clone(Chart.defaults.doughnut);
|
||||
helpers.extend(Chart.defaults.pie, {
|
||||
cutoutPercentage: 0
|
||||
});
|
||||
|
||||
|
||||
Chart.controllers.doughnut = Chart.controllers.pie = Chart.DatasetController.extend({
|
||||
linkScales: function() {
|
||||
// no scales for doughnut
|
||||
},
|
||||
|
||||
addElements: function() {
|
||||
this.getDataset().metaData = this.getDataset().metaData || [];
|
||||
helpers.each(this.getDataset().data, function(value, index) {
|
||||
this.getDataset().metaData[index] = this.getDataset().metaData[index] || new Chart.elements.Arc({
|
||||
_chart: this.chart.chart,
|
||||
_datasetIndex: this.index,
|
||||
_index: index
|
||||
});
|
||||
}, this);
|
||||
},
|
||||
addElementAndReset: function(index, colorForNewElement) {
|
||||
this.getDataset().metaData = this.getDataset().metaData || [];
|
||||
var arc = new Chart.elements.Arc({
|
||||
_chart: this.chart.chart,
|
||||
_datasetIndex: this.index,
|
||||
_index: index
|
||||
});
|
||||
|
||||
if (colorForNewElement && helpers.isArray(this.getDataset().backgroundColor)) {
|
||||
this.getDataset().backgroundColor.splice(index, 0, colorForNewElement);
|
||||
}
|
||||
|
||||
// Reset the point
|
||||
this.updateElement(arc, index, true);
|
||||
|
||||
// Add to the points array
|
||||
this.getDataset().metaData.splice(index, 0, arc);
|
||||
},
|
||||
|
||||
getVisibleDatasetCount: function getVisibleDatasetCount() {
|
||||
return helpers.where(this.chart.data.datasets, function(ds) {
|
||||
return helpers.isDatasetVisible(ds);
|
||||
}).length;
|
||||
},
|
||||
|
||||
// Get index of the dataset in relation to the visible datasets. This allows determining the inner and outer radius correctly
|
||||
getRingIndex: function getRingIndex(datasetIndex) {
|
||||
var ringIndex = 0;
|
||||
|
||||
for (var j = 0; j < datasetIndex; ++j) {
|
||||
if (helpers.isDatasetVisible(this.chart.data.datasets[j])) {
|
||||
++ringIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return ringIndex;
|
||||
},
|
||||
|
||||
update: function update(reset) {
|
||||
var minSize = Math.min(this.chart.chartArea.right - this.chart.chartArea.left, this.chart.chartArea.bottom - this.chart.chartArea.top);
|
||||
|
||||
this.chart.outerRadius = Math.max((minSize / 2) - this.chart.options.elements.arc.borderWidth / 2, 0);
|
||||
this.chart.innerRadius = Math.max(this.chart.options.cutoutPercentage ? (this.chart.outerRadius / 100) * (this.chart.options.cutoutPercentage) : 1, 0);
|
||||
this.chart.radiusLength = (this.chart.outerRadius - this.chart.innerRadius) / this.getVisibleDatasetCount();
|
||||
|
||||
this.getDataset().total = 0;
|
||||
helpers.each(this.getDataset().data, function(value) {
|
||||
if (!isNaN(value)) {
|
||||
this.getDataset().total += Math.abs(value);
|
||||
}
|
||||
}, this);
|
||||
|
||||
this.outerRadius = this.chart.outerRadius - (this.chart.radiusLength * this.getRingIndex(this.index));
|
||||
this.innerRadius = this.outerRadius - this.chart.radiusLength;
|
||||
|
||||
helpers.each(this.getDataset().metaData, function(arc, index) {
|
||||
this.updateElement(arc, index, reset);
|
||||
}, this);
|
||||
},
|
||||
updateElement: function(arc, index, reset) {
|
||||
var centerX = (this.chart.chartArea.left + this.chart.chartArea.right) / 2;
|
||||
var centerY = (this.chart.chartArea.top + this.chart.chartArea.bottom) / 2;
|
||||
var startAngle = Math.PI * -0.5; // non reset case handled later
|
||||
var endAngle = Math.PI * -0.5; // non reset case handled later
|
||||
var circumference = reset && this.chart.options.animation.animateRotate ? 0 : this.calculateCircumference(this.getDataset().data[index]);
|
||||
var innerRadius = reset && this.chart.options.animation.animateScale ? 0 : this.innerRadius;
|
||||
var outerRadius = reset && this.chart.options.animation.animateScale ? 0 : this.outerRadius;
|
||||
|
||||
helpers.extend(arc, {
|
||||
// Utility
|
||||
_chart: this.chart.chart,
|
||||
_datasetIndex: this.index,
|
||||
_index: index,
|
||||
|
||||
// Desired view properties
|
||||
_model: {
|
||||
x: centerX,
|
||||
y: centerY,
|
||||
startAngle: startAngle,
|
||||
endAngle: endAngle,
|
||||
circumference: circumference,
|
||||
outerRadius: outerRadius,
|
||||
innerRadius: innerRadius,
|
||||
|
||||
backgroundColor: arc.custom && arc.custom.backgroundColor ? arc.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().backgroundColor, index, this.chart.options.elements.arc.backgroundColor),
|
||||
hoverBackgroundColor: arc.custom && arc.custom.hoverBackgroundColor ? arc.custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().hoverBackgroundColor, index, this.chart.options.elements.arc.hoverBackgroundColor),
|
||||
borderWidth: arc.custom && arc.custom.borderWidth ? arc.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.getDataset().borderWidth, index, this.chart.options.elements.arc.borderWidth),
|
||||
borderColor: arc.custom && arc.custom.borderColor ? arc.custom.borderColor : helpers.getValueAtIndexOrDefault(this.getDataset().borderColor, index, this.chart.options.elements.arc.borderColor),
|
||||
|
||||
label: helpers.getValueAtIndexOrDefault(this.getDataset().label, index, this.chart.data.labels[index])
|
||||
}
|
||||
});
|
||||
|
||||
// Set correct angles if not resetting
|
||||
if (!reset) {
|
||||
|
||||
if (index === 0) {
|
||||
arc._model.startAngle = Math.PI * -0.5; // use - PI / 2 instead of 3PI / 2 to make animations better. It means that we never deal with overflow during the transition function
|
||||
} else {
|
||||
arc._model.startAngle = this.getDataset().metaData[index - 1]._model.endAngle;
|
||||
}
|
||||
|
||||
arc._model.endAngle = arc._model.startAngle + arc._model.circumference;
|
||||
}
|
||||
|
||||
arc.pivot();
|
||||
},
|
||||
|
||||
draw: function(ease) {
|
||||
var easingDecimal = ease || 1;
|
||||
helpers.each(this.getDataset().metaData, function(arc, index) {
|
||||
arc.transition(easingDecimal).draw();
|
||||
});
|
||||
},
|
||||
|
||||
setHoverStyle: function(arc) {
|
||||
var dataset = this.chart.data.datasets[arc._datasetIndex];
|
||||
var index = arc._index;
|
||||
|
||||
arc._model.backgroundColor = arc.custom && arc.custom.hoverBackgroundColor ? arc.custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.hoverBackgroundColor, index, helpers.color(arc._model.backgroundColor).saturate(0.5).darken(0.1).rgbString());
|
||||
arc._model.borderColor = arc.custom && arc.custom.hoverBorderColor ? arc.custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.hoverBorderColor, index, helpers.color(arc._model.borderColor).saturate(0.5).darken(0.1).rgbString());
|
||||
arc._model.borderWidth = arc.custom && arc.custom.hoverBorderWidth ? arc.custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.hoverBorderWidth, index, arc._model.borderWidth);
|
||||
},
|
||||
|
||||
removeHoverStyle: function(arc) {
|
||||
var dataset = this.chart.data.datasets[arc._datasetIndex];
|
||||
var index = arc._index;
|
||||
|
||||
arc._model.backgroundColor = arc.custom && arc.custom.backgroundColor ? arc.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().backgroundColor, index, this.chart.options.elements.arc.backgroundColor);
|
||||
arc._model.borderColor = arc.custom && arc.custom.borderColor ? arc.custom.borderColor : helpers.getValueAtIndexOrDefault(this.getDataset().borderColor, index, this.chart.options.elements.arc.borderColor);
|
||||
arc._model.borderWidth = arc.custom && arc.custom.borderWidth ? arc.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.getDataset().borderWidth, index, this.chart.options.elements.arc.borderWidth);
|
||||
},
|
||||
|
||||
calculateCircumference: function(value) {
|
||||
if (this.getDataset().total > 0 && !isNaN(value)) {
|
||||
return (Math.PI * 1.999999) * (value / this.getDataset().total);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,290 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = function(Chart) {
|
||||
|
||||
var helpers = Chart.helpers;
|
||||
|
||||
Chart.defaults.line = {
|
||||
showLines: true,
|
||||
|
||||
hover: {
|
||||
mode: "label"
|
||||
},
|
||||
|
||||
scales: {
|
||||
xAxes: [{
|
||||
type: "category",
|
||||
id: 'x-axis-0'
|
||||
}],
|
||||
yAxes: [{
|
||||
type: "linear",
|
||||
id: 'y-axis-0'
|
||||
}]
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Chart.controllers.line = Chart.DatasetController.extend({
|
||||
addElements: function() {
|
||||
|
||||
this.getDataset().metaData = this.getDataset().metaData || [];
|
||||
|
||||
this.getDataset().metaDataset = this.getDataset().metaDataset || new Chart.elements.Line({
|
||||
_chart: this.chart.chart,
|
||||
_datasetIndex: this.index,
|
||||
_points: this.getDataset().metaData
|
||||
});
|
||||
|
||||
helpers.each(this.getDataset().data, function(value, index) {
|
||||
this.getDataset().metaData[index] = this.getDataset().metaData[index] || new Chart.elements.Point({
|
||||
_chart: this.chart.chart,
|
||||
_datasetIndex: this.index,
|
||||
_index: index
|
||||
});
|
||||
}, this);
|
||||
},
|
||||
addElementAndReset: function(index) {
|
||||
this.getDataset().metaData = this.getDataset().metaData || [];
|
||||
var point = new Chart.elements.Point({
|
||||
_chart: this.chart.chart,
|
||||
_datasetIndex: this.index,
|
||||
_index: index
|
||||
});
|
||||
|
||||
// Reset the point
|
||||
this.updateElement(point, index, true);
|
||||
|
||||
// Add to the points array
|
||||
this.getDataset().metaData.splice(index, 0, point);
|
||||
|
||||
// Make sure bezier control points are updated
|
||||
if (this.chart.options.showLines && this.chart.options.elements.line.tension !== 0)
|
||||
this.updateBezierControlPoints();
|
||||
},
|
||||
|
||||
update: function update(reset) {
|
||||
var line = this.getDataset().metaDataset;
|
||||
var points = this.getDataset().metaData;
|
||||
|
||||
var yScale = this.getScaleForId(this.getDataset().yAxisID);
|
||||
var xScale = this.getScaleForId(this.getDataset().xAxisID);
|
||||
var scaleBase;
|
||||
|
||||
if (yScale.min < 0 && yScale.max < 0) {
|
||||
scaleBase = yScale.getPixelForValue(yScale.max);
|
||||
} else if (yScale.min > 0 && yScale.max > 0) {
|
||||
scaleBase = yScale.getPixelForValue(yScale.min);
|
||||
} else {
|
||||
scaleBase = yScale.getPixelForValue(0);
|
||||
}
|
||||
|
||||
// Update Line
|
||||
if (this.chart.options.showLines) {
|
||||
// Utility
|
||||
line._scale = yScale;
|
||||
line._datasetIndex = this.index;
|
||||
// Data
|
||||
line._children = points;
|
||||
// Model
|
||||
line._model = {
|
||||
// Appearance
|
||||
tension: line.custom && line.custom.tension ? line.custom.tension : helpers.getValueOrDefault(this.getDataset().tension, this.chart.options.elements.line.tension),
|
||||
backgroundColor: line.custom && line.custom.backgroundColor ? line.custom.backgroundColor : (this.getDataset().backgroundColor || this.chart.options.elements.line.backgroundColor),
|
||||
borderWidth: line.custom && line.custom.borderWidth ? line.custom.borderWidth : (this.getDataset().borderWidth || this.chart.options.elements.line.borderWidth),
|
||||
borderColor: line.custom && line.custom.borderColor ? line.custom.borderColor : (this.getDataset().borderColor || this.chart.options.elements.line.borderColor),
|
||||
borderCapStyle: line.custom && line.custom.borderCapStyle ? line.custom.borderCapStyle : (this.getDataset().borderCapStyle || this.chart.options.elements.line.borderCapStyle),
|
||||
borderDash: line.custom && line.custom.borderDash ? line.custom.borderDash : (this.getDataset().borderDash || this.chart.options.elements.line.borderDash),
|
||||
borderDashOffset: line.custom && line.custom.borderDashOffset ? line.custom.borderDashOffset : (this.getDataset().borderDashOffset || this.chart.options.elements.line.borderDashOffset),
|
||||
borderJoinStyle: line.custom && line.custom.borderJoinStyle ? line.custom.borderJoinStyle : (this.getDataset().borderJoinStyle || this.chart.options.elements.line.borderJoinStyle),
|
||||
fill: line.custom && line.custom.fill ? line.custom.fill : (this.getDataset().fill !== undefined ? this.getDataset().fill : this.chart.options.elements.line.fill),
|
||||
// Scale
|
||||
scaleTop: yScale.top,
|
||||
scaleBottom: yScale.bottom,
|
||||
scaleZero: scaleBase
|
||||
};
|
||||
line.pivot();
|
||||
}
|
||||
|
||||
// Update Points
|
||||
helpers.each(points, function(point, index) {
|
||||
this.updateElement(point, index, reset);
|
||||
}, this);
|
||||
|
||||
if (this.chart.options.showLines && this.chart.options.elements.line.tension !== 0)
|
||||
this.updateBezierControlPoints();
|
||||
},
|
||||
|
||||
getPointBackgroundColor: function(point, index) {
|
||||
var backgroundColor = this.chart.options.elements.point.backgroundColor;
|
||||
var dataset = this.getDataset();
|
||||
|
||||
if (point.custom && point.custom.backgroundColor) {
|
||||
backgroundColor = point.custom.backgroundColor;
|
||||
} else if (dataset.pointBackgroundColor) {
|
||||
backgroundColor = helpers.getValueAtIndexOrDefault(dataset.pointBackgroundColor, index, backgroundColor);
|
||||
} else if (dataset.backgroundColor) {
|
||||
backgroundColor = dataset.backgroundColor;
|
||||
}
|
||||
|
||||
return backgroundColor;
|
||||
},
|
||||
getPointBorderColor: function(point, index) {
|
||||
var borderColor = this.chart.options.elements.point.borderColor;
|
||||
var dataset = this.getDataset();
|
||||
|
||||
if (point.custom && point.custom.borderColor) {
|
||||
borderColor = point.custom.borderColor;
|
||||
} else if (dataset.pointBorderColor) {
|
||||
borderColor = helpers.getValueAtIndexOrDefault(this.getDataset().pointBorderColor, index, borderColor);
|
||||
} else if (dataset.borderColor) {
|
||||
borderColor = dataset.borderColor;
|
||||
}
|
||||
|
||||
return borderColor;
|
||||
},
|
||||
getPointBorderWidth: function(point, index) {
|
||||
var borderWidth = this.chart.options.elements.point.borderWidth;
|
||||
var dataset = this.getDataset();
|
||||
|
||||
if (point.custom && point.custom.borderWidth !== undefined) {
|
||||
borderWidth = point.custom.borderWidth;
|
||||
} else if (dataset.pointBorderWidth !== undefined) {
|
||||
borderWidth = helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, borderWidth);
|
||||
} else if (dataset.borderWidth !== undefined) {
|
||||
borderWidth = dataset.borderWidth;
|
||||
}
|
||||
|
||||
return borderWidth;
|
||||
},
|
||||
|
||||
updateElement: function(point, index, reset) {
|
||||
var yScale = this.getScaleForId(this.getDataset().yAxisID);
|
||||
var xScale = this.getScaleForId(this.getDataset().xAxisID);
|
||||
var scaleBase;
|
||||
|
||||
if (yScale.min < 0 && yScale.max < 0) {
|
||||
scaleBase = yScale.getPixelForValue(yScale.max);
|
||||
} else if (yScale.min > 0 && yScale.max > 0) {
|
||||
scaleBase = yScale.getPixelForValue(yScale.min);
|
||||
} else {
|
||||
scaleBase = yScale.getPixelForValue(0);
|
||||
}
|
||||
|
||||
// Utility
|
||||
point._chart = this.chart.chart;
|
||||
point._xScale = xScale;
|
||||
point._yScale = yScale;
|
||||
point._datasetIndex = this.index;
|
||||
point._index = index;
|
||||
|
||||
// Desired view properties
|
||||
point._model = {
|
||||
x: xScale.getPixelForValue(this.getDataset().data[index], index, this.index, this.chart.isCombo),
|
||||
y: reset ? scaleBase : this.calculatePointY(this.getDataset().data[index], index, this.index, this.chart.isCombo),
|
||||
// Appearance
|
||||
tension: point.custom && point.custom.tension ? point.custom.tension : helpers.getValueOrDefault(this.getDataset().tension, this.chart.options.elements.line.tension),
|
||||
radius: point.custom && point.custom.radius ? point.custom.radius : helpers.getValueAtIndexOrDefault(this.getDataset().radius, index, this.chart.options.elements.point.radius),
|
||||
pointStyle: point.custom && point.custom.pointStyle ? point.custom.pointStyle : helpers.getValueAtIndexOrDefault(this.getDataset().pointStyle, index, this.chart.options.elements.point.pointStyle),
|
||||
backgroundColor: this.getPointBackgroundColor(point, index),
|
||||
borderColor: this.getPointBorderColor(point, index),
|
||||
borderWidth: this.getPointBorderWidth(point, index),
|
||||
// Tooltip
|
||||
hitRadius: point.custom && point.custom.hitRadius ? point.custom.hitRadius : helpers.getValueAtIndexOrDefault(this.getDataset().hitRadius, index, this.chart.options.elements.point.hitRadius)
|
||||
};
|
||||
|
||||
point._model.skip = point.custom && point.custom.skip ? point.custom.skip : (isNaN(point._model.x) || isNaN(point._model.y));
|
||||
},
|
||||
|
||||
calculatePointY: function(value, index, datasetIndex, isCombo) {
|
||||
|
||||
var xScale = this.getScaleForId(this.getDataset().xAxisID);
|
||||
var yScale = this.getScaleForId(this.getDataset().yAxisID);
|
||||
|
||||
if (yScale.options.stacked) {
|
||||
|
||||
var sumPos = 0,
|
||||
sumNeg = 0;
|
||||
|
||||
for (var i = 0; i < datasetIndex; i++) {
|
||||
var ds = this.chart.data.datasets[i];
|
||||
if (ds.type === 'line' && helpers.isDatasetVisible(ds)) {
|
||||
if (ds.data[index] < 0) {
|
||||
sumNeg += ds.data[index] || 0;
|
||||
} else {
|
||||
sumPos += ds.data[index] || 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (value < 0) {
|
||||
return yScale.getPixelForValue(sumNeg + value);
|
||||
} else {
|
||||
return yScale.getPixelForValue(sumPos + value);
|
||||
}
|
||||
}
|
||||
|
||||
return yScale.getPixelForValue(value);
|
||||
},
|
||||
|
||||
updateBezierControlPoints: function() {
|
||||
// Update bezier control points
|
||||
helpers.each(this.getDataset().metaData, function(point, index) {
|
||||
var controlPoints = helpers.splineCurve(
|
||||
helpers.previousItem(this.getDataset().metaData, index)._model,
|
||||
point._model,
|
||||
helpers.nextItem(this.getDataset().metaData, index)._model,
|
||||
point._model.tension
|
||||
);
|
||||
|
||||
// Prevent the bezier going outside of the bounds of the graph
|
||||
point._model.controlPointPreviousX = Math.max(Math.min(controlPoints.previous.x, this.chart.chartArea.right), this.chart.chartArea.left);
|
||||
point._model.controlPointPreviousY = Math.max(Math.min(controlPoints.previous.y, this.chart.chartArea.bottom), this.chart.chartArea.top);
|
||||
|
||||
point._model.controlPointNextX = Math.max(Math.min(controlPoints.next.x, this.chart.chartArea.right), this.chart.chartArea.left);
|
||||
point._model.controlPointNextY = Math.max(Math.min(controlPoints.next.y, this.chart.chartArea.bottom), this.chart.chartArea.top);
|
||||
|
||||
// Now pivot the point for animation
|
||||
point.pivot();
|
||||
}, this);
|
||||
},
|
||||
|
||||
draw: function(ease) {
|
||||
var easingDecimal = ease || 1;
|
||||
|
||||
// Transition Point Locations
|
||||
helpers.each(this.getDataset().metaData, function(point) {
|
||||
point.transition(easingDecimal);
|
||||
});
|
||||
|
||||
// Transition and Draw the line
|
||||
if (this.chart.options.showLines)
|
||||
this.getDataset().metaDataset.transition(easingDecimal).draw();
|
||||
|
||||
// Draw the points
|
||||
helpers.each(this.getDataset().metaData, function(point) {
|
||||
point.draw();
|
||||
});
|
||||
},
|
||||
|
||||
setHoverStyle: function(point) {
|
||||
// Point
|
||||
var dataset = this.chart.data.datasets[point._datasetIndex];
|
||||
var index = point._index;
|
||||
|
||||
point._model.radius = point.custom && point.custom.hoverRadius ? point.custom.hoverRadius : helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, this.chart.options.elements.point.hoverRadius);
|
||||
point._model.backgroundColor = point.custom && point.custom.hoverBackgroundColor ? point.custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.color(point._model.backgroundColor).saturate(0.5).darken(0.1).rgbString());
|
||||
point._model.borderColor = point.custom && point.custom.hoverBorderColor ? point.custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.color(point._model.borderColor).saturate(0.5).darken(0.1).rgbString());
|
||||
point._model.borderWidth = point.custom && point.custom.hoverBorderWidth ? point.custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderWidth, index, point._model.borderWidth);
|
||||
},
|
||||
|
||||
removeHoverStyle: function(point) {
|
||||
var dataset = this.chart.data.datasets[point._datasetIndex];
|
||||
var index = point._index;
|
||||
|
||||
point._model.radius = point.custom && point.custom.radius ? point.custom.radius : helpers.getValueAtIndexOrDefault(this.getDataset().radius, index, this.chart.options.elements.point.radius);
|
||||
point._model.backgroundColor = this.getPointBackgroundColor(point, index);
|
||||
point._model.borderColor = this.getPointBorderColor(point, index);
|
||||
point._model.borderWidth = this.getPointBorderWidth(point, index);
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,236 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = function(Chart) {
|
||||
|
||||
var helpers = Chart.helpers;
|
||||
|
||||
Chart.defaults.polarArea = {
|
||||
|
||||
scale: {
|
||||
type: "radialLinear",
|
||||
lineArc: true // so that lines are circular
|
||||
},
|
||||
|
||||
//Boolean - Whether to animate the rotation of the chart
|
||||
animateRotate: true,
|
||||
animateScale: true,
|
||||
|
||||
aspectRatio: 1,
|
||||
legendCallback: function(chart) {
|
||||
var text = [];
|
||||
text.push('<ul class="' + chart.id + '-legend">');
|
||||
|
||||
if (chart.data.datasets.length) {
|
||||
for (var i = 0; i < chart.data.datasets[0].data.length; ++i) {
|
||||
text.push('<li><span style="background-color:' + chart.data.datasets[0].backgroundColor[i] + '">');
|
||||
if (chart.data.labels[i]) {
|
||||
text.push(chart.data.labels[i]);
|
||||
}
|
||||
text.push('</span></li>');
|
||||
}
|
||||
}
|
||||
|
||||
text.push('</ul>');
|
||||
return text.join("");
|
||||
},
|
||||
legend: {
|
||||
labels: {
|
||||
generateLabels: function(data) {
|
||||
if (data.labels.length && data.datasets.length) {
|
||||
return data.labels.map(function(label, i) {
|
||||
return {
|
||||
text: label,
|
||||
fillStyle: data.datasets[0].backgroundColor[i],
|
||||
hidden: isNaN(data.datasets[0].data[i]),
|
||||
|
||||
// Extra data used for toggling the correct item
|
||||
index: i
|
||||
};
|
||||
});
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
},
|
||||
onClick: function(e, legendItem) {
|
||||
helpers.each(this.chart.data.datasets, function(dataset) {
|
||||
dataset.metaHiddenData = dataset.metaHiddenData || [];
|
||||
var idx = legendItem.index;
|
||||
|
||||
if (!isNaN(dataset.data[idx])) {
|
||||
dataset.metaHiddenData[idx] = dataset.data[idx];
|
||||
dataset.data[idx] = NaN;
|
||||
} else if (!isNaN(dataset.metaHiddenData[idx])) {
|
||||
dataset.data[idx] = dataset.metaHiddenData[idx];
|
||||
}
|
||||
});
|
||||
|
||||
this.chart.update();
|
||||
}
|
||||
},
|
||||
|
||||
// Need to override these to give a nice default
|
||||
tooltips: {
|
||||
callbacks: {
|
||||
title: function() {
|
||||
return '';
|
||||
},
|
||||
label: function(tooltipItem, data) {
|
||||
return data.labels[tooltipItem.index] + ': ' + tooltipItem.yLabel;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Chart.controllers.polarArea = Chart.DatasetController.extend({
|
||||
linkScales: function() {
|
||||
// no scales for doughnut
|
||||
},
|
||||
addElements: function() {
|
||||
this.getDataset().metaData = this.getDataset().metaData || [];
|
||||
helpers.each(this.getDataset().data, function(value, index) {
|
||||
this.getDataset().metaData[index] = this.getDataset().metaData[index] || new Chart.elements.Arc({
|
||||
_chart: this.chart.chart,
|
||||
_datasetIndex: this.index,
|
||||
_index: index
|
||||
});
|
||||
}, this);
|
||||
},
|
||||
addElementAndReset: function(index) {
|
||||
this.getDataset().metaData = this.getDataset().metaData || [];
|
||||
var arc = new Chart.elements.Arc({
|
||||
_chart: this.chart.chart,
|
||||
_datasetIndex: this.index,
|
||||
_index: index
|
||||
});
|
||||
|
||||
// Reset the point
|
||||
this.updateElement(arc, index, true);
|
||||
|
||||
// Add to the points array
|
||||
this.getDataset().metaData.splice(index, 0, arc);
|
||||
},
|
||||
getVisibleDatasetCount: function getVisibleDatasetCount() {
|
||||
return helpers.where(this.chart.data.datasets, function(ds) {
|
||||
return helpers.isDatasetVisible(ds);
|
||||
}).length;
|
||||
},
|
||||
|
||||
update: function update(reset) {
|
||||
var minSize = Math.min(this.chart.chartArea.right - this.chart.chartArea.left, this.chart.chartArea.bottom - this.chart.chartArea.top);
|
||||
this.chart.outerRadius = Math.max((minSize - this.chart.options.elements.arc.borderWidth / 2) / 2, 0);
|
||||
this.chart.innerRadius = Math.max(this.chart.options.cutoutPercentage ? (this.chart.outerRadius / 100) * (this.chart.options.cutoutPercentage) : 1, 0);
|
||||
this.chart.radiusLength = (this.chart.outerRadius - this.chart.innerRadius) / this.getVisibleDatasetCount();
|
||||
|
||||
this.getDataset().total = 0;
|
||||
helpers.each(this.getDataset().data, function(value) {
|
||||
this.getDataset().total += Math.abs(value);
|
||||
}, this);
|
||||
|
||||
this.outerRadius = this.chart.outerRadius - (this.chart.radiusLength * this.index);
|
||||
this.innerRadius = this.outerRadius - this.chart.radiusLength;
|
||||
|
||||
helpers.each(this.getDataset().metaData, function(arc, index) {
|
||||
this.updateElement(arc, index, reset);
|
||||
}, this);
|
||||
},
|
||||
|
||||
updateElement: function(arc, index, reset) {
|
||||
var circumference = this.calculateCircumference(this.getDataset().data[index]);
|
||||
var centerX = (this.chart.chartArea.left + this.chart.chartArea.right) / 2;
|
||||
var centerY = (this.chart.chartArea.top + this.chart.chartArea.bottom) / 2;
|
||||
|
||||
// If there is NaN data before us, we need to calculate the starting angle correctly.
|
||||
// We could be way more efficient here, but its unlikely that the polar area chart will have a lot of data
|
||||
var notNullIndex = 0;
|
||||
for (var i = 0; i < index; ++i) {
|
||||
if (!isNaN(this.getDataset().data[i])) {
|
||||
++notNullIndex;
|
||||
}
|
||||
}
|
||||
|
||||
var startAngle = (-0.5 * Math.PI) + (circumference * notNullIndex);
|
||||
var endAngle = startAngle + circumference;
|
||||
|
||||
var resetModel = {
|
||||
x: centerX,
|
||||
y: centerY,
|
||||
innerRadius: 0,
|
||||
outerRadius: this.chart.options.animateScale ? 0 : this.chart.scale.getDistanceFromCenterForValue(this.getDataset().data[index]),
|
||||
startAngle: this.chart.options.animateRotate ? Math.PI * -0.5 : startAngle,
|
||||
endAngle: this.chart.options.animateRotate ? Math.PI * -0.5 : endAngle,
|
||||
|
||||
backgroundColor: arc.custom && arc.custom.backgroundColor ? arc.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().backgroundColor, index, this.chart.options.elements.arc.backgroundColor),
|
||||
borderWidth: arc.custom && arc.custom.borderWidth ? arc.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.getDataset().borderWidth, index, this.chart.options.elements.arc.borderWidth),
|
||||
borderColor: arc.custom && arc.custom.borderColor ? arc.custom.borderColor : helpers.getValueAtIndexOrDefault(this.getDataset().borderColor, index, this.chart.options.elements.arc.borderColor),
|
||||
|
||||
label: helpers.getValueAtIndexOrDefault(this.chart.data.labels, index, this.chart.data.labels[index])
|
||||
};
|
||||
|
||||
helpers.extend(arc, {
|
||||
// Utility
|
||||
_chart: this.chart.chart,
|
||||
_datasetIndex: this.index,
|
||||
_index: index,
|
||||
_scale: this.chart.scale,
|
||||
|
||||
// Desired view properties
|
||||
_model: reset ? resetModel : {
|
||||
x: centerX,
|
||||
y: centerY,
|
||||
innerRadius: 0,
|
||||
outerRadius: this.chart.scale.getDistanceFromCenterForValue(this.getDataset().data[index]),
|
||||
startAngle: startAngle,
|
||||
endAngle: endAngle,
|
||||
|
||||
backgroundColor: arc.custom && arc.custom.backgroundColor ? arc.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().backgroundColor, index, this.chart.options.elements.arc.backgroundColor),
|
||||
borderWidth: arc.custom && arc.custom.borderWidth ? arc.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.getDataset().borderWidth, index, this.chart.options.elements.arc.borderWidth),
|
||||
borderColor: arc.custom && arc.custom.borderColor ? arc.custom.borderColor : helpers.getValueAtIndexOrDefault(this.getDataset().borderColor, index, this.chart.options.elements.arc.borderColor),
|
||||
|
||||
label: helpers.getValueAtIndexOrDefault(this.chart.data.labels, index, this.chart.data.labels[index])
|
||||
}
|
||||
});
|
||||
|
||||
arc.pivot();
|
||||
},
|
||||
|
||||
draw: function(ease) {
|
||||
var easingDecimal = ease || 1;
|
||||
helpers.each(this.getDataset().metaData, function(arc, index) {
|
||||
arc.transition(easingDecimal).draw();
|
||||
});
|
||||
},
|
||||
|
||||
setHoverStyle: function(arc) {
|
||||
var dataset = this.chart.data.datasets[arc._datasetIndex];
|
||||
var index = arc._index;
|
||||
|
||||
arc._model.backgroundColor = arc.custom && arc.custom.hoverBackgroundColor ? arc.custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.hoverBackgroundColor, index, helpers.color(arc._model.backgroundColor).saturate(0.5).darken(0.1).rgbString());
|
||||
arc._model.borderColor = arc.custom && arc.custom.hoverBorderColor ? arc.custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.hoverBorderColor, index, helpers.color(arc._model.borderColor).saturate(0.5).darken(0.1).rgbString());
|
||||
arc._model.borderWidth = arc.custom && arc.custom.hoverBorderWidth ? arc.custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.hoverBorderWidth, index, arc._model.borderWidth);
|
||||
},
|
||||
|
||||
removeHoverStyle: function(arc) {
|
||||
var dataset = this.chart.data.datasets[arc._datasetIndex];
|
||||
var index = arc._index;
|
||||
|
||||
arc._model.backgroundColor = arc.custom && arc.custom.backgroundColor ? arc.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().backgroundColor, index, this.chart.options.elements.arc.backgroundColor);
|
||||
arc._model.borderColor = arc.custom && arc.custom.borderColor ? arc.custom.borderColor : helpers.getValueAtIndexOrDefault(this.getDataset().borderColor, index, this.chart.options.elements.arc.borderColor);
|
||||
arc._model.borderWidth = arc.custom && arc.custom.borderWidth ? arc.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.getDataset().borderWidth, index, this.chart.options.elements.arc.borderWidth);
|
||||
},
|
||||
|
||||
calculateCircumference: function(value) {
|
||||
if (isNaN(value)) {
|
||||
return 0;
|
||||
} else {
|
||||
// Count the number of NaN values
|
||||
var numNaN = helpers.where(this.getDataset().data, function(data) {
|
||||
return isNaN(data);
|
||||
}).length;
|
||||
|
||||
return (2 * Math.PI) / (this.getDataset().data.length - numNaN);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
@@ -0,0 +1,205 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = function(Chart) {
|
||||
|
||||
var helpers = Chart.helpers;
|
||||
|
||||
|
||||
Chart.defaults.radar = {
|
||||
scale: {
|
||||
type: "radialLinear"
|
||||
},
|
||||
elements: {
|
||||
line: {
|
||||
tension: 0 // no bezier in radar
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Chart.controllers.radar = Chart.DatasetController.extend({
|
||||
linkScales: function() {
|
||||
// No need. Single scale only
|
||||
},
|
||||
|
||||
addElements: function() {
|
||||
|
||||
this.getDataset().metaData = this.getDataset().metaData || [];
|
||||
|
||||
this.getDataset().metaDataset = this.getDataset().metaDataset || new Chart.elements.Line({
|
||||
_chart: this.chart.chart,
|
||||
_datasetIndex: this.index,
|
||||
_points: this.getDataset().metaData,
|
||||
_loop: true
|
||||
});
|
||||
|
||||
helpers.each(this.getDataset().data, function(value, index) {
|
||||
this.getDataset().metaData[index] = this.getDataset().metaData[index] || new Chart.elements.Point({
|
||||
_chart: this.chart.chart,
|
||||
_datasetIndex: this.index,
|
||||
_index: index,
|
||||
_model: {
|
||||
x: 0, //xScale.getPixelForValue(null, index, true),
|
||||
y: 0 //this.chartArea.bottom,
|
||||
}
|
||||
});
|
||||
}, this);
|
||||
},
|
||||
addElementAndReset: function(index) {
|
||||
this.getDataset().metaData = this.getDataset().metaData || [];
|
||||
var point = new Chart.elements.Point({
|
||||
_chart: this.chart.chart,
|
||||
_datasetIndex: this.index,
|
||||
_index: index
|
||||
});
|
||||
|
||||
// Reset the point
|
||||
this.updateElement(point, index, true);
|
||||
|
||||
// Add to the points array
|
||||
this.getDataset().metaData.splice(index, 0, point);
|
||||
|
||||
// Make sure bezier control points are updated
|
||||
this.updateBezierControlPoints();
|
||||
},
|
||||
|
||||
update: function update(reset) {
|
||||
|
||||
var line = this.getDataset().metaDataset;
|
||||
var points = this.getDataset().metaData;
|
||||
|
||||
var scale = this.chart.scale;
|
||||
var scaleBase;
|
||||
|
||||
if (scale.min < 0 && scale.max < 0) {
|
||||
scaleBase = scale.getPointPositionForValue(0, scale.max);
|
||||
} else if (scale.min > 0 && scale.max > 0) {
|
||||
scaleBase = scale.getPointPositionForValue(0, scale.min);
|
||||
} else {
|
||||
scaleBase = scale.getPointPositionForValue(0, 0);
|
||||
}
|
||||
|
||||
helpers.extend(this.getDataset().metaDataset, {
|
||||
// Utility
|
||||
_datasetIndex: this.index,
|
||||
// Data
|
||||
_children: this.getDataset().metaData,
|
||||
// Model
|
||||
_model: {
|
||||
// Appearance
|
||||
tension: line.custom && line.custom.tension ? line.custom.tension : helpers.getValueOrDefault(this.getDataset().tension, this.chart.options.elements.line.tension),
|
||||
backgroundColor: line.custom && line.custom.backgroundColor ? line.custom.backgroundColor : (this.getDataset().backgroundColor || this.chart.options.elements.line.backgroundColor),
|
||||
borderWidth: line.custom && line.custom.borderWidth ? line.custom.borderWidth : (this.getDataset().borderWidth || this.chart.options.elements.line.borderWidth),
|
||||
borderColor: line.custom && line.custom.borderColor ? line.custom.borderColor : (this.getDataset().borderColor || this.chart.options.elements.line.borderColor),
|
||||
fill: line.custom && line.custom.fill ? line.custom.fill : (this.getDataset().fill !== undefined ? this.getDataset().fill : this.chart.options.elements.line.fill),
|
||||
borderCapStyle: line.custom && line.custom.borderCapStyle ? line.custom.borderCapStyle : (this.getDataset().borderCapStyle || this.chart.options.elements.line.borderCapStyle),
|
||||
borderDash: line.custom && line.custom.borderDash ? line.custom.borderDash : (this.getDataset().borderDash || this.chart.options.elements.line.borderDash),
|
||||
borderDashOffset: line.custom && line.custom.borderDashOffset ? line.custom.borderDashOffset : (this.getDataset().borderDashOffset || this.chart.options.elements.line.borderDashOffset),
|
||||
borderJoinStyle: line.custom && line.custom.borderJoinStyle ? line.custom.borderJoinStyle : (this.getDataset().borderJoinStyle || this.chart.options.elements.line.borderJoinStyle),
|
||||
|
||||
// Scale
|
||||
scaleTop: scale.top,
|
||||
scaleBottom: scale.bottom,
|
||||
scaleZero: scaleBase
|
||||
}
|
||||
});
|
||||
|
||||
this.getDataset().metaDataset.pivot();
|
||||
|
||||
// Update Points
|
||||
helpers.each(points, function(point, index) {
|
||||
this.updateElement(point, index, reset);
|
||||
}, this);
|
||||
|
||||
|
||||
// Update bezier control points
|
||||
this.updateBezierControlPoints();
|
||||
},
|
||||
updateElement: function(point, index, reset) {
|
||||
var pointPosition = this.chart.scale.getPointPositionForValue(index, this.getDataset().data[index]);
|
||||
|
||||
helpers.extend(point, {
|
||||
// Utility
|
||||
_datasetIndex: this.index,
|
||||
_index: index,
|
||||
_scale: this.chart.scale,
|
||||
|
||||
// Desired view properties
|
||||
_model: {
|
||||
x: reset ? this.chart.scale.xCenter : pointPosition.x, // value not used in dataset scale, but we want a consistent API between scales
|
||||
y: reset ? this.chart.scale.yCenter : pointPosition.y,
|
||||
|
||||
// Appearance
|
||||
tension: point.custom && point.custom.tension ? point.custom.tension : helpers.getValueOrDefault(this.getDataset().tension, this.chart.options.elements.line.tension),
|
||||
radius: point.custom && point.custom.radius ? point.custom.radius : helpers.getValueAtIndexOrDefault(this.getDataset().pointRadius, index, this.chart.options.elements.point.radius),
|
||||
backgroundColor: point.custom && point.custom.backgroundColor ? point.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().pointBackgroundColor, index, this.chart.options.elements.point.backgroundColor),
|
||||
borderColor: point.custom && point.custom.borderColor ? point.custom.borderColor : helpers.getValueAtIndexOrDefault(this.getDataset().pointBorderColor, index, this.chart.options.elements.point.borderColor),
|
||||
borderWidth: point.custom && point.custom.borderWidth ? point.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.getDataset().pointBorderWidth, index, this.chart.options.elements.point.borderWidth),
|
||||
pointStyle: point.custom && point.custom.pointStyle ? point.custom.pointStyle : helpers.getValueAtIndexOrDefault(this.getDataset().pointStyle, index, this.chart.options.elements.point.pointStyle),
|
||||
|
||||
// Tooltip
|
||||
hitRadius: point.custom && point.custom.hitRadius ? point.custom.hitRadius : helpers.getValueAtIndexOrDefault(this.getDataset().hitRadius, index, this.chart.options.elements.point.hitRadius)
|
||||
}
|
||||
});
|
||||
|
||||
point._model.skip = point.custom && point.custom.skip ? point.custom.skip : (isNaN(point._model.x) || isNaN(point._model.y));
|
||||
},
|
||||
updateBezierControlPoints: function() {
|
||||
helpers.each(this.getDataset().metaData, function(point, index) {
|
||||
var controlPoints = helpers.splineCurve(
|
||||
helpers.previousItem(this.getDataset().metaData, index, true)._model,
|
||||
point._model,
|
||||
helpers.nextItem(this.getDataset().metaData, index, true)._model,
|
||||
point._model.tension
|
||||
);
|
||||
|
||||
// Prevent the bezier going outside of the bounds of the graph
|
||||
point._model.controlPointPreviousX = Math.max(Math.min(controlPoints.previous.x, this.chart.chartArea.right), this.chart.chartArea.left);
|
||||
point._model.controlPointPreviousY = Math.max(Math.min(controlPoints.previous.y, this.chart.chartArea.bottom), this.chart.chartArea.top);
|
||||
|
||||
point._model.controlPointNextX = Math.max(Math.min(controlPoints.next.x, this.chart.chartArea.right), this.chart.chartArea.left);
|
||||
point._model.controlPointNextY = Math.max(Math.min(controlPoints.next.y, this.chart.chartArea.bottom), this.chart.chartArea.top);
|
||||
|
||||
// Now pivot the point for animation
|
||||
point.pivot();
|
||||
}, this);
|
||||
},
|
||||
|
||||
draw: function(ease) {
|
||||
var easingDecimal = ease || 1;
|
||||
|
||||
// Transition Point Locations
|
||||
helpers.each(this.getDataset().metaData, function(point, index) {
|
||||
point.transition(easingDecimal);
|
||||
});
|
||||
|
||||
// Transition and Draw the line
|
||||
this.getDataset().metaDataset.transition(easingDecimal).draw();
|
||||
|
||||
// Draw the points
|
||||
helpers.each(this.getDataset().metaData, function(point) {
|
||||
point.draw();
|
||||
});
|
||||
},
|
||||
|
||||
setHoverStyle: function(point) {
|
||||
// Point
|
||||
var dataset = this.chart.data.datasets[point._datasetIndex];
|
||||
var index = point._index;
|
||||
|
||||
point._model.radius = point.custom && point.custom.hoverRadius ? point.custom.hoverRadius : helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, this.chart.options.elements.point.hoverRadius);
|
||||
point._model.backgroundColor = point.custom && point.custom.hoverBackgroundColor ? point.custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.color(point._model.backgroundColor).saturate(0.5).darken(0.1).rgbString());
|
||||
point._model.borderColor = point.custom && point.custom.hoverBorderColor ? point.custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.color(point._model.borderColor).saturate(0.5).darken(0.1).rgbString());
|
||||
point._model.borderWidth = point.custom && point.custom.hoverBorderWidth ? point.custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderWidth, index, point._model.borderWidth);
|
||||
},
|
||||
|
||||
removeHoverStyle: function(point) {
|
||||
var dataset = this.chart.data.datasets[point._datasetIndex];
|
||||
var index = point._index;
|
||||
|
||||
point._model.radius = point.custom && point.custom.radius ? point.custom.radius : helpers.getValueAtIndexOrDefault(this.getDataset().radius, index, this.chart.options.elements.point.radius);
|
||||
point._model.backgroundColor = point.custom && point.custom.backgroundColor ? point.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().pointBackgroundColor, index, this.chart.options.elements.point.backgroundColor);
|
||||
point._model.borderColor = point.custom && point.custom.borderColor ? point.custom.borderColor : helpers.getValueAtIndexOrDefault(this.getDataset().pointBorderColor, index, this.chart.options.elements.point.borderColor);
|
||||
point._model.borderWidth = point.custom && point.custom.borderWidth ? point.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.getDataset().pointBorderWidth, index, this.chart.options.elements.point.borderWidth);
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,120 @@
|
||||
/*global window: false */
|
||||
"use strict";
|
||||
|
||||
module.exports = function(Chart) {
|
||||
|
||||
var helpers = Chart.helpers;
|
||||
|
||||
Chart.defaults.global.animation = {
|
||||
duration: 1000,
|
||||
easing: "easeOutQuart",
|
||||
onProgress: helpers.noop,
|
||||
onComplete: helpers.noop
|
||||
};
|
||||
|
||||
Chart.Animation = Chart.Element.extend({
|
||||
currentStep: null, // the current animation step
|
||||
numSteps: 60, // default number of steps
|
||||
easing: "", // the easing to use for this animation
|
||||
render: null, // render function used by the animation service
|
||||
|
||||
onAnimationProgress: null, // user specified callback to fire on each step of the animation
|
||||
onAnimationComplete: null // user specified callback to fire when the animation finishes
|
||||
});
|
||||
|
||||
Chart.animationService = {
|
||||
frameDuration: 17,
|
||||
animations: [],
|
||||
dropFrames: 0,
|
||||
addAnimation: function(chartInstance, animationObject, duration, lazy) {
|
||||
|
||||
if (!lazy) {
|
||||
chartInstance.animating = true;
|
||||
}
|
||||
|
||||
for (var index = 0; index < this.animations.length; ++index) {
|
||||
if (this.animations[index].chartInstance === chartInstance) {
|
||||
// replacing an in progress animation
|
||||
this.animations[index].animationObject = animationObject;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.animations.push({
|
||||
chartInstance: chartInstance,
|
||||
animationObject: animationObject
|
||||
});
|
||||
|
||||
// If there are no animations queued, manually kickstart a digest, for lack of a better word
|
||||
if (this.animations.length === 1) {
|
||||
helpers.requestAnimFrame.call(window, this.digestWrapper);
|
||||
}
|
||||
},
|
||||
// Cancel the animation for a given chart instance
|
||||
cancelAnimation: function(chartInstance) {
|
||||
var index = helpers.findIndex(this.animations, function(animationWrapper) {
|
||||
return animationWrapper.chartInstance === chartInstance;
|
||||
});
|
||||
|
||||
if (index !== -1) {
|
||||
this.animations.splice(index, 1);
|
||||
chartInstance.animating = false;
|
||||
}
|
||||
},
|
||||
// calls startDigest with the proper context
|
||||
digestWrapper: function() {
|
||||
Chart.animationService.startDigest.call(Chart.animationService);
|
||||
},
|
||||
startDigest: function() {
|
||||
|
||||
var startTime = Date.now();
|
||||
var framesToDrop = 0;
|
||||
|
||||
if (this.dropFrames > 1) {
|
||||
framesToDrop = Math.floor(this.dropFrames);
|
||||
this.dropFrames = this.dropFrames % 1;
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
while (i < this.animations.length) {
|
||||
if (this.animations[i].animationObject.currentStep === null) {
|
||||
this.animations[i].animationObject.currentStep = 0;
|
||||
}
|
||||
|
||||
this.animations[i].animationObject.currentStep += 1 + framesToDrop;
|
||||
|
||||
if (this.animations[i].animationObject.currentStep > this.animations[i].animationObject.numSteps) {
|
||||
this.animations[i].animationObject.currentStep = this.animations[i].animationObject.numSteps;
|
||||
}
|
||||
|
||||
this.animations[i].animationObject.render(this.animations[i].chartInstance, this.animations[i].animationObject);
|
||||
if (this.animations[i].animationObject.onAnimationProgress && this.animations[i].animationObject.onAnimationProgress.call) {
|
||||
this.animations[i].animationObject.onAnimationProgress.call(this.animations[i].chartInstance, this.animations[i]);
|
||||
}
|
||||
|
||||
if (this.animations[i].animationObject.currentStep === this.animations[i].animationObject.numSteps) {
|
||||
if (this.animations[i].animationObject.onAnimationComplete && this.animations[i].animationObject.onAnimationComplete.call) {
|
||||
this.animations[i].animationObject.onAnimationComplete.call(this.animations[i].chartInstance, this.animations[i]);
|
||||
}
|
||||
|
||||
// executed the last frame. Remove the animation.
|
||||
this.animations[i].chartInstance.animating = false;
|
||||
|
||||
this.animations.splice(i, 1);
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
var endTime = Date.now();
|
||||
var dropFrames = (endTime - startTime) / this.frameDuration;
|
||||
|
||||
this.dropFrames += dropFrames;
|
||||
|
||||
// Do we have more stuff to animate?
|
||||
if (this.animations.length > 0) {
|
||||
helpers.requestAnimFrame.call(window, this.digestWrapper);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,572 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = function(Chart) {
|
||||
|
||||
var helpers = Chart.helpers;
|
||||
//Create a dictionary of chart types, to allow for extension of existing types
|
||||
Chart.types = {};
|
||||
|
||||
//Store a reference to each instance - allowing us to globally resize chart instances on window resize.
|
||||
//Destroy method on the chart will remove the instance of the chart from this reference.
|
||||
Chart.instances = {};
|
||||
|
||||
// Controllers available for dataset visualization eg. bar, line, slice, etc.
|
||||
Chart.controllers = {};
|
||||
|
||||
// The main controller of a chart
|
||||
Chart.Controller = function(instance) {
|
||||
|
||||
this.chart = instance;
|
||||
this.config = instance.config;
|
||||
this.options = this.config.options = helpers.configMerge(Chart.defaults.global, Chart.defaults[this.config.type], this.config.options || {});
|
||||
this.id = helpers.uid();
|
||||
|
||||
Object.defineProperty(this, 'data', {
|
||||
get: function() {
|
||||
return this.config.data;
|
||||
}
|
||||
});
|
||||
|
||||
//Add the chart instance to the global namespace
|
||||
Chart.instances[this.id] = this;
|
||||
|
||||
if (this.options.responsive) {
|
||||
// Silent resize before chart draws
|
||||
this.resize(true);
|
||||
}
|
||||
|
||||
this.initialize();
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
helpers.extend(Chart.Controller.prototype, {
|
||||
|
||||
initialize: function initialize() {
|
||||
|
||||
// TODO
|
||||
// If BeforeInit(this) doesn't return false, proceed
|
||||
|
||||
this.bindEvents();
|
||||
|
||||
// Make sure controllers are built first so that each dataset is bound to an axis before the scales
|
||||
// are built
|
||||
this.ensureScalesHaveIDs();
|
||||
this.buildOrUpdateControllers();
|
||||
this.buildScales();
|
||||
this.buildSurroundingItems();
|
||||
this.updateLayout();
|
||||
this.resetElements();
|
||||
this.initToolTip();
|
||||
this.update();
|
||||
|
||||
// TODO
|
||||
// If AfterInit(this) doesn't return false, proceed
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
clear: function clear() {
|
||||
helpers.clear(this.chart);
|
||||
return this;
|
||||
},
|
||||
|
||||
stop: function stop() {
|
||||
// Stops any current animation loop occuring
|
||||
Chart.animationService.cancelAnimation(this);
|
||||
return this;
|
||||
},
|
||||
|
||||
resize: function resize(silent) {
|
||||
var canvas = this.chart.canvas;
|
||||
var newWidth = helpers.getMaximumWidth(this.chart.canvas);
|
||||
var newHeight = (this.options.maintainAspectRatio && isNaN(this.chart.aspectRatio) === false && isFinite(this.chart.aspectRatio) && this.chart.aspectRatio !== 0) ? newWidth / this.chart.aspectRatio : helpers.getMaximumHeight(this.chart.canvas);
|
||||
|
||||
var sizeChanged = this.chart.width !== newWidth || this.chart.height !== newHeight;
|
||||
|
||||
if (!sizeChanged)
|
||||
return this;
|
||||
|
||||
canvas.width = this.chart.width = newWidth;
|
||||
canvas.height = this.chart.height = newHeight;
|
||||
|
||||
helpers.retinaScale(this.chart);
|
||||
|
||||
if (!silent) {
|
||||
this.stop();
|
||||
this.update(this.options.responsiveAnimationDuration);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
ensureScalesHaveIDs: function ensureScalesHaveIDs() {
|
||||
var defaultXAxisID = 'x-axis-';
|
||||
var defaultYAxisID = 'y-axis-';
|
||||
|
||||
if (this.options.scales) {
|
||||
if (this.options.scales.xAxes && this.options.scales.xAxes.length) {
|
||||
helpers.each(this.options.scales.xAxes, function(xAxisOptions, index) {
|
||||
xAxisOptions.id = xAxisOptions.id || (defaultXAxisID + index);
|
||||
});
|
||||
}
|
||||
|
||||
if (this.options.scales.yAxes && this.options.scales.yAxes.length) {
|
||||
// Build the y axes
|
||||
helpers.each(this.options.scales.yAxes, function(yAxisOptions, index) {
|
||||
yAxisOptions.id = yAxisOptions.id || (defaultYAxisID + index);
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
buildScales: function buildScales() {
|
||||
// Map of scale ID to scale object so we can lookup later
|
||||
this.scales = {};
|
||||
|
||||
// Build the x axes
|
||||
if (this.options.scales) {
|
||||
if (this.options.scales.xAxes && this.options.scales.xAxes.length) {
|
||||
helpers.each(this.options.scales.xAxes, function(xAxisOptions, index) {
|
||||
var xType = helpers.getValueOrDefault(xAxisOptions.type, 'category');
|
||||
var ScaleClass = Chart.scaleService.getScaleConstructor(xType);
|
||||
if (ScaleClass) {
|
||||
var scale = new ScaleClass({
|
||||
ctx: this.chart.ctx,
|
||||
options: xAxisOptions,
|
||||
chart: this,
|
||||
id: xAxisOptions.id
|
||||
});
|
||||
|
||||
this.scales[scale.id] = scale;
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
|
||||
if (this.options.scales.yAxes && this.options.scales.yAxes.length) {
|
||||
// Build the y axes
|
||||
helpers.each(this.options.scales.yAxes, function(yAxisOptions, index) {
|
||||
var yType = helpers.getValueOrDefault(yAxisOptions.type, 'linear');
|
||||
var ScaleClass = Chart.scaleService.getScaleConstructor(yType);
|
||||
if (ScaleClass) {
|
||||
var scale = new ScaleClass({
|
||||
ctx: this.chart.ctx,
|
||||
options: yAxisOptions,
|
||||
chart: this,
|
||||
id: yAxisOptions.id
|
||||
});
|
||||
|
||||
this.scales[scale.id] = scale;
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
}
|
||||
if (this.options.scale) {
|
||||
// Build radial axes
|
||||
var ScaleClass = Chart.scaleService.getScaleConstructor(this.options.scale.type);
|
||||
if (ScaleClass) {
|
||||
var scale = new ScaleClass({
|
||||
ctx: this.chart.ctx,
|
||||
options: this.options.scale,
|
||||
chart: this
|
||||
});
|
||||
|
||||
this.scale = scale;
|
||||
|
||||
this.scales.radialScale = scale;
|
||||
}
|
||||
}
|
||||
|
||||
Chart.scaleService.addScalesToLayout(this);
|
||||
},
|
||||
|
||||
buildSurroundingItems: function() {
|
||||
if (this.options.title) {
|
||||
this.titleBlock = new Chart.Title({
|
||||
ctx: this.chart.ctx,
|
||||
options: this.options.title,
|
||||
chart: this
|
||||
});
|
||||
|
||||
Chart.layoutService.addBox(this, this.titleBlock);
|
||||
}
|
||||
|
||||
if (this.options.legend) {
|
||||
this.legend = new Chart.Legend({
|
||||
ctx: this.chart.ctx,
|
||||
options: this.options.legend,
|
||||
chart: this
|
||||
});
|
||||
|
||||
Chart.layoutService.addBox(this, this.legend);
|
||||
}
|
||||
},
|
||||
|
||||
updateLayout: function() {
|
||||
Chart.layoutService.update(this, this.chart.width, this.chart.height);
|
||||
},
|
||||
|
||||
buildOrUpdateControllers: function buildOrUpdateControllers() {
|
||||
var types = [];
|
||||
var newControllers = [];
|
||||
|
||||
helpers.each(this.data.datasets, function(dataset, datasetIndex) {
|
||||
if (!dataset.type) {
|
||||
dataset.type = this.config.type;
|
||||
}
|
||||
|
||||
var type = dataset.type;
|
||||
types.push(type);
|
||||
|
||||
if (dataset.controller) {
|
||||
dataset.controller.updateIndex(datasetIndex);
|
||||
} else {
|
||||
dataset.controller = new Chart.controllers[type](this, datasetIndex);
|
||||
newControllers.push(dataset.controller);
|
||||
}
|
||||
}, this);
|
||||
|
||||
if (types.length > 1) {
|
||||
for (var i = 1; i < types.length; i++) {
|
||||
if (types[i] !== types[i - 1]) {
|
||||
this.isCombo = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return newControllers;
|
||||
},
|
||||
|
||||
resetElements: function resetElements() {
|
||||
helpers.each(this.data.datasets, function(dataset, datasetIndex) {
|
||||
dataset.controller.reset();
|
||||
});
|
||||
},
|
||||
|
||||
update: function update(animationDuration, lazy) {
|
||||
// In case the entire data object changed
|
||||
this.tooltip._data = this.data;
|
||||
|
||||
// Make sure dataset controllers are updated and new controllers are reset
|
||||
var newControllers = this.buildOrUpdateControllers();
|
||||
|
||||
Chart.layoutService.update(this, this.chart.width, this.chart.height);
|
||||
|
||||
// Can only reset the new controllers after the scales have been updated
|
||||
helpers.each(newControllers, function(controller) {
|
||||
controller.reset();
|
||||
});
|
||||
|
||||
// Make sure all dataset controllers have correct meta data counts
|
||||
helpers.each(this.data.datasets, function(dataset, datasetIndex) {
|
||||
dataset.controller.buildOrUpdateElements();
|
||||
});
|
||||
|
||||
// This will loop through any data and do the appropriate element update for the type
|
||||
helpers.each(this.data.datasets, function(dataset, datasetIndex) {
|
||||
dataset.controller.update();
|
||||
});
|
||||
this.render(animationDuration, lazy);
|
||||
},
|
||||
|
||||
render: function render(duration, lazy) {
|
||||
|
||||
if (this.options.animation && ((typeof duration !== 'undefined' && duration !== 0) || (typeof duration === 'undefined' && this.options.animation.duration !== 0))) {
|
||||
var animation = new Chart.Animation();
|
||||
animation.numSteps = (duration || this.options.animation.duration) / 16.66; //60 fps
|
||||
animation.easing = this.options.animation.easing;
|
||||
|
||||
// render function
|
||||
animation.render = function(chartInstance, animationObject) {
|
||||
var easingFunction = helpers.easingEffects[animationObject.easing];
|
||||
var stepDecimal = animationObject.currentStep / animationObject.numSteps;
|
||||
var easeDecimal = easingFunction(stepDecimal);
|
||||
|
||||
chartInstance.draw(easeDecimal, stepDecimal, animationObject.currentStep);
|
||||
};
|
||||
|
||||
// user events
|
||||
animation.onAnimationProgress = this.options.animation.onProgress;
|
||||
animation.onAnimationComplete = this.options.animation.onComplete;
|
||||
|
||||
Chart.animationService.addAnimation(this, animation, duration, lazy);
|
||||
} else {
|
||||
this.draw();
|
||||
if (this.options.animation && this.options.animation.onComplete && this.options.animation.onComplete.call) {
|
||||
this.options.animation.onComplete.call(this);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
draw: function(ease) {
|
||||
var easingDecimal = ease || 1;
|
||||
this.clear();
|
||||
|
||||
// Draw all the scales
|
||||
helpers.each(this.boxes, function(box) {
|
||||
box.draw(this.chartArea);
|
||||
}, this);
|
||||
if (this.scale) {
|
||||
this.scale.draw();
|
||||
}
|
||||
|
||||
// Clip out the chart area so that anything outside does not draw. This is necessary for zoom and pan to function
|
||||
this.chart.ctx.save();
|
||||
this.chart.ctx.beginPath();
|
||||
this.chart.ctx.rect(this.chartArea.left, this.chartArea.top, this.chartArea.right - this.chartArea.left, this.chartArea.bottom - this.chartArea.top);
|
||||
this.chart.ctx.clip();
|
||||
|
||||
// Draw each dataset via its respective controller (reversed to support proper line stacking)
|
||||
helpers.each(this.data.datasets, function(dataset, datasetIndex) {
|
||||
if (helpers.isDatasetVisible(dataset)) {
|
||||
dataset.controller.draw(ease);
|
||||
}
|
||||
}, null, true);
|
||||
|
||||
// Restore from the clipping operation
|
||||
this.chart.ctx.restore();
|
||||
|
||||
// Finally draw the tooltip
|
||||
this.tooltip.transition(easingDecimal).draw();
|
||||
},
|
||||
|
||||
// Get the single element that was clicked on
|
||||
// @return : An object containing the dataset index and element index of the matching element. Also contains the rectangle that was draw
|
||||
getElementAtEvent: function(e) {
|
||||
|
||||
var eventPosition = helpers.getRelativePosition(e, this.chart);
|
||||
var elementsArray = [];
|
||||
|
||||
helpers.each(this.data.datasets, function(dataset, datasetIndex) {
|
||||
if (helpers.isDatasetVisible(dataset)) {
|
||||
helpers.each(dataset.metaData, function(element, index) {
|
||||
if (element.inRange(eventPosition.x, eventPosition.y)) {
|
||||
elementsArray.push(element);
|
||||
return elementsArray;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return elementsArray;
|
||||
},
|
||||
|
||||
getElementsAtEvent: function(e) {
|
||||
var eventPosition = helpers.getRelativePosition(e, this.chart);
|
||||
var elementsArray = [];
|
||||
|
||||
var found = (function() {
|
||||
if (this.data.datasets) {
|
||||
for (var i = 0; i < this.data.datasets.length; i++) {
|
||||
if (helpers.isDatasetVisible(this.data.datasets[i])) {
|
||||
for (var j = 0; j < this.data.datasets[i].metaData.length; j++) {
|
||||
if (this.data.datasets[i].metaData[j].inRange(eventPosition.x, eventPosition.y)) {
|
||||
return this.data.datasets[i].metaData[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}).call(this);
|
||||
|
||||
if (!found) {
|
||||
return elementsArray;
|
||||
}
|
||||
|
||||
helpers.each(this.data.datasets, function(dataset, dsIndex) {
|
||||
if (helpers.isDatasetVisible(dataset)) {
|
||||
elementsArray.push(dataset.metaData[found._index]);
|
||||
}
|
||||
});
|
||||
|
||||
return elementsArray;
|
||||
},
|
||||
|
||||
getDatasetAtEvent: function(e) {
|
||||
var elementsArray = this.getElementAtEvent(e);
|
||||
|
||||
if (elementsArray.length > 0) {
|
||||
elementsArray = this.data.datasets[elementsArray[0]._datasetIndex].metaData;
|
||||
}
|
||||
|
||||
return elementsArray;
|
||||
},
|
||||
|
||||
generateLegend: function generateLegend() {
|
||||
return this.options.legendCallback(this);
|
||||
},
|
||||
|
||||
destroy: function destroy() {
|
||||
this.clear();
|
||||
helpers.unbindEvents(this, this.events);
|
||||
helpers.removeResizeListener(this.chart.canvas.parentNode);
|
||||
|
||||
// Reset canvas height/width attributes
|
||||
var canvas = this.chart.canvas;
|
||||
canvas.width = this.chart.width;
|
||||
canvas.height = this.chart.height;
|
||||
|
||||
// if we scaled the canvas in response to a devicePixelRatio !== 1, we need to undo that transform here
|
||||
if (this.chart.originalDevicePixelRatio !== undefined) {
|
||||
this.chart.ctx.scale(1 / this.chart.originalDevicePixelRatio, 1 / this.chart.originalDevicePixelRatio);
|
||||
}
|
||||
|
||||
// Reset to the old style since it may have been changed by the device pixel ratio changes
|
||||
canvas.style.width = this.chart.originalCanvasStyleWidth;
|
||||
canvas.style.height = this.chart.originalCanvasStyleHeight;
|
||||
|
||||
delete Chart.instances[this.id];
|
||||
},
|
||||
|
||||
toBase64Image: function toBase64Image() {
|
||||
return this.chart.canvas.toDataURL.apply(this.chart.canvas, arguments);
|
||||
},
|
||||
|
||||
initToolTip: function initToolTip() {
|
||||
this.tooltip = new Chart.Tooltip({
|
||||
_chart: this.chart,
|
||||
_chartInstance: this,
|
||||
_data: this.data,
|
||||
_options: this.options
|
||||
}, this);
|
||||
},
|
||||
|
||||
bindEvents: function bindEvents() {
|
||||
helpers.bindEvents(this, this.options.events, function(evt) {
|
||||
this.eventHandler(evt);
|
||||
});
|
||||
},
|
||||
eventHandler: function eventHandler(e) {
|
||||
this.lastActive = this.lastActive || [];
|
||||
this.lastTooltipActive = this.lastTooltipActive || [];
|
||||
|
||||
// Find Active Elements for hover and tooltips
|
||||
if (e.type === 'mouseout') {
|
||||
this.active = [];
|
||||
this.tooltipActive = [];
|
||||
} else {
|
||||
|
||||
var _this = this;
|
||||
var getItemsForMode = function(mode) {
|
||||
switch (mode) {
|
||||
case 'single':
|
||||
return _this.getElementAtEvent(e);
|
||||
case 'label':
|
||||
return _this.getElementsAtEvent(e);
|
||||
case 'dataset':
|
||||
return _this.getDatasetAtEvent(e);
|
||||
default:
|
||||
return e;
|
||||
}
|
||||
};
|
||||
|
||||
this.active = getItemsForMode(this.options.hover.mode);
|
||||
this.tooltipActive = getItemsForMode(this.options.tooltips.mode);
|
||||
}
|
||||
|
||||
// On Hover hook
|
||||
if (this.options.hover.onHover) {
|
||||
this.options.hover.onHover.call(this, this.active);
|
||||
}
|
||||
|
||||
if (e.type === 'mouseup' || e.type === 'click') {
|
||||
if (this.options.onClick) {
|
||||
this.options.onClick.call(this, e, this.active);
|
||||
}
|
||||
|
||||
if (this.legend && this.legend.handleEvent) {
|
||||
this.legend.handleEvent(e);
|
||||
}
|
||||
}
|
||||
|
||||
var dataset;
|
||||
var index;
|
||||
|
||||
// Remove styling for last active (even if it may still be active)
|
||||
if (this.lastActive.length) {
|
||||
switch (this.options.hover.mode) {
|
||||
case 'single':
|
||||
this.data.datasets[this.lastActive[0]._datasetIndex].controller.removeHoverStyle(this.lastActive[0], this.lastActive[0]._datasetIndex, this.lastActive[0]._index);
|
||||
break;
|
||||
case 'label':
|
||||
case 'dataset':
|
||||
for (var i = 0; i < this.lastActive.length; i++) {
|
||||
if (this.lastActive[i])
|
||||
this.data.datasets[this.lastActive[i]._datasetIndex].controller.removeHoverStyle(this.lastActive[i], this.lastActive[i]._datasetIndex, this.lastActive[i]._index);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Don't change anything
|
||||
}
|
||||
}
|
||||
|
||||
// Built in hover styling
|
||||
if (this.active.length && this.options.hover.mode) {
|
||||
switch (this.options.hover.mode) {
|
||||
case 'single':
|
||||
this.data.datasets[this.active[0]._datasetIndex].controller.setHoverStyle(this.active[0]);
|
||||
break;
|
||||
case 'label':
|
||||
case 'dataset':
|
||||
for (var j = 0; j < this.active.length; j++) {
|
||||
if (this.active[j])
|
||||
this.data.datasets[this.active[j]._datasetIndex].controller.setHoverStyle(this.active[j]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Don't change anything
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Built in Tooltips
|
||||
if (this.options.tooltips.enabled || this.options.tooltips.custom) {
|
||||
|
||||
// The usual updates
|
||||
this.tooltip.initialize();
|
||||
this.tooltip._active = this.tooltipActive;
|
||||
this.tooltip.update();
|
||||
}
|
||||
|
||||
// Hover animations
|
||||
this.tooltip.pivot();
|
||||
|
||||
if (!this.animating) {
|
||||
var changed;
|
||||
|
||||
helpers.each(this.active, function(element, index) {
|
||||
if (element !== this.lastActive[index]) {
|
||||
changed = true;
|
||||
}
|
||||
}, this);
|
||||
|
||||
helpers.each(this.tooltipActive, function(element, index) {
|
||||
if (element !== this.lastTooltipActive[index]) {
|
||||
changed = true;
|
||||
}
|
||||
}, this);
|
||||
|
||||
// If entering, leaving, or changing elements, animate the change via pivot
|
||||
if ((this.lastActive.length !== this.active.length) ||
|
||||
(this.lastTooltipActive.length !== this.tooltipActive.length) ||
|
||||
changed) {
|
||||
|
||||
this.stop();
|
||||
|
||||
if (this.options.tooltips.enabled || this.options.tooltips.custom) {
|
||||
this.tooltip.update(true);
|
||||
}
|
||||
|
||||
// We only need to render at this point. Updating will cause scales to be recomputed generating flicker & using more
|
||||
// memory than necessary.
|
||||
this.render(this.options.hover.animationDuration, true);
|
||||
}
|
||||
}
|
||||
|
||||
// Remember Last Actives
|
||||
this.lastActive = this.active;
|
||||
this.lastTooltipActive = this.tooltipActive;
|
||||
return this;
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,73 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = function(Chart) {
|
||||
|
||||
var helpers = Chart.helpers;
|
||||
|
||||
// Base class for all dataset controllers (line, bar, etc)
|
||||
Chart.DatasetController = function(chart, datasetIndex) {
|
||||
this.initialize.call(this, chart, datasetIndex);
|
||||
};
|
||||
|
||||
helpers.extend(Chart.DatasetController.prototype, {
|
||||
initialize: function(chart, datasetIndex) {
|
||||
this.chart = chart;
|
||||
this.index = datasetIndex;
|
||||
this.linkScales();
|
||||
this.addElements();
|
||||
},
|
||||
updateIndex: function(datasetIndex) {
|
||||
this.index = datasetIndex;
|
||||
},
|
||||
|
||||
linkScales: function() {
|
||||
if (!this.getDataset().xAxisID) {
|
||||
this.getDataset().xAxisID = this.chart.options.scales.xAxes[0].id;
|
||||
}
|
||||
|
||||
if (!this.getDataset().yAxisID) {
|
||||
this.getDataset().yAxisID = this.chart.options.scales.yAxes[0].id;
|
||||
}
|
||||
},
|
||||
|
||||
getDataset: function() {
|
||||
return this.chart.data.datasets[this.index];
|
||||
},
|
||||
|
||||
getScaleForId: function(scaleID) {
|
||||
return this.chart.scales[scaleID];
|
||||
},
|
||||
|
||||
reset: function() {
|
||||
this.update(true);
|
||||
},
|
||||
|
||||
buildOrUpdateElements: function buildOrUpdateElements() {
|
||||
// Handle the number of data points changing
|
||||
var numData = this.getDataset().data.length;
|
||||
var numMetaData = this.getDataset().metaData.length;
|
||||
|
||||
// Make sure that we handle number of datapoints changing
|
||||
if (numData < numMetaData) {
|
||||
// Remove excess bars for data points that have been removed
|
||||
this.getDataset().metaData.splice(numData, numMetaData - numData);
|
||||
} else if (numData > numMetaData) {
|
||||
// Add new elements
|
||||
for (var index = numMetaData; index < numData; ++index) {
|
||||
this.addElementAndReset(index);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Controllers should implement the following
|
||||
addElements: helpers.noop,
|
||||
addElementAndReset: helpers.noop,
|
||||
draw: helpers.noop,
|
||||
removeHoverStyle: helpers.noop,
|
||||
setHoverStyle: helpers.noop,
|
||||
update: helpers.noop
|
||||
});
|
||||
|
||||
Chart.DatasetController.extend = helpers.inherits;
|
||||
|
||||
};
|
||||
@@ -0,0 +1,93 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = function(Chart) {
|
||||
|
||||
var helpers = Chart.helpers;
|
||||
|
||||
Chart.elements = {};
|
||||
|
||||
Chart.Element = function(configuration) {
|
||||
helpers.extend(this, configuration);
|
||||
this.initialize.apply(this, arguments);
|
||||
};
|
||||
helpers.extend(Chart.Element.prototype, {
|
||||
initialize: function() {},
|
||||
pivot: function() {
|
||||
if (!this._view) {
|
||||
this._view = helpers.clone(this._model);
|
||||
}
|
||||
this._start = helpers.clone(this._view);
|
||||
return this;
|
||||
},
|
||||
transition: function(ease) {
|
||||
if (!this._view) {
|
||||
this._view = helpers.clone(this._model);
|
||||
}
|
||||
|
||||
// No animation -> No Transition
|
||||
if (ease === 1) {
|
||||
this._view = this._model;
|
||||
this._start = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
if (!this._start) {
|
||||
this.pivot();
|
||||
}
|
||||
|
||||
helpers.each(this._model, function(value, key) {
|
||||
|
||||
if (key[0] === '_' || !this._model.hasOwnProperty(key)) {
|
||||
// Only non-underscored properties
|
||||
}
|
||||
|
||||
// Init if doesn't exist
|
||||
else if (!this._view.hasOwnProperty(key)) {
|
||||
if (typeof value === 'number' && !isNaN(this._view[key])) {
|
||||
this._view[key] = value * ease;
|
||||
} else {
|
||||
this._view[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
// No unnecessary computations
|
||||
else if (value === this._view[key]) {
|
||||
// It's the same! Woohoo!
|
||||
}
|
||||
|
||||
// Color transitions if possible
|
||||
else if (typeof value === 'string') {
|
||||
try {
|
||||
var color = helpers.color(this._start[key]).mix(helpers.color(this._model[key]), ease);
|
||||
this._view[key] = color.rgbString();
|
||||
} catch (err) {
|
||||
this._view[key] = value;
|
||||
}
|
||||
}
|
||||
// Number transitions
|
||||
else if (typeof value === 'number') {
|
||||
var startVal = this._start[key] !== undefined && isNaN(this._start[key]) === false ? this._start[key] : 0;
|
||||
this._view[key] = ((this._model[key] - startVal) * ease) + startVal;
|
||||
}
|
||||
// Everything else
|
||||
else {
|
||||
this._view[key] = value;
|
||||
}
|
||||
}, this);
|
||||
|
||||
return this;
|
||||
},
|
||||
tooltipPosition: function() {
|
||||
return {
|
||||
x: this._model.x,
|
||||
y: this._model.y
|
||||
};
|
||||
},
|
||||
hasValue: function() {
|
||||
return helpers.isNumber(this._model.x) && helpers.isNumber(this._model.y);
|
||||
}
|
||||
});
|
||||
|
||||
Chart.Element.extend = helpers.inherits;
|
||||
|
||||
};
|
||||
@@ -0,0 +1,944 @@
|
||||
/*global window: false */
|
||||
/*global document: false */
|
||||
"use strict";
|
||||
|
||||
var color = require('chartjs-color');
|
||||
|
||||
module.exports = function(Chart) {
|
||||
|
||||
//Global Chart helpers object for utility methods and classes
|
||||
var helpers = Chart.helpers = {};
|
||||
|
||||
//-- Basic js utility methods
|
||||
helpers.each = function(loopable, callback, self, reverse) {
|
||||
// Check to see if null or undefined firstly.
|
||||
var i, len;
|
||||
if (helpers.isArray(loopable)) {
|
||||
len = loopable.length;
|
||||
if (reverse) {
|
||||
for (i = len - 1; i >= 0; i--) {
|
||||
callback.call(self, loopable[i], i);
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < len; i++) {
|
||||
callback.call(self, loopable[i], i);
|
||||
}
|
||||
}
|
||||
} else if (typeof loopable === 'object') {
|
||||
var keys = Object.keys(loopable);
|
||||
len = keys.length;
|
||||
for (i = 0; i < len; i++) {
|
||||
callback.call(self, loopable[keys[i]], keys[i]);
|
||||
}
|
||||
}
|
||||
};
|
||||
helpers.clone = function(obj) {
|
||||
var objClone = {};
|
||||
helpers.each(obj, function(value, key) {
|
||||
if (obj.hasOwnProperty(key)) {
|
||||
if (helpers.isArray(value)) {
|
||||
objClone[key] = value.slice(0);
|
||||
} else if (typeof value === 'object' && value !== null) {
|
||||
objClone[key] = helpers.clone(value);
|
||||
} else {
|
||||
objClone[key] = value;
|
||||
}
|
||||
}
|
||||
});
|
||||
return objClone;
|
||||
};
|
||||
helpers.extend = function(base) {
|
||||
var len = arguments.length;
|
||||
var additionalArgs = [];
|
||||
for (var i = 1; i < len; i++) {
|
||||
additionalArgs.push(arguments[i]);
|
||||
}
|
||||
helpers.each(additionalArgs, function(extensionObject) {
|
||||
helpers.each(extensionObject, function(value, key) {
|
||||
if (extensionObject.hasOwnProperty(key)) {
|
||||
base[key] = value;
|
||||
}
|
||||
});
|
||||
});
|
||||
return base;
|
||||
};
|
||||
// Need a special merge function to chart configs since they are now grouped
|
||||
helpers.configMerge = function(_base) {
|
||||
var base = helpers.clone(_base);
|
||||
helpers.each(Array.prototype.slice.call(arguments, 1), function(extension) {
|
||||
helpers.each(extension, function(value, key) {
|
||||
if (extension.hasOwnProperty(key)) {
|
||||
if (key === 'scales') {
|
||||
// Scale config merging is complex. Add out own function here for that
|
||||
base[key] = helpers.scaleMerge(base.hasOwnProperty(key) ? base[key] : {}, value);
|
||||
|
||||
} else if (key === 'scale') {
|
||||
// Used in polar area & radar charts since there is only one scale
|
||||
base[key] = helpers.configMerge(base.hasOwnProperty(key) ? base[key] : {}, Chart.scaleService.getScaleDefaults(value.type), value);
|
||||
} else if (base.hasOwnProperty(key) && helpers.isArray(base[key]) && helpers.isArray(value)) {
|
||||
// In this case we have an array of objects replacing another array. Rather than doing a strict replace,
|
||||
// merge. This allows easy scale option merging
|
||||
var baseArray = base[key];
|
||||
|
||||
helpers.each(value, function(valueObj, index) {
|
||||
|
||||
if (index < baseArray.length) {
|
||||
if (typeof baseArray[index] === 'object' && baseArray[index] !== null && typeof valueObj === 'object' && valueObj !== null) {
|
||||
// Two objects are coming together. Do a merge of them.
|
||||
baseArray[index] = helpers.configMerge(baseArray[index], valueObj);
|
||||
} else {
|
||||
// Just overwrite in this case since there is nothing to merge
|
||||
baseArray[index] = valueObj;
|
||||
}
|
||||
} else {
|
||||
baseArray.push(valueObj); // nothing to merge
|
||||
}
|
||||
});
|
||||
|
||||
} else if (base.hasOwnProperty(key) && typeof base[key] === "object" && base[key] !== null && typeof value === "object") {
|
||||
// If we are overwriting an object with an object, do a merge of the properties.
|
||||
base[key] = helpers.configMerge(base[key], value);
|
||||
|
||||
} else {
|
||||
// can just overwrite the value in this case
|
||||
base[key] = value;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return base;
|
||||
};
|
||||
helpers.extendDeep = function(_base) {
|
||||
return _extendDeep.apply(this, arguments);
|
||||
|
||||
function _extendDeep(dst) {
|
||||
helpers.each(arguments, function(obj) {
|
||||
if (obj !== dst) {
|
||||
helpers.each(obj, function(value, key) {
|
||||
if (dst[key] && dst[key].constructor && dst[key].constructor === Object) {
|
||||
_extendDeep(dst[key], value);
|
||||
} else {
|
||||
dst[key] = value;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return dst;
|
||||
}
|
||||
};
|
||||
helpers.scaleMerge = function(_base, extension) {
|
||||
var base = helpers.clone(_base);
|
||||
|
||||
helpers.each(extension, function(value, key) {
|
||||
if (extension.hasOwnProperty(key)) {
|
||||
if (key === 'xAxes' || key === 'yAxes') {
|
||||
// These properties are arrays of items
|
||||
if (base.hasOwnProperty(key)) {
|
||||
helpers.each(value, function(valueObj, index) {
|
||||
var axisType = helpers.getValueOrDefault(valueObj.type, key === 'xAxes' ? 'category' : 'linear');
|
||||
var axisDefaults = Chart.scaleService.getScaleDefaults(axisType);
|
||||
if (index >= base[key].length || !base[key][index].type) {
|
||||
base[key].push(helpers.configMerge(axisDefaults, valueObj));
|
||||
} else if (valueObj.type && valueObj.type !== base[key][index].type) {
|
||||
// Type changed. Bring in the new defaults before we bring in valueObj so that valueObj can override the correct scale defaults
|
||||
base[key][index] = helpers.configMerge(base[key][index], axisDefaults, valueObj);
|
||||
} else {
|
||||
// Type is the same
|
||||
base[key][index] = helpers.configMerge(base[key][index], valueObj);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
base[key] = [];
|
||||
helpers.each(value, function(valueObj) {
|
||||
var axisType = helpers.getValueOrDefault(valueObj.type, key === 'xAxes' ? 'category' : 'linear');
|
||||
base[key].push(helpers.configMerge(Chart.scaleService.getScaleDefaults(axisType), valueObj));
|
||||
});
|
||||
}
|
||||
} else if (base.hasOwnProperty(key) && typeof base[key] === "object" && base[key] !== null && typeof value === "object") {
|
||||
// If we are overwriting an object with an object, do a merge of the properties.
|
||||
base[key] = helpers.configMerge(base[key], value);
|
||||
|
||||
} else {
|
||||
// can just overwrite the value in this case
|
||||
base[key] = value;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return base;
|
||||
};
|
||||
helpers.getValueAtIndexOrDefault = function(value, index, defaultValue) {
|
||||
if (value === undefined || value === null) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
if (helpers.isArray(value)) {
|
||||
return index < value.length ? value[index] : defaultValue;
|
||||
}
|
||||
|
||||
return value;
|
||||
};
|
||||
helpers.getValueOrDefault = function(value, defaultValue) {
|
||||
return value === undefined ? defaultValue : value;
|
||||
};
|
||||
helpers.indexOf = function(arrayToSearch, item) {
|
||||
if (Array.prototype.indexOf) {
|
||||
return arrayToSearch.indexOf(item);
|
||||
} else {
|
||||
for (var i = 0; i < arrayToSearch.length; i++) {
|
||||
if (arrayToSearch[i] === item)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
helpers.where = function(collection, filterCallback) {
|
||||
var filtered = [];
|
||||
|
||||
helpers.each(collection, function(item) {
|
||||
if (filterCallback(item)) {
|
||||
filtered.push(item);
|
||||
}
|
||||
});
|
||||
|
||||
return filtered;
|
||||
};
|
||||
helpers.findIndex = function(arrayToSearch, callback, thisArg) {
|
||||
var index = -1;
|
||||
if (Array.prototype.findIndex) {
|
||||
index = arrayToSearch.findIndex(callback, thisArg);
|
||||
} else {
|
||||
for (var i = 0; i < arrayToSearch.length; ++i) {
|
||||
thisArg = thisArg !== undefined ? thisArg : arrayToSearch;
|
||||
|
||||
if (callback.call(thisArg, arrayToSearch[i], i, arrayToSearch)) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return index;
|
||||
};
|
||||
helpers.findNextWhere = function(arrayToSearch, filterCallback, startIndex) {
|
||||
// Default to start of the array
|
||||
if (startIndex === undefined || startIndex === null) {
|
||||
startIndex = -1;
|
||||
}
|
||||
for (var i = startIndex + 1; i < arrayToSearch.length; i++) {
|
||||
var currentItem = arrayToSearch[i];
|
||||
if (filterCallback(currentItem)) {
|
||||
return currentItem;
|
||||
}
|
||||
}
|
||||
};
|
||||
helpers.findPreviousWhere = function(arrayToSearch, filterCallback, startIndex) {
|
||||
// Default to end of the array
|
||||
if (startIndex === undefined || startIndex === null) {
|
||||
startIndex = arrayToSearch.length;
|
||||
}
|
||||
for (var i = startIndex - 1; i >= 0; i--) {
|
||||
var currentItem = arrayToSearch[i];
|
||||
if (filterCallback(currentItem)) {
|
||||
return currentItem;
|
||||
}
|
||||
}
|
||||
};
|
||||
helpers.inherits = function(extensions) {
|
||||
//Basic javascript inheritance based on the model created in Backbone.js
|
||||
var parent = this;
|
||||
var ChartElement = (extensions && extensions.hasOwnProperty("constructor")) ? extensions.constructor : function() {
|
||||
return parent.apply(this, arguments);
|
||||
};
|
||||
|
||||
var Surrogate = function() {
|
||||
this.constructor = ChartElement;
|
||||
};
|
||||
Surrogate.prototype = parent.prototype;
|
||||
ChartElement.prototype = new Surrogate();
|
||||
|
||||
ChartElement.extend = helpers.inherits;
|
||||
|
||||
if (extensions) {
|
||||
helpers.extend(ChartElement.prototype, extensions);
|
||||
}
|
||||
|
||||
ChartElement.__super__ = parent.prototype;
|
||||
|
||||
return ChartElement;
|
||||
};
|
||||
helpers.noop = function() {};
|
||||
helpers.uid = (function() {
|
||||
var id = 0;
|
||||
return function() {
|
||||
return "chart-" + id++;
|
||||
};
|
||||
})();
|
||||
helpers.warn = function(str) {
|
||||
//Method for warning of errors
|
||||
if (console && typeof console.warn === "function") {
|
||||
console.warn(str);
|
||||
}
|
||||
};
|
||||
//-- Math methods
|
||||
helpers.isNumber = function(n) {
|
||||
return !isNaN(parseFloat(n)) && isFinite(n);
|
||||
};
|
||||
helpers.almostEquals = function(x, y, epsilon) {
|
||||
return Math.abs(x - y) < epsilon;
|
||||
};
|
||||
helpers.max = function(array) {
|
||||
return array.reduce(function(max, value) {
|
||||
if (!isNaN(value)) {
|
||||
return Math.max(max, value);
|
||||
} else {
|
||||
return max;
|
||||
}
|
||||
}, Number.NEGATIVE_INFINITY);
|
||||
};
|
||||
helpers.min = function(array) {
|
||||
return array.reduce(function(min, value) {
|
||||
if (!isNaN(value)) {
|
||||
return Math.min(min, value);
|
||||
} else {
|
||||
return min;
|
||||
}
|
||||
}, Number.POSITIVE_INFINITY);
|
||||
};
|
||||
helpers.sign = function(x) {
|
||||
if (Math.sign) {
|
||||
return Math.sign(x);
|
||||
} else {
|
||||
x = +x; // convert to a number
|
||||
if (x === 0 || isNaN(x)) {
|
||||
return x;
|
||||
}
|
||||
return x > 0 ? 1 : -1;
|
||||
}
|
||||
};
|
||||
helpers.log10 = function(x) {
|
||||
if (Math.log10) {
|
||||
return Math.log10(x);
|
||||
} else {
|
||||
return Math.log(x) / Math.LN10;
|
||||
}
|
||||
};
|
||||
helpers.toRadians = function(degrees) {
|
||||
return degrees * (Math.PI / 180);
|
||||
};
|
||||
helpers.toDegrees = function(radians) {
|
||||
return radians * (180 / Math.PI);
|
||||
};
|
||||
// Gets the angle from vertical upright to the point about a centre.
|
||||
helpers.getAngleFromPoint = function(centrePoint, anglePoint) {
|
||||
var distanceFromXCenter = anglePoint.x - centrePoint.x,
|
||||
distanceFromYCenter = anglePoint.y - centrePoint.y,
|
||||
radialDistanceFromCenter = Math.sqrt(distanceFromXCenter * distanceFromXCenter + distanceFromYCenter * distanceFromYCenter);
|
||||
|
||||
var angle = Math.atan2(distanceFromYCenter, distanceFromXCenter);
|
||||
|
||||
if (angle < (-0.5 * Math.PI)) {
|
||||
angle += 2.0 * Math.PI; // make sure the returned angle is in the range of (-PI/2, 3PI/2]
|
||||
}
|
||||
|
||||
return {
|
||||
angle: angle,
|
||||
distance: radialDistanceFromCenter
|
||||
};
|
||||
};
|
||||
helpers.aliasPixel = function(pixelWidth) {
|
||||
return (pixelWidth % 2 === 0) ? 0 : 0.5;
|
||||
};
|
||||
helpers.splineCurve = function(firstPoint, middlePoint, afterPoint, t) {
|
||||
//Props to Rob Spencer at scaled innovation for his post on splining between points
|
||||
//http://scaledinnovation.com/analytics/splines/aboutSplines.html
|
||||
|
||||
// This function must also respect "skipped" points
|
||||
|
||||
var previous = firstPoint.skip ? middlePoint : firstPoint,
|
||||
current = middlePoint,
|
||||
next = afterPoint.skip ? middlePoint : afterPoint;
|
||||
|
||||
var d01 = Math.sqrt(Math.pow(current.x - previous.x, 2) + Math.pow(current.y - previous.y, 2));
|
||||
var d12 = Math.sqrt(Math.pow(next.x - current.x, 2) + Math.pow(next.y - current.y, 2));
|
||||
|
||||
var s01 = d01 / (d01 + d12);
|
||||
var s12 = d12 / (d01 + d12);
|
||||
|
||||
// If all points are the same, s01 & s02 will be inf
|
||||
s01 = isNaN(s01) ? 0 : s01;
|
||||
s12 = isNaN(s12) ? 0 : s12;
|
||||
|
||||
var fa = t * s01; // scaling factor for triangle Ta
|
||||
var fb = t * s12;
|
||||
|
||||
return {
|
||||
previous: {
|
||||
x: current.x - fa * (next.x - previous.x),
|
||||
y: current.y - fa * (next.y - previous.y)
|
||||
},
|
||||
next: {
|
||||
x: current.x + fb * (next.x - previous.x),
|
||||
y: current.y + fb * (next.y - previous.y)
|
||||
}
|
||||
};
|
||||
};
|
||||
helpers.nextItem = function(collection, index, loop) {
|
||||
if (loop) {
|
||||
return index >= collection.length - 1 ? collection[0] : collection[index + 1];
|
||||
}
|
||||
|
||||
return index >= collection.length - 1 ? collection[collection.length - 1] : collection[index + 1];
|
||||
};
|
||||
helpers.previousItem = function(collection, index, loop) {
|
||||
if (loop) {
|
||||
return index <= 0 ? collection[collection.length - 1] : collection[index - 1];
|
||||
}
|
||||
return index <= 0 ? collection[0] : collection[index - 1];
|
||||
};
|
||||
// Implementation of the nice number algorithm used in determining where axis labels will go
|
||||
helpers.niceNum = function(range, round) {
|
||||
var exponent = Math.floor(helpers.log10(range));
|
||||
var fraction = range / Math.pow(10, exponent);
|
||||
var niceFraction;
|
||||
|
||||
if (round) {
|
||||
if (fraction < 1.5) {
|
||||
niceFraction = 1;
|
||||
} else if (fraction < 3) {
|
||||
niceFraction = 2;
|
||||
} else if (fraction < 7) {
|
||||
niceFraction = 5;
|
||||
} else {
|
||||
niceFraction = 10;
|
||||
}
|
||||
} else {
|
||||
if (fraction <= 1.0) {
|
||||
niceFraction = 1;
|
||||
} else if (fraction <= 2) {
|
||||
niceFraction = 2;
|
||||
} else if (fraction <= 5) {
|
||||
niceFraction = 5;
|
||||
} else {
|
||||
niceFraction = 10;
|
||||
}
|
||||
}
|
||||
|
||||
return niceFraction * Math.pow(10, exponent);
|
||||
};
|
||||
//Easing functions adapted from Robert Penner's easing equations
|
||||
//http://www.robertpenner.com/easing/
|
||||
var easingEffects = helpers.easingEffects = {
|
||||
linear: function(t) {
|
||||
return t;
|
||||
},
|
||||
easeInQuad: function(t) {
|
||||
return t * t;
|
||||
},
|
||||
easeOutQuad: function(t) {
|
||||
return -1 * t * (t - 2);
|
||||
},
|
||||
easeInOutQuad: function(t) {
|
||||
if ((t /= 1 / 2) < 1) {
|
||||
return 1 / 2 * t * t;
|
||||
}
|
||||
return -1 / 2 * ((--t) * (t - 2) - 1);
|
||||
},
|
||||
easeInCubic: function(t) {
|
||||
return t * t * t;
|
||||
},
|
||||
easeOutCubic: function(t) {
|
||||
return 1 * ((t = t / 1 - 1) * t * t + 1);
|
||||
},
|
||||
easeInOutCubic: function(t) {
|
||||
if ((t /= 1 / 2) < 1) {
|
||||
return 1 / 2 * t * t * t;
|
||||
}
|
||||
return 1 / 2 * ((t -= 2) * t * t + 2);
|
||||
},
|
||||
easeInQuart: function(t) {
|
||||
return t * t * t * t;
|
||||
},
|
||||
easeOutQuart: function(t) {
|
||||
return -1 * ((t = t / 1 - 1) * t * t * t - 1);
|
||||
},
|
||||
easeInOutQuart: function(t) {
|
||||
if ((t /= 1 / 2) < 1) {
|
||||
return 1 / 2 * t * t * t * t;
|
||||
}
|
||||
return -1 / 2 * ((t -= 2) * t * t * t - 2);
|
||||
},
|
||||
easeInQuint: function(t) {
|
||||
return 1 * (t /= 1) * t * t * t * t;
|
||||
},
|
||||
easeOutQuint: function(t) {
|
||||
return 1 * ((t = t / 1 - 1) * t * t * t * t + 1);
|
||||
},
|
||||
easeInOutQuint: function(t) {
|
||||
if ((t /= 1 / 2) < 1) {
|
||||
return 1 / 2 * t * t * t * t * t;
|
||||
}
|
||||
return 1 / 2 * ((t -= 2) * t * t * t * t + 2);
|
||||
},
|
||||
easeInSine: function(t) {
|
||||
return -1 * Math.cos(t / 1 * (Math.PI / 2)) + 1;
|
||||
},
|
||||
easeOutSine: function(t) {
|
||||
return 1 * Math.sin(t / 1 * (Math.PI / 2));
|
||||
},
|
||||
easeInOutSine: function(t) {
|
||||
return -1 / 2 * (Math.cos(Math.PI * t / 1) - 1);
|
||||
},
|
||||
easeInExpo: function(t) {
|
||||
return (t === 0) ? 1 : 1 * Math.pow(2, 10 * (t / 1 - 1));
|
||||
},
|
||||
easeOutExpo: function(t) {
|
||||
return (t === 1) ? 1 : 1 * (-Math.pow(2, -10 * t / 1) + 1);
|
||||
},
|
||||
easeInOutExpo: function(t) {
|
||||
if (t === 0) {
|
||||
return 0;
|
||||
}
|
||||
if (t === 1) {
|
||||
return 1;
|
||||
}
|
||||
if ((t /= 1 / 2) < 1) {
|
||||
return 1 / 2 * Math.pow(2, 10 * (t - 1));
|
||||
}
|
||||
return 1 / 2 * (-Math.pow(2, -10 * --t) + 2);
|
||||
},
|
||||
easeInCirc: function(t) {
|
||||
if (t >= 1) {
|
||||
return t;
|
||||
}
|
||||
return -1 * (Math.sqrt(1 - (t /= 1) * t) - 1);
|
||||
},
|
||||
easeOutCirc: function(t) {
|
||||
return 1 * Math.sqrt(1 - (t = t / 1 - 1) * t);
|
||||
},
|
||||
easeInOutCirc: function(t) {
|
||||
if ((t /= 1 / 2) < 1) {
|
||||
return -1 / 2 * (Math.sqrt(1 - t * t) - 1);
|
||||
}
|
||||
return 1 / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1);
|
||||
},
|
||||
easeInElastic: function(t) {
|
||||
var s = 1.70158;
|
||||
var p = 0;
|
||||
var a = 1;
|
||||
if (t === 0) {
|
||||
return 0;
|
||||
}
|
||||
if ((t /= 1) === 1) {
|
||||
return 1;
|
||||
}
|
||||
if (!p) {
|
||||
p = 1 * 0.3;
|
||||
}
|
||||
if (a < Math.abs(1)) {
|
||||
a = 1;
|
||||
s = p / 4;
|
||||
} else {
|
||||
s = p / (2 * Math.PI) * Math.asin(1 / a);
|
||||
}
|
||||
return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p));
|
||||
},
|
||||
easeOutElastic: function(t) {
|
||||
var s = 1.70158;
|
||||
var p = 0;
|
||||
var a = 1;
|
||||
if (t === 0) {
|
||||
return 0;
|
||||
}
|
||||
if ((t /= 1) === 1) {
|
||||
return 1;
|
||||
}
|
||||
if (!p) {
|
||||
p = 1 * 0.3;
|
||||
}
|
||||
if (a < Math.abs(1)) {
|
||||
a = 1;
|
||||
s = p / 4;
|
||||
} else {
|
||||
s = p / (2 * Math.PI) * Math.asin(1 / a);
|
||||
}
|
||||
return a * Math.pow(2, -10 * t) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) + 1;
|
||||
},
|
||||
easeInOutElastic: function(t) {
|
||||
var s = 1.70158;
|
||||
var p = 0;
|
||||
var a = 1;
|
||||
if (t === 0) {
|
||||
return 0;
|
||||
}
|
||||
if ((t /= 1 / 2) === 2) {
|
||||
return 1;
|
||||
}
|
||||
if (!p) {
|
||||
p = 1 * (0.3 * 1.5);
|
||||
}
|
||||
if (a < Math.abs(1)) {
|
||||
a = 1;
|
||||
s = p / 4;
|
||||
} else {
|
||||
s = p / (2 * Math.PI) * Math.asin(1 / a);
|
||||
}
|
||||
if (t < 1) {
|
||||
return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p));
|
||||
}
|
||||
return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) * 0.5 + 1;
|
||||
},
|
||||
easeInBack: function(t) {
|
||||
var s = 1.70158;
|
||||
return 1 * (t /= 1) * t * ((s + 1) * t - s);
|
||||
},
|
||||
easeOutBack: function(t) {
|
||||
var s = 1.70158;
|
||||
return 1 * ((t = t / 1 - 1) * t * ((s + 1) * t + s) + 1);
|
||||
},
|
||||
easeInOutBack: function(t) {
|
||||
var s = 1.70158;
|
||||
if ((t /= 1 / 2) < 1) {
|
||||
return 1 / 2 * (t * t * (((s *= (1.525)) + 1) * t - s));
|
||||
}
|
||||
return 1 / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2);
|
||||
},
|
||||
easeInBounce: function(t) {
|
||||
return 1 - easingEffects.easeOutBounce(1 - t);
|
||||
},
|
||||
easeOutBounce: function(t) {
|
||||
if ((t /= 1) < (1 / 2.75)) {
|
||||
return 1 * (7.5625 * t * t);
|
||||
} else if (t < (2 / 2.75)) {
|
||||
return 1 * (7.5625 * (t -= (1.5 / 2.75)) * t + 0.75);
|
||||
} else if (t < (2.5 / 2.75)) {
|
||||
return 1 * (7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375);
|
||||
} else {
|
||||
return 1 * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375);
|
||||
}
|
||||
},
|
||||
easeInOutBounce: function(t) {
|
||||
if (t < 1 / 2) {
|
||||
return easingEffects.easeInBounce(t * 2) * 0.5;
|
||||
}
|
||||
return easingEffects.easeOutBounce(t * 2 - 1) * 0.5 + 1 * 0.5;
|
||||
}
|
||||
};
|
||||
//Request animation polyfill - http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
|
||||
helpers.requestAnimFrame = (function() {
|
||||
return window.requestAnimationFrame ||
|
||||
window.webkitRequestAnimationFrame ||
|
||||
window.mozRequestAnimationFrame ||
|
||||
window.oRequestAnimationFrame ||
|
||||
window.msRequestAnimationFrame ||
|
||||
function(callback) {
|
||||
return window.setTimeout(callback, 1000 / 60);
|
||||
};
|
||||
})();
|
||||
helpers.cancelAnimFrame = (function() {
|
||||
return window.cancelAnimationFrame ||
|
||||
window.webkitCancelAnimationFrame ||
|
||||
window.mozCancelAnimationFrame ||
|
||||
window.oCancelAnimationFrame ||
|
||||
window.msCancelAnimationFrame ||
|
||||
function(callback) {
|
||||
return window.clearTimeout(callback, 1000 / 60);
|
||||
};
|
||||
})();
|
||||
//-- DOM methods
|
||||
helpers.getRelativePosition = function(evt, chart) {
|
||||
var mouseX, mouseY;
|
||||
var e = evt.originalEvent || evt,
|
||||
canvas = evt.currentTarget || evt.srcElement,
|
||||
boundingRect = canvas.getBoundingClientRect();
|
||||
|
||||
if (e.touches && e.touches.length > 0) {
|
||||
mouseX = e.touches[0].clientX;
|
||||
mouseY = e.touches[0].clientY;
|
||||
|
||||
} else {
|
||||
mouseX = e.clientX;
|
||||
mouseY = e.clientY;
|
||||
}
|
||||
|
||||
// Scale mouse coordinates into canvas coordinates
|
||||
// by following the pattern laid out by 'jerryj' in the comments of
|
||||
// http://www.html5canvastutorials.com/advanced/html5-canvas-mouse-coordinates/
|
||||
var paddingLeft = parseFloat(helpers.getStyle(canvas, 'padding-left'));
|
||||
var paddingTop = parseFloat(helpers.getStyle(canvas, 'padding-top'));
|
||||
var paddingRight = parseFloat(helpers.getStyle(canvas, 'padding-right'));
|
||||
var paddingBottom = parseFloat(helpers.getStyle(canvas, 'padding-bottom'));
|
||||
var width = boundingRect.right - boundingRect.left - paddingLeft - paddingRight;
|
||||
var height = boundingRect.bottom - boundingRect.top - paddingTop - paddingBottom;
|
||||
|
||||
// We divide by the current device pixel ratio, because the canvas is scaled up by that amount in each direction. However
|
||||
// the backend model is in unscaled coordinates. Since we are going to deal with our model coordinates, we go back here
|
||||
mouseX = Math.round((mouseX - boundingRect.left - paddingLeft) / (width) * canvas.width / chart.currentDevicePixelRatio);
|
||||
mouseY = Math.round((mouseY - boundingRect.top - paddingTop) / (height) * canvas.height / chart.currentDevicePixelRatio);
|
||||
|
||||
return {
|
||||
x: mouseX,
|
||||
y: mouseY
|
||||
};
|
||||
|
||||
};
|
||||
helpers.addEvent = function(node, eventType, method) {
|
||||
if (node.addEventListener) {
|
||||
node.addEventListener(eventType, method);
|
||||
} else if (node.attachEvent) {
|
||||
node.attachEvent("on" + eventType, method);
|
||||
} else {
|
||||
node["on" + eventType] = method;
|
||||
}
|
||||
};
|
||||
helpers.removeEvent = function(node, eventType, handler) {
|
||||
if (node.removeEventListener) {
|
||||
node.removeEventListener(eventType, handler, false);
|
||||
} else if (node.detachEvent) {
|
||||
node.detachEvent("on" + eventType, handler);
|
||||
} else {
|
||||
node["on" + eventType] = helpers.noop;
|
||||
}
|
||||
};
|
||||
helpers.bindEvents = function(chartInstance, arrayOfEvents, handler) {
|
||||
// Create the events object if it's not already present
|
||||
if (!chartInstance.events)
|
||||
chartInstance.events = {};
|
||||
|
||||
helpers.each(arrayOfEvents, function(eventName) {
|
||||
chartInstance.events[eventName] = function() {
|
||||
handler.apply(chartInstance, arguments);
|
||||
};
|
||||
helpers.addEvent(chartInstance.chart.canvas, eventName, chartInstance.events[eventName]);
|
||||
});
|
||||
};
|
||||
helpers.unbindEvents = function(chartInstance, arrayOfEvents) {
|
||||
helpers.each(arrayOfEvents, function(handler, eventName) {
|
||||
helpers.removeEvent(chartInstance.chart.canvas, eventName, handler);
|
||||
});
|
||||
};
|
||||
|
||||
// Private helper function to convert max-width/max-height values that may be percentages into a number
|
||||
function parseMaxStyle(styleValue, node, parentProperty) {
|
||||
var valueInPixels;
|
||||
if (typeof(styleValue) === 'string') {
|
||||
valueInPixels = parseInt(styleValue, 10);
|
||||
|
||||
if (styleValue.indexOf('%') != -1) {
|
||||
// percentage * size in dimension
|
||||
valueInPixels = valueInPixels / 100 * node.parentNode[parentProperty];
|
||||
}
|
||||
} else {
|
||||
valueInPixels = styleValue;
|
||||
}
|
||||
|
||||
return valueInPixels;
|
||||
}
|
||||
|
||||
// Private helper to get a constraint dimension
|
||||
// @param domNode : the node to check the constraint on
|
||||
// @param maxStyle : the style that defines the maximum for the direction we are using (max-width / max-height)
|
||||
// @param percentageProperty : property of parent to use when calculating width as a percentage
|
||||
function getConstraintDimension(domNode, maxStyle, percentageProperty) {
|
||||
var constrainedDimension;
|
||||
var constrainedNode = document.defaultView.getComputedStyle(domNode)[maxStyle];
|
||||
var constrainedContainer = document.defaultView.getComputedStyle(domNode.parentNode)[maxStyle];
|
||||
var hasCNode = constrainedNode !== null && constrainedNode !== "none";
|
||||
var hasCContainer = constrainedContainer !== null && constrainedContainer !== "none";
|
||||
|
||||
if (hasCNode || hasCContainer) {
|
||||
constrainedDimension = Math.min((hasCNode ? parseMaxStyle(constrainedNode, domNode, percentageProperty) : Number.POSITIVE_INFINITY), (hasCContainer ? parseMaxStyle(constrainedContainer, domNode.parentNode, percentageProperty) : Number.POSITIVE_INFINITY));
|
||||
}
|
||||
return constrainedDimension;
|
||||
}
|
||||
// returns Number or undefined if no constraint
|
||||
helpers.getConstraintWidth = function(domNode) {
|
||||
return getConstraintDimension(domNode, 'max-width', 'clientWidth');
|
||||
};
|
||||
// returns Number or undefined if no constraint
|
||||
helpers.getConstraintHeight = function(domNode) {
|
||||
return getConstraintDimension(domNode, 'max-height', 'clientHeight');
|
||||
};
|
||||
helpers.getMaximumWidth = function(domNode) {
|
||||
var container = domNode.parentNode;
|
||||
var padding = parseInt(helpers.getStyle(container, 'padding-left')) + parseInt(helpers.getStyle(container, 'padding-right'));
|
||||
|
||||
var w = container.clientWidth - padding;
|
||||
var cw = helpers.getConstraintWidth(domNode);
|
||||
if (cw !== undefined) {
|
||||
w = Math.min(w, cw);
|
||||
}
|
||||
|
||||
return w;
|
||||
};
|
||||
helpers.getMaximumHeight = function(domNode) {
|
||||
var container = domNode.parentNode;
|
||||
var padding = parseInt(helpers.getStyle(container, 'padding-top')) + parseInt(helpers.getStyle(container, 'padding-bottom'));
|
||||
|
||||
var h = container.clientHeight - padding;
|
||||
var ch = helpers.getConstraintHeight(domNode);
|
||||
if (ch !== undefined) {
|
||||
h = Math.min(h, ch);
|
||||
}
|
||||
|
||||
return h;
|
||||
};
|
||||
helpers.getStyle = function(el, property) {
|
||||
return el.currentStyle ?
|
||||
el.currentStyle[property] :
|
||||
document.defaultView.getComputedStyle(el, null).getPropertyValue(property);
|
||||
};
|
||||
helpers.retinaScale = function(chart) {
|
||||
var ctx = chart.ctx;
|
||||
var width = chart.canvas.width;
|
||||
var height = chart.canvas.height;
|
||||
var pixelRatio = chart.currentDevicePixelRatio = window.devicePixelRatio || 1;
|
||||
|
||||
if (pixelRatio !== 1) {
|
||||
ctx.canvas.height = height * pixelRatio;
|
||||
ctx.canvas.width = width * pixelRatio;
|
||||
ctx.scale(pixelRatio, pixelRatio);
|
||||
|
||||
// Store the device pixel ratio so that we can go backwards in `destroy`.
|
||||
// The devicePixelRatio changes with zoom, so there are no guarantees that it is the same
|
||||
// when destroy is called
|
||||
chart.originalDevicePixelRatio = chart.originalDevicePixelRatio || pixelRatio;
|
||||
}
|
||||
|
||||
ctx.canvas.style.width = width + 'px';
|
||||
ctx.canvas.style.height = height + 'px';
|
||||
};
|
||||
//-- Canvas methods
|
||||
helpers.clear = function(chart) {
|
||||
chart.ctx.clearRect(0, 0, chart.width, chart.height);
|
||||
};
|
||||
helpers.fontString = function(pixelSize, fontStyle, fontFamily) {
|
||||
return fontStyle + " " + pixelSize + "px " + fontFamily;
|
||||
};
|
||||
helpers.longestText = function(ctx, font, arrayOfStrings, cache) {
|
||||
cache = cache || {};
|
||||
cache.data = cache.data || {};
|
||||
cache.garbageCollect = cache.garbageCollect || [];
|
||||
|
||||
if (cache.font !== font) {
|
||||
cache.data = {};
|
||||
cache.garbageCollect = [];
|
||||
cache.font = font;
|
||||
}
|
||||
|
||||
ctx.font = font;
|
||||
var longest = 0;
|
||||
helpers.each(arrayOfStrings, function(string) {
|
||||
// Undefined strings should not be measured
|
||||
if (string !== undefined && string !== null) {
|
||||
var textWidth = cache.data[string];
|
||||
if (!textWidth) {
|
||||
textWidth = cache.data[string] = ctx.measureText(string).width;
|
||||
cache.garbageCollect.push(string);
|
||||
}
|
||||
|
||||
if (textWidth > longest) {
|
||||
longest = textWidth;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var gcLen = cache.garbageCollect.length / 2;
|
||||
if (gcLen > arrayOfStrings.length) {
|
||||
for (var i = 0; i < gcLen; i++) {
|
||||
delete cache.data[cache.garbageCollect[i]];
|
||||
}
|
||||
cache.garbageCollect.splice(0, gcLen);
|
||||
}
|
||||
|
||||
return longest;
|
||||
};
|
||||
helpers.drawRoundedRectangle = function(ctx, x, y, width, height, radius) {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x + radius, y);
|
||||
ctx.lineTo(x + width - radius, y);
|
||||
ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
|
||||
ctx.lineTo(x + width, y + height - radius);
|
||||
ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
|
||||
ctx.lineTo(x + radius, y + height);
|
||||
ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
|
||||
ctx.lineTo(x, y + radius);
|
||||
ctx.quadraticCurveTo(x, y, x + radius, y);
|
||||
ctx.closePath();
|
||||
};
|
||||
helpers.color = function(c) {
|
||||
if (!color) {
|
||||
console.log('Color.js not found!');
|
||||
return c;
|
||||
}
|
||||
return color(c);
|
||||
};
|
||||
helpers.addResizeListener = function(node, callback) {
|
||||
// Hide an iframe before the node
|
||||
var hiddenIframe = document.createElement('iframe');
|
||||
var hiddenIframeClass = 'chartjs-hidden-iframe';
|
||||
|
||||
if (hiddenIframe.classlist) {
|
||||
// can use classlist
|
||||
hiddenIframe.classlist.add(hiddenIframeClass);
|
||||
} else {
|
||||
hiddenIframe.setAttribute('class', hiddenIframeClass);
|
||||
}
|
||||
|
||||
// Set the style
|
||||
hiddenIframe.style.width = '100%';
|
||||
hiddenIframe.style.display = 'block';
|
||||
hiddenIframe.style.border = 0;
|
||||
hiddenIframe.style.height = 0;
|
||||
hiddenIframe.style.margin = 0;
|
||||
hiddenIframe.style.position = 'absolute';
|
||||
hiddenIframe.style.left = 0;
|
||||
hiddenIframe.style.right = 0;
|
||||
hiddenIframe.style.top = 0;
|
||||
hiddenIframe.style.bottom = 0;
|
||||
|
||||
// Insert the iframe so that contentWindow is available
|
||||
node.insertBefore(hiddenIframe, node.firstChild);
|
||||
|
||||
(hiddenIframe.contentWindow || hiddenIframe).onresize = function() {
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
};
|
||||
helpers.removeResizeListener = function(node) {
|
||||
var hiddenIframe = node.querySelector('.chartjs-hidden-iframe');
|
||||
|
||||
// Remove the resize detect iframe
|
||||
if (hiddenIframe) {
|
||||
hiddenIframe.parentNode.removeChild(hiddenIframe);
|
||||
}
|
||||
};
|
||||
helpers.isArray = function(obj) {
|
||||
if (!Array.isArray) {
|
||||
return Object.prototype.toString.call(obj) === '[object Array]';
|
||||
}
|
||||
return Array.isArray(obj);
|
||||
};
|
||||
helpers.pushAllIfDefined = function(element, array) {
|
||||
if (typeof element === "undefined") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (helpers.isArray(element)) {
|
||||
array.push.apply(array, element);
|
||||
} else {
|
||||
array.push(element);
|
||||
}
|
||||
};
|
||||
helpers.isDatasetVisible = function(dataset) {
|
||||
return !dataset.hidden;
|
||||
};
|
||||
helpers.callCallback = function(fn, args, _tArg) {
|
||||
if (fn && typeof fn.call === 'function') {
|
||||
fn.apply(_tArg, args);
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
Arquivo executável
+104
@@ -0,0 +1,104 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = function() {
|
||||
|
||||
//Occupy the global variable of Chart, and create a simple base class
|
||||
var Chart = function(context, config) {
|
||||
this.config = config;
|
||||
|
||||
// Support a jQuery'd canvas element
|
||||
if (context.length && context[0].getContext) {
|
||||
context = context[0];
|
||||
}
|
||||
|
||||
// Support a canvas domnode
|
||||
if (context.getContext) {
|
||||
context = context.getContext("2d");
|
||||
}
|
||||
|
||||
this.ctx = context;
|
||||
this.canvas = context.canvas;
|
||||
|
||||
// Figure out what the size of the chart will be.
|
||||
// If the canvas has a specified width and height, we use those else
|
||||
// we look to see if the canvas node has a CSS width and height.
|
||||
// If there is still no height, fill the parent container
|
||||
this.width = context.canvas.width || parseInt(Chart.helpers.getStyle(context.canvas, 'width')) || Chart.helpers.getMaximumWidth(context.canvas);
|
||||
this.height = context.canvas.height || parseInt(Chart.helpers.getStyle(context.canvas, 'height')) || Chart.helpers.getMaximumHeight(context.canvas);
|
||||
|
||||
this.aspectRatio = this.width / this.height;
|
||||
|
||||
if (isNaN(this.aspectRatio) || isFinite(this.aspectRatio) === false) {
|
||||
// If the canvas has no size, try and figure out what the aspect ratio will be.
|
||||
// Some charts prefer square canvases (pie, radar, etc). If that is specified, use that
|
||||
// else use the canvas default ratio of 2
|
||||
this.aspectRatio = config.aspectRatio !== undefined ? config.aspectRatio : 2;
|
||||
}
|
||||
|
||||
// Store the original style of the element so we can set it back
|
||||
this.originalCanvasStyleWidth = context.canvas.style.width;
|
||||
this.originalCanvasStyleHeight = context.canvas.style.height;
|
||||
|
||||
// High pixel density displays - multiply the size of the canvas height/width by the device pixel ratio, then scale.
|
||||
Chart.helpers.retinaScale(this);
|
||||
|
||||
if (config) {
|
||||
this.controller = new Chart.Controller(this);
|
||||
}
|
||||
|
||||
// Always bind this so that if the responsive state changes we still work
|
||||
var _this = this;
|
||||
Chart.helpers.addResizeListener(context.canvas.parentNode, function() {
|
||||
if (_this.controller && _this.controller.config.options.responsive) {
|
||||
_this.controller.resize();
|
||||
}
|
||||
});
|
||||
|
||||
return this.controller ? this.controller : this;
|
||||
|
||||
};
|
||||
|
||||
//Globally expose the defaults to allow for user updating/changing
|
||||
Chart.defaults = {
|
||||
global: {
|
||||
responsive: true,
|
||||
responsiveAnimationDuration: 0,
|
||||
maintainAspectRatio: true,
|
||||
events: ["mousemove", "mouseout", "click", "touchstart", "touchmove"],
|
||||
hover: {
|
||||
onHover: null,
|
||||
mode: 'single',
|
||||
animationDuration: 400
|
||||
},
|
||||
onClick: null,
|
||||
defaultColor: 'rgba(0,0,0,0.1)',
|
||||
defaultFontColor: '#666',
|
||||
defaultFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
|
||||
defaultFontSize: 12,
|
||||
defaultFontStyle: 'normal',
|
||||
showLines: true,
|
||||
|
||||
// Element defaults defined in element extensions
|
||||
elements: {},
|
||||
|
||||
// Legend callback string
|
||||
legendCallback: function(chart) {
|
||||
var text = [];
|
||||
text.push('<ul class="' + chart.id + '-legend">');
|
||||
for (var i = 0; i < chart.data.datasets.length; i++) {
|
||||
text.push('<li><span style="background-color:' + chart.data.datasets[i].backgroundColor + '">');
|
||||
if (chart.data.datasets[i].label) {
|
||||
text.push(chart.data.datasets[i].label);
|
||||
}
|
||||
text.push('</span></li>');
|
||||
}
|
||||
text.push('</ul>');
|
||||
|
||||
return text.join("");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return Chart;
|
||||
|
||||
};
|
||||
@@ -0,0 +1,323 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = function(Chart) {
|
||||
|
||||
var helpers = Chart.helpers;
|
||||
|
||||
// The layout service is very self explanatory. It's responsible for the layout within a chart.
|
||||
// Scales, Legends and Plugins all rely on the layout service and can easily register to be placed anywhere they need
|
||||
// It is this service's responsibility of carrying out that layout.
|
||||
Chart.layoutService = {
|
||||
defaults: {},
|
||||
|
||||
// Register a box to a chartInstance. A box is simply a reference to an object that requires layout. eg. Scales, Legend, Plugins.
|
||||
addBox: function(chartInstance, box) {
|
||||
if (!chartInstance.boxes) {
|
||||
chartInstance.boxes = [];
|
||||
}
|
||||
chartInstance.boxes.push(box);
|
||||
},
|
||||
|
||||
removeBox: function(chartInstance, box) {
|
||||
if (!chartInstance.boxes) {
|
||||
return;
|
||||
}
|
||||
chartInstance.boxes.splice(chartInstance.boxes.indexOf(box), 1);
|
||||
},
|
||||
|
||||
// The most important function
|
||||
update: function(chartInstance, width, height) {
|
||||
|
||||
if (!chartInstance) {
|
||||
return;
|
||||
}
|
||||
|
||||
var xPadding = 0;
|
||||
var yPadding = 0;
|
||||
|
||||
var leftBoxes = helpers.where(chartInstance.boxes, function(box) {
|
||||
return box.options.position === "left";
|
||||
});
|
||||
var rightBoxes = helpers.where(chartInstance.boxes, function(box) {
|
||||
return box.options.position === "right";
|
||||
});
|
||||
var topBoxes = helpers.where(chartInstance.boxes, function(box) {
|
||||
return box.options.position === "top";
|
||||
});
|
||||
var bottomBoxes = helpers.where(chartInstance.boxes, function(box) {
|
||||
return box.options.position === "bottom";
|
||||
});
|
||||
|
||||
// Boxes that overlay the chartarea such as the radialLinear scale
|
||||
var chartAreaBoxes = helpers.where(chartInstance.boxes, function(box) {
|
||||
return box.options.position === "chartArea";
|
||||
});
|
||||
|
||||
function fullWidthSorter(a, b) {
|
||||
|
||||
}
|
||||
|
||||
// Ensure that full width boxes are at the very top / bottom
|
||||
topBoxes.sort(function(a, b) {
|
||||
return (b.options.fullWidth ? 1 : 0) - (a.options.fullWidth ? 1 : 0);
|
||||
});
|
||||
bottomBoxes.sort(function(a, b) {
|
||||
return (a.options.fullWidth ? 1 : 0) - (b.options.fullWidth ? 1 : 0);
|
||||
});
|
||||
|
||||
// Essentially we now have any number of boxes on each of the 4 sides.
|
||||
// Our canvas looks like the following.
|
||||
// The areas L1 and L2 are the left axes. R1 is the right axis, T1 is the top axis and
|
||||
// B1 is the bottom axis
|
||||
// There are also 4 quadrant-like locations (left to right instead of clockwise) reserved for chart overlays
|
||||
// These locations are single-box locations only, when trying to register a chartArea location that is already taken,
|
||||
// an error will be thrown.
|
||||
//
|
||||
// |----------------------------------------------------|
|
||||
// | T1 (Full Width) |
|
||||
// |----------------------------------------------------|
|
||||
// | | | T2 | |
|
||||
// | |----|-------------------------------------|----|
|
||||
// | | | C1 | | C2 | |
|
||||
// | | |----| |----| |
|
||||
// | | | | |
|
||||
// | L1 | L2 | ChartArea (C0) | R1 |
|
||||
// | | | | |
|
||||
// | | |----| |----| |
|
||||
// | | | C3 | | C4 | |
|
||||
// | |----|-------------------------------------|----|
|
||||
// | | | B1 | |
|
||||
// |----------------------------------------------------|
|
||||
// | B2 (Full Width) |
|
||||
// |----------------------------------------------------|
|
||||
//
|
||||
// What we do to find the best sizing, we do the following
|
||||
// 1. Determine the minimum size of the chart area.
|
||||
// 2. Split the remaining width equally between each vertical axis
|
||||
// 3. Split the remaining height equally between each horizontal axis
|
||||
// 4. Give each layout the maximum size it can be. The layout will return it's minimum size
|
||||
// 5. Adjust the sizes of each axis based on it's minimum reported size.
|
||||
// 6. Refit each axis
|
||||
// 7. Position each axis in the final location
|
||||
// 8. Tell the chart the final location of the chart area
|
||||
// 9. Tell any axes that overlay the chart area the positions of the chart area
|
||||
|
||||
// Step 1
|
||||
var chartWidth = width - (2 * xPadding);
|
||||
var chartHeight = height - (2 * yPadding);
|
||||
var chartAreaWidth = chartWidth / 2; // min 50%
|
||||
var chartAreaHeight = chartHeight / 2; // min 50%
|
||||
|
||||
// Step 2
|
||||
var verticalBoxWidth = (width - chartAreaWidth) / (leftBoxes.length + rightBoxes.length);
|
||||
|
||||
// Step 3
|
||||
var horizontalBoxHeight = (height - chartAreaHeight) / (topBoxes.length + bottomBoxes.length);
|
||||
|
||||
// Step 4
|
||||
var maxChartAreaWidth = chartWidth;
|
||||
var maxChartAreaHeight = chartHeight;
|
||||
var minBoxSizes = [];
|
||||
|
||||
helpers.each(leftBoxes.concat(rightBoxes, topBoxes, bottomBoxes), getMinimumBoxSize);
|
||||
|
||||
function getMinimumBoxSize(box) {
|
||||
var minSize;
|
||||
var isHorizontal = box.isHorizontal();
|
||||
|
||||
if (isHorizontal) {
|
||||
minSize = box.update(box.options.fullWidth ? chartWidth : maxChartAreaWidth, horizontalBoxHeight);
|
||||
maxChartAreaHeight -= minSize.height;
|
||||
} else {
|
||||
minSize = box.update(verticalBoxWidth, chartAreaHeight);
|
||||
maxChartAreaWidth -= minSize.width;
|
||||
}
|
||||
|
||||
minBoxSizes.push({
|
||||
horizontal: isHorizontal,
|
||||
minSize: minSize,
|
||||
box: box
|
||||
});
|
||||
}
|
||||
|
||||
// At this point, maxChartAreaHeight and maxChartAreaWidth are the size the chart area could
|
||||
// be if the axes are drawn at their minimum sizes.
|
||||
|
||||
// Steps 5 & 6
|
||||
var totalLeftBoxesWidth = xPadding;
|
||||
var totalRightBoxesWidth = xPadding;
|
||||
var totalTopBoxesHeight = yPadding;
|
||||
var totalBottomBoxesHeight = yPadding;
|
||||
|
||||
// Update, and calculate the left and right margins for the horizontal boxes
|
||||
helpers.each(leftBoxes.concat(rightBoxes), fitBox);
|
||||
|
||||
helpers.each(leftBoxes, function(box) {
|
||||
totalLeftBoxesWidth += box.width;
|
||||
});
|
||||
|
||||
helpers.each(rightBoxes, function(box) {
|
||||
totalRightBoxesWidth += box.width;
|
||||
});
|
||||
|
||||
// Set the Left and Right margins for the horizontal boxes
|
||||
helpers.each(topBoxes.concat(bottomBoxes), fitBox);
|
||||
|
||||
// Function to fit a box
|
||||
function fitBox(box) {
|
||||
var minBoxSize = helpers.findNextWhere(minBoxSizes, function(minBoxSize) {
|
||||
return minBoxSize.box === box;
|
||||
});
|
||||
|
||||
if (minBoxSize) {
|
||||
if (box.isHorizontal()) {
|
||||
var scaleMargin = {
|
||||
left: totalLeftBoxesWidth,
|
||||
right: totalRightBoxesWidth,
|
||||
top: 0,
|
||||
bottom: 0
|
||||
};
|
||||
|
||||
// Don't use min size here because of label rotation. When the labels are rotated, their rotation highly depends
|
||||
// on the margin. Sometimes they need to increase in size slightly
|
||||
box.update(box.options.fullWidth ? chartWidth : maxChartAreaWidth, chartHeight / 2, scaleMargin);
|
||||
} else {
|
||||
box.update(minBoxSize.minSize.width, maxChartAreaHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Figure out how much margin is on the top and bottom of the vertical boxes
|
||||
helpers.each(topBoxes, function(box) {
|
||||
totalTopBoxesHeight += box.height;
|
||||
});
|
||||
|
||||
helpers.each(bottomBoxes, function(box) {
|
||||
totalBottomBoxesHeight += box.height;
|
||||
});
|
||||
|
||||
// Let the left layout know the final margin
|
||||
helpers.each(leftBoxes.concat(rightBoxes), finalFitVerticalBox);
|
||||
|
||||
function finalFitVerticalBox(box) {
|
||||
var minBoxSize = helpers.findNextWhere(minBoxSizes, function(minBoxSize) {
|
||||
return minBoxSize.box === box;
|
||||
});
|
||||
|
||||
var scaleMargin = {
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: totalTopBoxesHeight,
|
||||
bottom: totalBottomBoxesHeight
|
||||
};
|
||||
|
||||
if (minBoxSize) {
|
||||
box.update(minBoxSize.minSize.width, maxChartAreaHeight, scaleMargin);
|
||||
}
|
||||
}
|
||||
|
||||
// Recalculate because the size of each layout might have changed slightly due to the margins (label rotation for instance)
|
||||
totalLeftBoxesWidth = xPadding;
|
||||
totalRightBoxesWidth = xPadding;
|
||||
totalTopBoxesHeight = yPadding;
|
||||
totalBottomBoxesHeight = yPadding;
|
||||
|
||||
helpers.each(leftBoxes, function(box) {
|
||||
totalLeftBoxesWidth += box.width;
|
||||
});
|
||||
|
||||
helpers.each(rightBoxes, function(box) {
|
||||
totalRightBoxesWidth += box.width;
|
||||
});
|
||||
|
||||
helpers.each(topBoxes, function(box) {
|
||||
totalTopBoxesHeight += box.height;
|
||||
});
|
||||
helpers.each(bottomBoxes, function(box) {
|
||||
totalBottomBoxesHeight += box.height;
|
||||
});
|
||||
|
||||
// Figure out if our chart area changed. This would occur if the dataset layout label rotation
|
||||
// changed due to the application of the margins in step 6. Since we can only get bigger, this is safe to do
|
||||
// without calling `fit` again
|
||||
var newMaxChartAreaHeight = height - totalTopBoxesHeight - totalBottomBoxesHeight;
|
||||
var newMaxChartAreaWidth = width - totalLeftBoxesWidth - totalRightBoxesWidth;
|
||||
|
||||
if (newMaxChartAreaWidth !== maxChartAreaWidth || newMaxChartAreaHeight !== maxChartAreaHeight) {
|
||||
helpers.each(leftBoxes, function(box) {
|
||||
box.height = newMaxChartAreaHeight;
|
||||
});
|
||||
|
||||
helpers.each(rightBoxes, function(box) {
|
||||
box.height = newMaxChartAreaHeight;
|
||||
});
|
||||
|
||||
helpers.each(topBoxes, function(box) {
|
||||
box.width = newMaxChartAreaWidth;
|
||||
});
|
||||
|
||||
helpers.each(bottomBoxes, function(box) {
|
||||
box.width = newMaxChartAreaWidth;
|
||||
});
|
||||
|
||||
maxChartAreaHeight = newMaxChartAreaHeight;
|
||||
maxChartAreaWidth = newMaxChartAreaWidth;
|
||||
}
|
||||
|
||||
// Step 7 - Position the boxes
|
||||
var left = xPadding;
|
||||
var top = yPadding;
|
||||
var right = 0;
|
||||
var bottom = 0;
|
||||
|
||||
helpers.each(leftBoxes.concat(topBoxes), placeBox);
|
||||
|
||||
// Account for chart width and height
|
||||
left += maxChartAreaWidth;
|
||||
top += maxChartAreaHeight;
|
||||
|
||||
helpers.each(rightBoxes, placeBox);
|
||||
helpers.each(bottomBoxes, placeBox);
|
||||
|
||||
function placeBox(box) {
|
||||
if (box.isHorizontal()) {
|
||||
box.left = box.options.fullWidth ? xPadding : totalLeftBoxesWidth;
|
||||
box.right = box.options.fullWidth ? width - xPadding : totalLeftBoxesWidth + maxChartAreaWidth;
|
||||
box.top = top;
|
||||
box.bottom = top + box.height;
|
||||
|
||||
// Move to next point
|
||||
top = box.bottom;
|
||||
|
||||
} else {
|
||||
|
||||
box.left = left;
|
||||
box.right = left + box.width;
|
||||
box.top = totalTopBoxesHeight;
|
||||
box.bottom = totalTopBoxesHeight + maxChartAreaHeight;
|
||||
|
||||
// Move to next point
|
||||
left = box.right;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 8
|
||||
chartInstance.chartArea = {
|
||||
left: totalLeftBoxesWidth,
|
||||
top: totalTopBoxesHeight,
|
||||
right: totalLeftBoxesWidth + maxChartAreaWidth,
|
||||
bottom: totalTopBoxesHeight + maxChartAreaHeight
|
||||
};
|
||||
|
||||
// Step 9
|
||||
helpers.each(chartAreaBoxes, function(box) {
|
||||
box.left = chartInstance.chartArea.left;
|
||||
box.top = chartInstance.chartArea.top;
|
||||
box.right = chartInstance.chartArea.right;
|
||||
box.bottom = chartInstance.chartArea.bottom;
|
||||
|
||||
box.update(maxChartAreaWidth, maxChartAreaHeight);
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,331 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = function(Chart) {
|
||||
|
||||
var helpers = Chart.helpers;
|
||||
|
||||
Chart.defaults.global.legend = {
|
||||
|
||||
display: true,
|
||||
position: 'top',
|
||||
fullWidth: true, // marks that this box should take the full width of the canvas (pushing down other boxes)
|
||||
reverse: false,
|
||||
|
||||
// a callback that will handle
|
||||
onClick: function(e, legendItem) {
|
||||
var dataset = this.chart.data.datasets[legendItem.datasetIndex];
|
||||
dataset.hidden = !dataset.hidden;
|
||||
|
||||
// We hid a dataset ... rerender the chart
|
||||
this.chart.update();
|
||||
},
|
||||
|
||||
labels: {
|
||||
boxWidth: 40,
|
||||
padding: 10,
|
||||
// Generates labels shown in the legend
|
||||
// Valid properties to return:
|
||||
// text : text to display
|
||||
// fillStyle : fill of coloured box
|
||||
// strokeStyle: stroke of coloured box
|
||||
// hidden : if this legend item refers to a hidden item
|
||||
// lineCap : cap style for line
|
||||
// lineDash
|
||||
// lineDashOffset :
|
||||
// lineJoin :
|
||||
// lineWidth :
|
||||
generateLabels: function(data) {
|
||||
return helpers.isArray(data.datasets) ? data.datasets.map(function(dataset, i) {
|
||||
return {
|
||||
text: dataset.label,
|
||||
fillStyle: dataset.backgroundColor,
|
||||
hidden: dataset.hidden,
|
||||
lineCap: dataset.borderCapStyle,
|
||||
lineDash: dataset.borderDash,
|
||||
lineDashOffset: dataset.borderDashOffset,
|
||||
lineJoin: dataset.borderJoinStyle,
|
||||
lineWidth: dataset.borderWidth,
|
||||
strokeStyle: dataset.borderColor,
|
||||
|
||||
// Below is extra data used for toggling the datasets
|
||||
datasetIndex: i
|
||||
};
|
||||
}, this) : [];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Chart.Legend = Chart.Element.extend({
|
||||
|
||||
initialize: function(config) {
|
||||
helpers.extend(this, config);
|
||||
|
||||
// Contains hit boxes for each dataset (in dataset order)
|
||||
this.legendHitBoxes = [];
|
||||
|
||||
// Are we in doughnut mode which has a different data type
|
||||
this.doughnutMode = false;
|
||||
},
|
||||
|
||||
// These methods are ordered by lifecyle. Utilities then follow.
|
||||
// Any function defined here is inherited by all legend types.
|
||||
// Any function can be extended by the legend type
|
||||
|
||||
beforeUpdate: helpers.noop,
|
||||
update: function(maxWidth, maxHeight, margins) {
|
||||
|
||||
// Update Lifecycle - Probably don't want to ever extend or overwrite this function ;)
|
||||
this.beforeUpdate();
|
||||
|
||||
// Absorb the master measurements
|
||||
this.maxWidth = maxWidth;
|
||||
this.maxHeight = maxHeight;
|
||||
this.margins = margins;
|
||||
|
||||
// Dimensions
|
||||
this.beforeSetDimensions();
|
||||
this.setDimensions();
|
||||
this.afterSetDimensions();
|
||||
// Labels
|
||||
this.beforeBuildLabels();
|
||||
this.buildLabels();
|
||||
this.afterBuildLabels();
|
||||
|
||||
// Fit
|
||||
this.beforeFit();
|
||||
this.fit();
|
||||
this.afterFit();
|
||||
//
|
||||
this.afterUpdate();
|
||||
|
||||
return this.minSize;
|
||||
|
||||
},
|
||||
afterUpdate: helpers.noop,
|
||||
|
||||
//
|
||||
|
||||
beforeSetDimensions: helpers.noop,
|
||||
setDimensions: function() {
|
||||
// Set the unconstrained dimension before label rotation
|
||||
if (this.isHorizontal()) {
|
||||
// Reset position before calculating rotation
|
||||
this.width = this.maxWidth;
|
||||
this.left = 0;
|
||||
this.right = this.width;
|
||||
} else {
|
||||
this.height = this.maxHeight;
|
||||
|
||||
// Reset position before calculating rotation
|
||||
this.top = 0;
|
||||
this.bottom = this.height;
|
||||
}
|
||||
|
||||
// Reset padding
|
||||
this.paddingLeft = 0;
|
||||
this.paddingTop = 0;
|
||||
this.paddingRight = 0;
|
||||
this.paddingBottom = 0;
|
||||
|
||||
// Reset minSize
|
||||
this.minSize = {
|
||||
width: 0,
|
||||
height: 0
|
||||
};
|
||||
},
|
||||
afterSetDimensions: helpers.noop,
|
||||
|
||||
//
|
||||
|
||||
beforeBuildLabels: helpers.noop,
|
||||
buildLabels: function() {
|
||||
this.legendItems = this.options.labels.generateLabels.call(this, this.chart.data);
|
||||
if(this.options.reverse){
|
||||
this.legendItems.reverse();
|
||||
}
|
||||
},
|
||||
afterBuildLabels: helpers.noop,
|
||||
|
||||
//
|
||||
|
||||
beforeFit: helpers.noop,
|
||||
fit: function() {
|
||||
|
||||
var ctx = this.ctx;
|
||||
var fontSize = helpers.getValueOrDefault(this.options.labels.fontSize, Chart.defaults.global.defaultFontSize);
|
||||
var fontStyle = helpers.getValueOrDefault(this.options.labels.fontStyle, Chart.defaults.global.defaultFontStyle);
|
||||
var fontFamily = helpers.getValueOrDefault(this.options.labels.fontFamily, Chart.defaults.global.defaultFontFamily);
|
||||
var labelFont = helpers.fontString(fontSize, fontStyle, fontFamily);
|
||||
|
||||
// Reset hit boxes
|
||||
this.legendHitBoxes = [];
|
||||
|
||||
// Width
|
||||
if (this.isHorizontal()) {
|
||||
this.minSize.width = this.maxWidth; // fill all the width
|
||||
} else {
|
||||
this.minSize.width = this.options.display ? 10 : 0;
|
||||
}
|
||||
|
||||
// height
|
||||
if (this.isHorizontal()) {
|
||||
this.minSize.height = this.options.display ? 10 : 0;
|
||||
} else {
|
||||
this.minSize.height = this.maxHeight; // fill all the height
|
||||
}
|
||||
|
||||
// Increase sizes here
|
||||
if (this.options.display) {
|
||||
if (this.isHorizontal()) {
|
||||
// Labels
|
||||
|
||||
// Width of each line of legend boxes. Labels wrap onto multiple lines when there are too many to fit on one
|
||||
this.lineWidths = [0];
|
||||
var totalHeight = this.legendItems.length ? fontSize + (this.options.labels.padding) : 0;
|
||||
|
||||
ctx.textAlign = "left";
|
||||
ctx.textBaseline = 'top';
|
||||
ctx.font = labelFont;
|
||||
|
||||
helpers.each(this.legendItems, function(legendItem, i) {
|
||||
var width = this.options.labels.boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width;
|
||||
if (this.lineWidths[this.lineWidths.length - 1] + width + this.options.labels.padding >= this.width) {
|
||||
totalHeight += fontSize + (this.options.labels.padding);
|
||||
this.lineWidths[this.lineWidths.length] = this.left;
|
||||
}
|
||||
|
||||
// Store the hitbox width and height here. Final position will be updated in `draw`
|
||||
this.legendHitBoxes[i] = {
|
||||
left: 0,
|
||||
top: 0,
|
||||
width: width,
|
||||
height: fontSize
|
||||
};
|
||||
|
||||
this.lineWidths[this.lineWidths.length - 1] += width + this.options.labels.padding;
|
||||
}, this);
|
||||
|
||||
this.minSize.height += totalHeight;
|
||||
|
||||
} else {
|
||||
// TODO vertical
|
||||
}
|
||||
}
|
||||
|
||||
this.width = this.minSize.width;
|
||||
this.height = this.minSize.height;
|
||||
|
||||
},
|
||||
afterFit: helpers.noop,
|
||||
|
||||
// Shared Methods
|
||||
isHorizontal: function() {
|
||||
return this.options.position === "top" || this.options.position === "bottom";
|
||||
},
|
||||
|
||||
// Actualy draw the legend on the canvas
|
||||
draw: function() {
|
||||
if (this.options.display) {
|
||||
var ctx = this.ctx;
|
||||
var cursor = {
|
||||
x: this.left + ((this.width - this.lineWidths[0]) / 2),
|
||||
y: this.top + this.options.labels.padding,
|
||||
line: 0
|
||||
};
|
||||
|
||||
var fontColor = helpers.getValueOrDefault(this.options.labels.fontColor, Chart.defaults.global.defaultFontColor);
|
||||
var fontSize = helpers.getValueOrDefault(this.options.labels.fontSize, Chart.defaults.global.defaultFontSize);
|
||||
var fontStyle = helpers.getValueOrDefault(this.options.labels.fontStyle, Chart.defaults.global.defaultFontStyle);
|
||||
var fontFamily = helpers.getValueOrDefault(this.options.labels.fontFamily, Chart.defaults.global.defaultFontFamily);
|
||||
var labelFont = helpers.fontString(fontSize, fontStyle, fontFamily);
|
||||
|
||||
// Horizontal
|
||||
if (this.isHorizontal()) {
|
||||
// Labels
|
||||
ctx.textAlign = "left";
|
||||
ctx.textBaseline = 'top';
|
||||
ctx.lineWidth = 0.5;
|
||||
ctx.strokeStyle = fontColor; // for strikethrough effect
|
||||
ctx.fillStyle = fontColor; // render in correct colour
|
||||
ctx.font = labelFont;
|
||||
|
||||
helpers.each(this.legendItems, function(legendItem, i) {
|
||||
var textWidth = ctx.measureText(legendItem.text).width;
|
||||
var width = this.options.labels.boxWidth + (fontSize / 2) + textWidth;
|
||||
|
||||
if (cursor.x + width >= this.width) {
|
||||
cursor.y += fontSize + (this.options.labels.padding);
|
||||
cursor.line++;
|
||||
cursor.x = this.left + ((this.width - this.lineWidths[cursor.line]) / 2);
|
||||
}
|
||||
|
||||
// Set the ctx for the box
|
||||
ctx.save();
|
||||
|
||||
var itemOrDefault = function(item, defaulVal) {
|
||||
return item !== undefined ? item : defaulVal;
|
||||
};
|
||||
|
||||
ctx.fillStyle = itemOrDefault(legendItem.fillStyle, Chart.defaults.global.defaultColor);
|
||||
ctx.lineCap = itemOrDefault(legendItem.lineCap, Chart.defaults.global.elements.line.borderCapStyle);
|
||||
ctx.lineDashOffset = itemOrDefault(legendItem.lineDashOffset, Chart.defaults.global.elements.line.borderDashOffset);
|
||||
ctx.lineJoin = itemOrDefault(legendItem.lineJoin, Chart.defaults.global.elements.line.borderJoinStyle);
|
||||
ctx.lineWidth = itemOrDefault(legendItem.lineWidth, Chart.defaults.global.elements.line.borderWidth);
|
||||
ctx.strokeStyle = itemOrDefault(legendItem.strokeStyle, Chart.defaults.global.defaultColor);
|
||||
|
||||
if (ctx.setLineDash) {
|
||||
// IE 9 and 10 do not support line dash
|
||||
ctx.setLineDash(itemOrDefault(legendItem.lineDash, Chart.defaults.global.elements.line.borderDash));
|
||||
}
|
||||
|
||||
// Draw the box
|
||||
ctx.strokeRect(cursor.x, cursor.y, this.options.labels.boxWidth, fontSize);
|
||||
ctx.fillRect(cursor.x, cursor.y, this.options.labels.boxWidth, fontSize);
|
||||
|
||||
ctx.restore();
|
||||
|
||||
this.legendHitBoxes[i].left = cursor.x;
|
||||
this.legendHitBoxes[i].top = cursor.y;
|
||||
|
||||
// Fill the actual label
|
||||
ctx.fillText(legendItem.text, this.options.labels.boxWidth + (fontSize / 2) + cursor.x, cursor.y);
|
||||
|
||||
if (legendItem.hidden) {
|
||||
// Strikethrough the text if hidden
|
||||
ctx.beginPath();
|
||||
ctx.lineWidth = 2;
|
||||
ctx.moveTo(this.options.labels.boxWidth + (fontSize / 2) + cursor.x, cursor.y + (fontSize / 2));
|
||||
ctx.lineTo(this.options.labels.boxWidth + (fontSize / 2) + cursor.x + textWidth, cursor.y + (fontSize / 2));
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
cursor.x += width + (this.options.labels.padding);
|
||||
}, this);
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Handle an event
|
||||
handleEvent: function(e) {
|
||||
var position = helpers.getRelativePosition(e, this.chart.chart);
|
||||
|
||||
if (position.x >= this.left && position.x <= this.right && position.y >= this.top && position.y <= this.bottom) {
|
||||
// See if we are touching one of the dataset boxes
|
||||
for (var i = 0; i < this.legendHitBoxes.length; ++i) {
|
||||
var hitBox = this.legendHitBoxes[i];
|
||||
|
||||
if (position.x >= hitBox.left && position.x <= hitBox.left + hitBox.width && position.y >= hitBox.top && position.y <= hitBox.top + hitBox.height) {
|
||||
// Touching an element
|
||||
if (this.options.onClick) {
|
||||
this.options.onClick.call(this, e, this.legendItems[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
@@ -0,0 +1,685 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = function(Chart) {
|
||||
|
||||
var helpers = Chart.helpers;
|
||||
|
||||
Chart.defaults.scale = {
|
||||
display: true,
|
||||
|
||||
// grid line settings
|
||||
gridLines: {
|
||||
display: true,
|
||||
color: "rgba(0, 0, 0, 0.1)",
|
||||
lineWidth: 1,
|
||||
drawOnChartArea: true,
|
||||
drawTicks: true,
|
||||
zeroLineWidth: 1,
|
||||
zeroLineColor: "rgba(0,0,0,0.25)",
|
||||
offsetGridLines: false
|
||||
},
|
||||
|
||||
// scale label
|
||||
scaleLabel: {
|
||||
// actual label
|
||||
labelString: '',
|
||||
|
||||
// display property
|
||||
display: false
|
||||
},
|
||||
|
||||
// label settings
|
||||
ticks: {
|
||||
beginAtZero: false,
|
||||
maxRotation: 90,
|
||||
mirror: false,
|
||||
padding: 10,
|
||||
reverse: false,
|
||||
display: true,
|
||||
autoSkip: true,
|
||||
autoSkipPadding: 20,
|
||||
callback: function(value) {
|
||||
return '' + value;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Chart.Scale = Chart.Element.extend({
|
||||
|
||||
// These methods are ordered by lifecyle. Utilities then follow.
|
||||
// Any function defined here is inherited by all scale types.
|
||||
// Any function can be extended by the scale type
|
||||
|
||||
beforeUpdate: function() {
|
||||
helpers.callCallback(this.options.beforeUpdate, [this]);
|
||||
},
|
||||
update: function(maxWidth, maxHeight, margins) {
|
||||
|
||||
// Update Lifecycle - Probably don't want to ever extend or overwrite this function ;)
|
||||
this.beforeUpdate();
|
||||
|
||||
// Absorb the master measurements
|
||||
this.maxWidth = maxWidth;
|
||||
this.maxHeight = maxHeight;
|
||||
this.margins = helpers.extend({
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: 0,
|
||||
bottom: 0
|
||||
}, margins);
|
||||
|
||||
// Dimensions
|
||||
this.beforeSetDimensions();
|
||||
this.setDimensions();
|
||||
this.afterSetDimensions();
|
||||
|
||||
// Data min/max
|
||||
this.beforeDataLimits();
|
||||
this.determineDataLimits();
|
||||
this.afterDataLimits();
|
||||
|
||||
// Ticks
|
||||
this.beforeBuildTicks();
|
||||
this.buildTicks();
|
||||
this.afterBuildTicks();
|
||||
|
||||
this.beforeTickToLabelConversion();
|
||||
this.convertTicksToLabels();
|
||||
this.afterTickToLabelConversion();
|
||||
|
||||
// Tick Rotation
|
||||
this.beforeCalculateTickRotation();
|
||||
this.calculateTickRotation();
|
||||
this.afterCalculateTickRotation();
|
||||
// Fit
|
||||
this.beforeFit();
|
||||
this.fit();
|
||||
this.afterFit();
|
||||
//
|
||||
this.afterUpdate();
|
||||
|
||||
return this.minSize;
|
||||
|
||||
},
|
||||
afterUpdate: function() {
|
||||
helpers.callCallback(this.options.afterUpdate, [this]);
|
||||
},
|
||||
|
||||
//
|
||||
|
||||
beforeSetDimensions: function() {
|
||||
helpers.callCallback(this.options.beforeSetDimensions, [this]);
|
||||
},
|
||||
setDimensions: function() {
|
||||
// Set the unconstrained dimension before label rotation
|
||||
if (this.isHorizontal()) {
|
||||
// Reset position before calculating rotation
|
||||
this.width = this.maxWidth;
|
||||
this.left = 0;
|
||||
this.right = this.width;
|
||||
} else {
|
||||
this.height = this.maxHeight;
|
||||
|
||||
// Reset position before calculating rotation
|
||||
this.top = 0;
|
||||
this.bottom = this.height;
|
||||
}
|
||||
|
||||
// Reset padding
|
||||
this.paddingLeft = 0;
|
||||
this.paddingTop = 0;
|
||||
this.paddingRight = 0;
|
||||
this.paddingBottom = 0;
|
||||
},
|
||||
afterSetDimensions: function() {
|
||||
helpers.callCallback(this.options.afterSetDimensions, [this]);
|
||||
},
|
||||
|
||||
// Data limits
|
||||
beforeDataLimits: function() {
|
||||
helpers.callCallback(this.options.beforeDataLimits, [this]);
|
||||
},
|
||||
determineDataLimits: helpers.noop,
|
||||
afterDataLimits: function() {
|
||||
helpers.callCallback(this.options.afterDataLimits, [this]);
|
||||
},
|
||||
|
||||
//
|
||||
beforeBuildTicks: function() {
|
||||
helpers.callCallback(this.options.beforeBuildTicks, [this]);
|
||||
},
|
||||
buildTicks: helpers.noop,
|
||||
afterBuildTicks: function() {
|
||||
helpers.callCallback(this.options.afterBuildTicks, [this]);
|
||||
},
|
||||
|
||||
beforeTickToLabelConversion: function() {
|
||||
helpers.callCallback(this.options.beforeTickToLabelConversion, [this]);
|
||||
},
|
||||
convertTicksToLabels: function() {
|
||||
// Convert ticks to strings
|
||||
this.ticks = this.ticks.map(function(numericalTick, index, ticks) {
|
||||
if (this.options.ticks.userCallback) {
|
||||
return this.options.ticks.userCallback(numericalTick, index, ticks);
|
||||
}
|
||||
return this.options.ticks.callback(numericalTick, index, ticks);
|
||||
},
|
||||
this);
|
||||
},
|
||||
afterTickToLabelConversion: function() {
|
||||
helpers.callCallback(this.options.afterTickToLabelConversion, [this]);
|
||||
},
|
||||
|
||||
//
|
||||
|
||||
beforeCalculateTickRotation: function() {
|
||||
helpers.callCallback(this.options.beforeCalculateTickRotation, [this]);
|
||||
},
|
||||
calculateTickRotation: function() {
|
||||
//Get the width of each grid by calculating the difference
|
||||
//between x offsets between 0 and 1.
|
||||
var tickFontSize = helpers.getValueOrDefault(this.options.ticks.fontSize, Chart.defaults.global.defaultFontSize);
|
||||
var tickFontStyle = helpers.getValueOrDefault(this.options.ticks.fontStyle, Chart.defaults.global.defaultFontStyle);
|
||||
var tickFontFamily = helpers.getValueOrDefault(this.options.ticks.fontFamily, Chart.defaults.global.defaultFontFamily);
|
||||
var tickLabelFont = helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily);
|
||||
this.ctx.font = tickLabelFont;
|
||||
|
||||
var firstWidth = this.ctx.measureText(this.ticks[0]).width;
|
||||
var lastWidth = this.ctx.measureText(this.ticks[this.ticks.length - 1]).width;
|
||||
var firstRotated;
|
||||
|
||||
this.labelRotation = 0;
|
||||
this.paddingRight = 0;
|
||||
this.paddingLeft = 0;
|
||||
|
||||
if (this.options.display) {
|
||||
if (this.isHorizontal()) {
|
||||
this.paddingRight = lastWidth / 2 + 3;
|
||||
this.paddingLeft = firstWidth / 2 + 3;
|
||||
|
||||
if (!this.longestTextCache) {
|
||||
this.longestTextCache = {};
|
||||
}
|
||||
var originalLabelWidth = helpers.longestText(this.ctx, tickLabelFont, this.ticks, this.longestTextCache);
|
||||
var labelWidth = originalLabelWidth;
|
||||
var cosRotation;
|
||||
var sinRotation;
|
||||
|
||||
// Allow 3 pixels x2 padding either side for label readability
|
||||
// only the index matters for a dataset scale, but we want a consistent interface between scales
|
||||
var tickWidth = this.getPixelForTick(1) - this.getPixelForTick(0) - 6;
|
||||
|
||||
//Max label rotation can be set or default to 90 - also act as a loop counter
|
||||
while (labelWidth > tickWidth && this.labelRotation < this.options.ticks.maxRotation) {
|
||||
cosRotation = Math.cos(helpers.toRadians(this.labelRotation));
|
||||
sinRotation = Math.sin(helpers.toRadians(this.labelRotation));
|
||||
|
||||
firstRotated = cosRotation * firstWidth;
|
||||
|
||||
// We're right aligning the text now.
|
||||
if (firstRotated + tickFontSize / 2 > this.yLabelWidth) {
|
||||
this.paddingLeft = firstRotated + tickFontSize / 2;
|
||||
}
|
||||
|
||||
this.paddingRight = tickFontSize / 2;
|
||||
|
||||
if (sinRotation * originalLabelWidth > this.maxHeight) {
|
||||
// go back one step
|
||||
this.labelRotation--;
|
||||
break;
|
||||
}
|
||||
|
||||
this.labelRotation++;
|
||||
labelWidth = cosRotation * originalLabelWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.margins) {
|
||||
this.paddingLeft = Math.max(this.paddingLeft - this.margins.left, 0);
|
||||
this.paddingRight = Math.max(this.paddingRight - this.margins.right, 0);
|
||||
}
|
||||
},
|
||||
afterCalculateTickRotation: function() {
|
||||
helpers.callCallback(this.options.afterCalculateTickRotation, [this]);
|
||||
},
|
||||
|
||||
//
|
||||
|
||||
beforeFit: function() {
|
||||
helpers.callCallback(this.options.beforeFit, [this]);
|
||||
},
|
||||
fit: function() {
|
||||
|
||||
this.minSize = {
|
||||
width: 0,
|
||||
height: 0
|
||||
};
|
||||
|
||||
var tickFontSize = helpers.getValueOrDefault(this.options.ticks.fontSize, Chart.defaults.global.defaultFontSize);
|
||||
var tickFontStyle = helpers.getValueOrDefault(this.options.ticks.fontStyle, Chart.defaults.global.defaultFontStyle);
|
||||
var tickFontFamily = helpers.getValueOrDefault(this.options.ticks.fontFamily, Chart.defaults.global.defaultFontFamily);
|
||||
var tickLabelFont = helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily);
|
||||
|
||||
var scaleLabelFontSize = helpers.getValueOrDefault(this.options.scaleLabel.fontSize, Chart.defaults.global.defaultFontSize);
|
||||
var scaleLabelFontStyle = helpers.getValueOrDefault(this.options.scaleLabel.fontStyle, Chart.defaults.global.defaultFontStyle);
|
||||
var scaleLabelFontFamily = helpers.getValueOrDefault(this.options.scaleLabel.fontFamily, Chart.defaults.global.defaultFontFamily);
|
||||
var scaleLabelFont = helpers.fontString(scaleLabelFontSize, scaleLabelFontStyle, scaleLabelFontFamily);
|
||||
|
||||
// Width
|
||||
if (this.isHorizontal()) {
|
||||
// subtract the margins to line up with the chartArea if we are a full width scale
|
||||
this.minSize.width = this.isFullWidth() ? this.maxWidth - this.margins.left - this.margins.right : this.maxWidth;
|
||||
} else {
|
||||
this.minSize.width = this.options.gridLines.display && this.options.display ? 10 : 0;
|
||||
}
|
||||
|
||||
// height
|
||||
if (this.isHorizontal()) {
|
||||
this.minSize.height = this.options.gridLines.display && this.options.display ? 10 : 0;
|
||||
} else {
|
||||
this.minSize.height = this.maxHeight; // fill all the height
|
||||
}
|
||||
|
||||
// Are we showing a title for the scale?
|
||||
if (this.options.scaleLabel.display) {
|
||||
if (this.isHorizontal()) {
|
||||
this.minSize.height += (scaleLabelFontSize * 1.5);
|
||||
} else {
|
||||
this.minSize.width += (scaleLabelFontSize * 1.5);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.options.ticks.display && this.options.display) {
|
||||
// Don't bother fitting the ticks if we are not showing them
|
||||
if (!this.longestTextCache) {
|
||||
this.longestTextCache = {};
|
||||
}
|
||||
|
||||
var largestTextWidth = helpers.longestText(this.ctx, tickLabelFont, this.ticks, this.longestTextCache);
|
||||
|
||||
if (this.isHorizontal()) {
|
||||
// A horizontal axis is more constrained by the height.
|
||||
this.longestLabelWidth = largestTextWidth;
|
||||
|
||||
// TODO - improve this calculation
|
||||
var labelHeight = (Math.sin(helpers.toRadians(this.labelRotation)) * this.longestLabelWidth) + 1.5 * tickFontSize;
|
||||
|
||||
this.minSize.height = Math.min(this.maxHeight, this.minSize.height + labelHeight);
|
||||
this.ctx.font = tickLabelFont;
|
||||
|
||||
var firstLabelWidth = this.ctx.measureText(this.ticks[0]).width;
|
||||
var lastLabelWidth = this.ctx.measureText(this.ticks[this.ticks.length - 1]).width;
|
||||
|
||||
// Ensure that our ticks are always inside the canvas. When rotated, ticks are right aligned which means that the right padding is dominated
|
||||
// by the font height
|
||||
var cosRotation = Math.cos(helpers.toRadians(this.labelRotation));
|
||||
var sinRotation = Math.sin(helpers.toRadians(this.labelRotation));
|
||||
this.paddingLeft = this.labelRotation !== 0 ? (cosRotation * firstLabelWidth) + 3 : firstLabelWidth / 2 + 3; // add 3 px to move away from canvas edges
|
||||
this.paddingRight = this.labelRotation !== 0 ? (sinRotation * (tickFontSize / 2)) + 3 : lastLabelWidth / 2 + 3; // when rotated
|
||||
} else {
|
||||
// A vertical axis is more constrained by the width. Labels are the dominant factor here, so get that length first
|
||||
var maxLabelWidth = this.maxWidth - this.minSize.width;
|
||||
|
||||
// Account for padding
|
||||
if (!this.options.ticks.mirror) {
|
||||
largestTextWidth += this.options.ticks.padding;
|
||||
}
|
||||
|
||||
if (largestTextWidth < maxLabelWidth) {
|
||||
// We don't need all the room
|
||||
this.minSize.width += largestTextWidth;
|
||||
} else {
|
||||
// Expand to max size
|
||||
this.minSize.width = this.maxWidth;
|
||||
}
|
||||
|
||||
this.paddingTop = tickFontSize / 2;
|
||||
this.paddingBottom = tickFontSize / 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.margins) {
|
||||
this.paddingLeft = Math.max(this.paddingLeft - this.margins.left, 0);
|
||||
this.paddingTop = Math.max(this.paddingTop - this.margins.top, 0);
|
||||
this.paddingRight = Math.max(this.paddingRight - this.margins.right, 0);
|
||||
this.paddingBottom = Math.max(this.paddingBottom - this.margins.bottom, 0);
|
||||
}
|
||||
|
||||
this.width = this.minSize.width;
|
||||
this.height = this.minSize.height;
|
||||
|
||||
},
|
||||
afterFit: function() {
|
||||
helpers.callCallback(this.options.afterFit, [this]);
|
||||
},
|
||||
|
||||
// Shared Methods
|
||||
isHorizontal: function() {
|
||||
return this.options.position === "top" || this.options.position === "bottom";
|
||||
},
|
||||
isFullWidth: function() {
|
||||
return (this.options.fullWidth);
|
||||
},
|
||||
|
||||
// Get the correct value. NaN bad inputs, If the value type is object get the x or y based on whether we are horizontal or not
|
||||
getRightValue: function getRightValue(rawValue) {
|
||||
// Null and undefined values first
|
||||
if (rawValue === null || typeof(rawValue) === 'undefined') {
|
||||
return NaN;
|
||||
}
|
||||
// isNaN(object) returns true, so make sure NaN is checking for a number
|
||||
if (typeof(rawValue) === 'number' && isNaN(rawValue)) {
|
||||
return NaN;
|
||||
}
|
||||
// If it is in fact an object, dive in one more level
|
||||
if (typeof(rawValue) === "object") {
|
||||
if (rawValue instanceof Date) {
|
||||
return rawValue;
|
||||
} else {
|
||||
return getRightValue(this.isHorizontal() ? rawValue.x : rawValue.y);
|
||||
}
|
||||
}
|
||||
|
||||
// Value is good, return it
|
||||
return rawValue;
|
||||
},
|
||||
|
||||
// Used to get the value to display in the tooltip for the data at the given index
|
||||
// function getLabelForIndex(index, datasetIndex)
|
||||
getLabelForIndex: helpers.noop,
|
||||
|
||||
// Used to get data value locations. Value can either be an index or a numerical value
|
||||
getPixelForValue: helpers.noop,
|
||||
|
||||
// Used for tick location, should
|
||||
getPixelForTick: function(index, includeOffset) {
|
||||
if (this.isHorizontal()) {
|
||||
var innerWidth = this.width - (this.paddingLeft + this.paddingRight);
|
||||
var tickWidth = innerWidth / Math.max((this.ticks.length - ((this.options.gridLines.offsetGridLines) ? 0 : 1)), 1);
|
||||
var pixel = (tickWidth * index) + this.paddingLeft;
|
||||
|
||||
if (includeOffset) {
|
||||
pixel += tickWidth / 2;
|
||||
}
|
||||
|
||||
var finalVal = this.left + Math.round(pixel);
|
||||
finalVal += this.isFullWidth() ? this.margins.left : 0;
|
||||
return finalVal;
|
||||
} else {
|
||||
var innerHeight = this.height - (this.paddingTop + this.paddingBottom);
|
||||
return this.top + (index * (innerHeight / (this.ticks.length - 1)));
|
||||
}
|
||||
},
|
||||
|
||||
// Utility for getting the pixel location of a percentage of scale
|
||||
getPixelForDecimal: function(decimal /*, includeOffset*/ ) {
|
||||
if (this.isHorizontal()) {
|
||||
var innerWidth = this.width - (this.paddingLeft + this.paddingRight);
|
||||
var valueOffset = (innerWidth * decimal) + this.paddingLeft;
|
||||
|
||||
var finalVal = this.left + Math.round(valueOffset);
|
||||
finalVal += this.isFullWidth() ? this.margins.left : 0;
|
||||
return finalVal;
|
||||
} else {
|
||||
return this.top + (decimal * this.height);
|
||||
}
|
||||
},
|
||||
|
||||
// Actualy draw the scale on the canvas
|
||||
// @param {rectangle} chartArea : the area of the chart to draw full grid lines on
|
||||
draw: function(chartArea) {
|
||||
if (this.options.display) {
|
||||
|
||||
var setContextLineSettings;
|
||||
var isRotated = this.labelRotation !== 0;
|
||||
var skipRatio;
|
||||
var scaleLabelX;
|
||||
var scaleLabelY;
|
||||
var useAutoskipper = this.options.ticks.autoSkip;
|
||||
|
||||
|
||||
// figure out the maximum number of gridlines to show
|
||||
var maxTicks;
|
||||
|
||||
if (this.options.ticks.maxTicksLimit) {
|
||||
maxTicks = this.options.ticks.maxTicksLimit;
|
||||
}
|
||||
|
||||
var tickFontColor = helpers.getValueOrDefault(this.options.ticks.fontColor, Chart.defaults.global.defaultFontColor);
|
||||
var tickFontSize = helpers.getValueOrDefault(this.options.ticks.fontSize, Chart.defaults.global.defaultFontSize);
|
||||
var tickFontStyle = helpers.getValueOrDefault(this.options.ticks.fontStyle, Chart.defaults.global.defaultFontStyle);
|
||||
var tickFontFamily = helpers.getValueOrDefault(this.options.ticks.fontFamily, Chart.defaults.global.defaultFontFamily);
|
||||
var tickLabelFont = helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily);
|
||||
|
||||
var scaleLabelFontColor = helpers.getValueOrDefault(this.options.scaleLabel.fontColor, Chart.defaults.global.defaultFontColor);
|
||||
var scaleLabelFontSize = helpers.getValueOrDefault(this.options.scaleLabel.fontSize, Chart.defaults.global.defaultFontSize);
|
||||
var scaleLabelFontStyle = helpers.getValueOrDefault(this.options.scaleLabel.fontStyle, Chart.defaults.global.defaultFontStyle);
|
||||
var scaleLabelFontFamily = helpers.getValueOrDefault(this.options.scaleLabel.fontFamily, Chart.defaults.global.defaultFontFamily);
|
||||
var scaleLabelFont = helpers.fontString(scaleLabelFontSize, scaleLabelFontStyle, scaleLabelFontFamily);
|
||||
|
||||
var cosRotation = Math.cos(helpers.toRadians(this.labelRotation));
|
||||
var sinRotation = Math.sin(helpers.toRadians(this.labelRotation));
|
||||
var longestRotatedLabel = this.longestLabelWidth * cosRotation;
|
||||
var rotatedLabelHeight = tickFontSize * sinRotation;
|
||||
|
||||
// Make sure we draw text in the correct color and font
|
||||
this.ctx.fillStyle = tickFontColor;
|
||||
|
||||
if (this.isHorizontal()) {
|
||||
setContextLineSettings = true;
|
||||
var yTickStart = this.options.position === "bottom" ? this.top : this.bottom - 10;
|
||||
var yTickEnd = this.options.position === "bottom" ? this.top + 10 : this.bottom;
|
||||
skipRatio = false;
|
||||
|
||||
if (((longestRotatedLabel / 2) + this.options.ticks.autoSkipPadding) * this.ticks.length > (this.width - (this.paddingLeft + this.paddingRight))) {
|
||||
skipRatio = 1 + Math.floor((((longestRotatedLabel / 2) + this.options.ticks.autoSkipPadding) * this.ticks.length) / (this.width - (this.paddingLeft + this.paddingRight)));
|
||||
}
|
||||
|
||||
// if they defined a max number of ticks,
|
||||
// increase skipRatio until that number is met
|
||||
if (maxTicks && this.ticks.length > maxTicks) {
|
||||
while (!skipRatio || this.ticks.length / (skipRatio || 1) > maxTicks) {
|
||||
if (!skipRatio) {
|
||||
skipRatio = 1;
|
||||
}
|
||||
skipRatio += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!useAutoskipper) {
|
||||
skipRatio = false;
|
||||
}
|
||||
|
||||
helpers.each(this.ticks, function(label, index) {
|
||||
// Blank ticks
|
||||
var isLastTick = this.ticks.length === index + 1;
|
||||
|
||||
// Since we always show the last tick,we need may need to hide the last shown one before
|
||||
var shouldSkip = (skipRatio > 1 && index % skipRatio > 0) || (index % skipRatio === 0 && index + skipRatio > this.ticks.length);
|
||||
if (shouldSkip && !isLastTick || (label === undefined || label === null)) {
|
||||
return;
|
||||
}
|
||||
var xLineValue = this.getPixelForTick(index); // xvalues for grid lines
|
||||
var xLabelValue = this.getPixelForTick(index, this.options.gridLines.offsetGridLines); // x values for ticks (need to consider offsetLabel option)
|
||||
|
||||
if (this.options.gridLines.display) {
|
||||
if (index === (typeof this.zeroLineIndex !== 'undefined' ? this.zeroLineIndex : 0)) {
|
||||
// Draw the first index specially
|
||||
this.ctx.lineWidth = this.options.gridLines.zeroLineWidth;
|
||||
this.ctx.strokeStyle = this.options.gridLines.zeroLineColor;
|
||||
setContextLineSettings = true; // reset next time
|
||||
} else if (setContextLineSettings) {
|
||||
this.ctx.lineWidth = this.options.gridLines.lineWidth;
|
||||
this.ctx.strokeStyle = this.options.gridLines.color;
|
||||
setContextLineSettings = false;
|
||||
}
|
||||
|
||||
xLineValue += helpers.aliasPixel(this.ctx.lineWidth);
|
||||
|
||||
// Draw the label area
|
||||
this.ctx.beginPath();
|
||||
|
||||
if (this.options.gridLines.drawTicks) {
|
||||
this.ctx.moveTo(xLineValue, yTickStart);
|
||||
this.ctx.lineTo(xLineValue, yTickEnd);
|
||||
}
|
||||
|
||||
// Draw the chart area
|
||||
if (this.options.gridLines.drawOnChartArea) {
|
||||
this.ctx.moveTo(xLineValue, chartArea.top);
|
||||
this.ctx.lineTo(xLineValue, chartArea.bottom);
|
||||
}
|
||||
|
||||
// Need to stroke in the loop because we are potentially changing line widths & colours
|
||||
this.ctx.stroke();
|
||||
}
|
||||
|
||||
if (this.options.ticks.display) {
|
||||
this.ctx.save();
|
||||
this.ctx.translate(xLabelValue, (isRotated) ? this.top + 12 : this.options.position === "top" ? this.bottom - 10 : this.top + 10);
|
||||
this.ctx.rotate(helpers.toRadians(this.labelRotation) * -1);
|
||||
this.ctx.font = tickLabelFont;
|
||||
this.ctx.textAlign = (isRotated) ? "right" : "center";
|
||||
this.ctx.textBaseline = (isRotated) ? "middle" : this.options.position === "top" ? "bottom" : "top";
|
||||
this.ctx.fillText(label, 0, 0);
|
||||
this.ctx.restore();
|
||||
}
|
||||
}, this);
|
||||
|
||||
if (this.options.scaleLabel.display) {
|
||||
// Draw the scale label
|
||||
this.ctx.textAlign = "center";
|
||||
this.ctx.textBaseline = 'middle';
|
||||
this.ctx.fillStyle = scaleLabelFontColor; // render in correct colour
|
||||
this.ctx.font = scaleLabelFont;
|
||||
|
||||
scaleLabelX = this.left + ((this.right - this.left) / 2); // midpoint of the width
|
||||
scaleLabelY = this.options.position === 'bottom' ? this.bottom - (scaleLabelFontSize / 2) : this.top + (scaleLabelFontSize / 2);
|
||||
|
||||
this.ctx.fillText(this.options.scaleLabel.labelString, scaleLabelX, scaleLabelY);
|
||||
}
|
||||
|
||||
} else {
|
||||
setContextLineSettings = true;
|
||||
var xTickStart = this.options.position === "right" ? this.left : this.right - 5;
|
||||
var xTickEnd = this.options.position === "right" ? this.left + 5 : this.right;
|
||||
|
||||
helpers.each(this.ticks, function(label, index) {
|
||||
// If the callback returned a null or undefined value, do not draw this line
|
||||
if (label === undefined || label === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var yLineValue = this.getPixelForTick(index); // xvalues for grid lines
|
||||
|
||||
if (this.options.gridLines.display) {
|
||||
if (index === (typeof this.zeroLineIndex !== 'undefined' ? this.zeroLineIndex : 0)) {
|
||||
// Draw the first index specially
|
||||
this.ctx.lineWidth = this.options.gridLines.zeroLineWidth;
|
||||
this.ctx.strokeStyle = this.options.gridLines.zeroLineColor;
|
||||
setContextLineSettings = true; // reset next time
|
||||
} else if (setContextLineSettings) {
|
||||
this.ctx.lineWidth = this.options.gridLines.lineWidth;
|
||||
this.ctx.strokeStyle = this.options.gridLines.color;
|
||||
setContextLineSettings = false;
|
||||
}
|
||||
|
||||
yLineValue += helpers.aliasPixel(this.ctx.lineWidth);
|
||||
|
||||
// Draw the label area
|
||||
this.ctx.beginPath();
|
||||
|
||||
if (this.options.gridLines.drawTicks) {
|
||||
this.ctx.moveTo(xTickStart, yLineValue);
|
||||
this.ctx.lineTo(xTickEnd, yLineValue);
|
||||
}
|
||||
|
||||
// Draw the chart area
|
||||
if (this.options.gridLines.drawOnChartArea) {
|
||||
this.ctx.moveTo(chartArea.left, yLineValue);
|
||||
this.ctx.lineTo(chartArea.right, yLineValue);
|
||||
}
|
||||
|
||||
// Need to stroke in the loop because we are potentially changing line widths & colours
|
||||
this.ctx.stroke();
|
||||
}
|
||||
|
||||
if (this.options.ticks.display) {
|
||||
var xLabelValue;
|
||||
var yLabelValue = this.getPixelForTick(index, this.options.gridLines.offsetGridLines); // x values for ticks (need to consider offsetLabel option)
|
||||
|
||||
this.ctx.save();
|
||||
|
||||
if (this.options.position === "left") {
|
||||
if (this.options.ticks.mirror) {
|
||||
xLabelValue = this.right + this.options.ticks.padding;
|
||||
this.ctx.textAlign = "left";
|
||||
} else {
|
||||
xLabelValue = this.right - this.options.ticks.padding;
|
||||
this.ctx.textAlign = "right";
|
||||
}
|
||||
} else {
|
||||
// right side
|
||||
if (this.options.ticks.mirror) {
|
||||
xLabelValue = this.left - this.options.ticks.padding;
|
||||
this.ctx.textAlign = "right";
|
||||
} else {
|
||||
xLabelValue = this.left + this.options.ticks.padding;
|
||||
this.ctx.textAlign = "left";
|
||||
}
|
||||
}
|
||||
|
||||
this.ctx.translate(xLabelValue, yLabelValue);
|
||||
this.ctx.rotate(helpers.toRadians(this.labelRotation) * -1);
|
||||
this.ctx.font = tickLabelFont;
|
||||
this.ctx.textBaseline = "middle";
|
||||
this.ctx.fillText(label, 0, 0);
|
||||
this.ctx.restore();
|
||||
}
|
||||
}, this);
|
||||
|
||||
if (this.options.scaleLabel.display) {
|
||||
// Draw the scale label
|
||||
scaleLabelX = this.options.position === 'left' ? this.left + (scaleLabelFontSize / 2) : this.right - (scaleLabelFontSize / 2);
|
||||
scaleLabelY = this.top + ((this.bottom - this.top) / 2);
|
||||
var rotation = this.options.position === 'left' ? -0.5 * Math.PI : 0.5 * Math.PI;
|
||||
|
||||
this.ctx.save();
|
||||
this.ctx.translate(scaleLabelX, scaleLabelY);
|
||||
this.ctx.rotate(rotation);
|
||||
this.ctx.textAlign = "center";
|
||||
this.ctx.fillStyle =scaleLabelFontColor; // render in correct colour
|
||||
this.ctx.font = scaleLabelFont;
|
||||
this.ctx.textBaseline = 'middle';
|
||||
this.ctx.fillText(this.options.scaleLabel.labelString, 0, 0);
|
||||
this.ctx.restore();
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the line at the edge of the axis
|
||||
this.ctx.lineWidth = this.options.gridLines.lineWidth;
|
||||
this.ctx.strokeStyle = this.options.gridLines.color;
|
||||
var x1 = this.left,
|
||||
x2 = this.right,
|
||||
y1 = this.top,
|
||||
y2 = this.bottom;
|
||||
|
||||
if (this.isHorizontal()) {
|
||||
y1 = y2 = this.options.position === 'top' ? this.bottom : this.top;
|
||||
y1 += helpers.aliasPixel(this.ctx.lineWidth);
|
||||
y2 += helpers.aliasPixel(this.ctx.lineWidth);
|
||||
} else {
|
||||
x1 = x2 = this.options.position === 'left' ? this.right : this.left;
|
||||
x1 += helpers.aliasPixel(this.ctx.lineWidth);
|
||||
x2 += helpers.aliasPixel(this.ctx.lineWidth);
|
||||
}
|
||||
|
||||
this.ctx.beginPath();
|
||||
this.ctx.moveTo(x1, y1);
|
||||
this.ctx.lineTo(x2, y2);
|
||||
this.ctx.stroke();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = function(Chart) {
|
||||
|
||||
var helpers = Chart.helpers;
|
||||
|
||||
Chart.scaleService = {
|
||||
// Scale registration object. Extensions can register new scale types (such as log or DB scales) and then
|
||||
// use the new chart options to grab the correct scale
|
||||
constructors: {},
|
||||
// Use a registration function so that we can move to an ES6 map when we no longer need to support
|
||||
// old browsers
|
||||
|
||||
// Scale config defaults
|
||||
defaults: {},
|
||||
registerScaleType: function(type, scaleConstructor, defaults) {
|
||||
this.constructors[type] = scaleConstructor;
|
||||
this.defaults[type] = helpers.clone(defaults);
|
||||
},
|
||||
getScaleConstructor: function(type) {
|
||||
return this.constructors.hasOwnProperty(type) ? this.constructors[type] : undefined;
|
||||
},
|
||||
getScaleDefaults: function(type) {
|
||||
// Return the scale defaults merged with the global settings so that we always use the latest ones
|
||||
return this.defaults.hasOwnProperty(type) ? helpers.scaleMerge(Chart.defaults.scale, this.defaults[type]) : {};
|
||||
},
|
||||
addScalesToLayout: function(chartInstance) {
|
||||
// Adds each scale to the chart.boxes array to be sized accordingly
|
||||
helpers.each(chartInstance.scales, function(scale) {
|
||||
Chart.layoutService.addBox(chartInstance, scale);
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,193 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = function(Chart) {
|
||||
|
||||
var helpers = Chart.helpers;
|
||||
|
||||
Chart.defaults.global.title = {
|
||||
display: false,
|
||||
position: 'top',
|
||||
fullWidth: true, // marks that this box should take the full width of the canvas (pushing down other boxes)
|
||||
|
||||
fontStyle: 'bold',
|
||||
padding: 10,
|
||||
|
||||
// actual title
|
||||
text: ''
|
||||
};
|
||||
|
||||
Chart.Title = Chart.Element.extend({
|
||||
|
||||
initialize: function(config) {
|
||||
helpers.extend(this, config);
|
||||
this.options = helpers.configMerge(Chart.defaults.global.title, config.options);
|
||||
|
||||
// Contains hit boxes for each dataset (in dataset order)
|
||||
this.legendHitBoxes = [];
|
||||
},
|
||||
|
||||
// These methods are ordered by lifecyle. Utilities then follow.
|
||||
|
||||
beforeUpdate: helpers.noop,
|
||||
update: function(maxWidth, maxHeight, margins) {
|
||||
|
||||
// Update Lifecycle - Probably don't want to ever extend or overwrite this function ;)
|
||||
this.beforeUpdate();
|
||||
|
||||
// Absorb the master measurements
|
||||
this.maxWidth = maxWidth;
|
||||
this.maxHeight = maxHeight;
|
||||
this.margins = margins;
|
||||
|
||||
// Dimensions
|
||||
this.beforeSetDimensions();
|
||||
this.setDimensions();
|
||||
this.afterSetDimensions();
|
||||
// Labels
|
||||
this.beforeBuildLabels();
|
||||
this.buildLabels();
|
||||
this.afterBuildLabels();
|
||||
|
||||
// Fit
|
||||
this.beforeFit();
|
||||
this.fit();
|
||||
this.afterFit();
|
||||
//
|
||||
this.afterUpdate();
|
||||
|
||||
return this.minSize;
|
||||
|
||||
},
|
||||
afterUpdate: helpers.noop,
|
||||
|
||||
//
|
||||
|
||||
beforeSetDimensions: helpers.noop,
|
||||
setDimensions: function() {
|
||||
// Set the unconstrained dimension before label rotation
|
||||
if (this.isHorizontal()) {
|
||||
// Reset position before calculating rotation
|
||||
this.width = this.maxWidth;
|
||||
this.left = 0;
|
||||
this.right = this.width;
|
||||
} else {
|
||||
this.height = this.maxHeight;
|
||||
|
||||
// Reset position before calculating rotation
|
||||
this.top = 0;
|
||||
this.bottom = this.height;
|
||||
}
|
||||
|
||||
// Reset padding
|
||||
this.paddingLeft = 0;
|
||||
this.paddingTop = 0;
|
||||
this.paddingRight = 0;
|
||||
this.paddingBottom = 0;
|
||||
|
||||
// Reset minSize
|
||||
this.minSize = {
|
||||
width: 0,
|
||||
height: 0
|
||||
};
|
||||
},
|
||||
afterSetDimensions: helpers.noop,
|
||||
|
||||
//
|
||||
|
||||
beforeBuildLabels: helpers.noop,
|
||||
buildLabels: helpers.noop,
|
||||
afterBuildLabels: helpers.noop,
|
||||
|
||||
//
|
||||
|
||||
beforeFit: helpers.noop,
|
||||
fit: function() {
|
||||
|
||||
var ctx = this.ctx;
|
||||
var fontSize = helpers.getValueOrDefault(this.options.fontSize, Chart.defaults.global.defaultFontSize);
|
||||
var fontStyle = helpers.getValueOrDefault(this.options.fontStyle, Chart.defaults.global.defaultFontStyle);
|
||||
var fontFamily = helpers.getValueOrDefault(this.options.fontFamily, Chart.defaults.global.defaultFontFamily);
|
||||
var titleFont = helpers.fontString(fontSize, fontStyle, fontFamily);
|
||||
|
||||
// Width
|
||||
if (this.isHorizontal()) {
|
||||
this.minSize.width = this.maxWidth; // fill all the width
|
||||
} else {
|
||||
this.minSize.width = 0;
|
||||
}
|
||||
|
||||
// height
|
||||
if (this.isHorizontal()) {
|
||||
this.minSize.height = 0;
|
||||
} else {
|
||||
this.minSize.height = this.maxHeight; // fill all the height
|
||||
}
|
||||
|
||||
// Increase sizes here
|
||||
if (this.isHorizontal()) {
|
||||
|
||||
// Title
|
||||
if (this.options.display) {
|
||||
this.minSize.height += fontSize + (this.options.padding * 2);
|
||||
}
|
||||
} else {
|
||||
if (this.options.display) {
|
||||
this.minSize.width += fontSize + (this.options.padding * 2);
|
||||
}
|
||||
}
|
||||
|
||||
this.width = this.minSize.width;
|
||||
this.height = this.minSize.height;
|
||||
|
||||
},
|
||||
afterFit: helpers.noop,
|
||||
|
||||
// Shared Methods
|
||||
isHorizontal: function() {
|
||||
return this.options.position === "top" || this.options.position === "bottom";
|
||||
},
|
||||
|
||||
// Actualy draw the title block on the canvas
|
||||
draw: function() {
|
||||
if (this.options.display) {
|
||||
var ctx = this.ctx;
|
||||
var titleX, titleY;
|
||||
|
||||
var fontColor = helpers.getValueOrDefault(this.options.fontColor, Chart.defaults.global.defaultFontColor);
|
||||
var fontSize = helpers.getValueOrDefault(this.options.fontSize, Chart.defaults.global.defaultFontSize);
|
||||
var fontStyle = helpers.getValueOrDefault(this.options.fontStyle, Chart.defaults.global.defaultFontStyle);
|
||||
var fontFamily = helpers.getValueOrDefault(this.options.fontFamily, Chart.defaults.global.defaultFontFamily);
|
||||
var titleFont = helpers.fontString(fontSize, fontStyle, fontFamily);
|
||||
|
||||
ctx.fillStyle = fontColor; // render in correct colour
|
||||
ctx.font = titleFont;
|
||||
|
||||
// Horizontal
|
||||
if (this.isHorizontal()) {
|
||||
// Title
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = 'middle';
|
||||
|
||||
titleX = this.left + ((this.right - this.left) / 2); // midpoint of the width
|
||||
titleY = this.top + ((this.bottom - this.top) / 2); // midpoint of the height
|
||||
|
||||
ctx.fillText(this.options.text, titleX, titleY);
|
||||
} else {
|
||||
|
||||
// Title
|
||||
titleX = this.options.position === 'left' ? this.left + (fontSize / 2) : this.right - (fontSize / 2);
|
||||
titleY = this.top + ((this.bottom - this.top) / 2);
|
||||
var rotation = this.options.position === 'left' ? -0.5 * Math.PI : 0.5 * Math.PI;
|
||||
|
||||
ctx.save();
|
||||
ctx.translate(titleX, titleY);
|
||||
ctx.rotate(rotation);
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = 'middle';
|
||||
ctx.fillText(this.options.text, 0, 0);
|
||||
ctx.restore();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
Alguns arquivos não foram exibidos porque demasiados arquivos foram alterados neste diff Mostrar Mais
Referência em uma Nova Issue
Bloquear um usuário