Compare commits
619 Commits
v13.0.0-58
...
v13.5.14
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
491cd422c4 | ||
|
|
4b88e2aac5 | ||
|
|
e33c67fc72 | ||
|
|
085dda4cbd | ||
|
|
f382846874 | ||
|
|
9afc5cf615 | ||
|
|
ca0fb4b15d | ||
|
|
d369a771a9 | ||
|
|
995fbfa4cc | ||
|
|
7486ea7148 | ||
|
|
2c80a955da | ||
|
|
233872493b | ||
|
|
64d164a904 | ||
|
|
a08e54c2fc | ||
|
|
2b377cd46d | ||
|
|
b4b8927550 | ||
|
|
b2761b50f2 | ||
|
|
28a9ce962d | ||
|
|
0ec67170d3 | ||
|
|
df9bfbe778 | ||
|
|
f1ab417570 | ||
|
|
4922eeac56 | ||
|
|
57d6c6f831 | ||
|
|
371f2b6d55 | ||
|
|
85a7ad148f | ||
|
|
7ec1b3a19e | ||
|
|
633eb9033c | ||
|
|
4707fc46ac | ||
|
|
89b4320a8e | ||
|
|
0ea0a35521 | ||
|
|
15ea4ee805 | ||
|
|
744469d363 | ||
|
|
311dd50f1b | ||
|
|
89c5541ee6 | ||
|
|
28d8db86f0 | ||
|
|
0c34216ed0 | ||
|
|
9aa518bc14 | ||
|
|
27b1190a28 | ||
|
|
f3d8db491b | ||
|
|
e9905602f8 | ||
|
|
2b8154fa16 | ||
|
|
5ddb7eefed | ||
|
|
4b35de5ad5 | ||
|
|
097b9e8208 | ||
|
|
5cac153a17 | ||
|
|
a7e4724edd | ||
|
|
71d8da6513 | ||
|
|
c72ac448e9 | ||
|
|
da21fca334 | ||
|
|
d80512d690 | ||
|
|
6886881b76 | ||
|
|
dc9717ecd0 | ||
|
|
7bd764fba7 | ||
|
|
4047890a6e | ||
|
|
1627e7b3f6 | ||
|
|
e55d3cc510 | ||
|
|
55bd0b16f7 | ||
|
|
ab7de51064 | ||
|
|
d4917bb567 | ||
|
|
4e343ccace | ||
|
|
4efd47447b | ||
|
|
5aa1aaebb3 | ||
|
|
7656f897d6 | ||
|
|
5244755879 | ||
|
|
3a7a324a24 | ||
|
|
9e98fec504 | ||
|
|
b1c7022890 | ||
|
|
c67428d715 | ||
|
|
45a9af96af | ||
|
|
249c4f9c45 | ||
|
|
cdc7d3ffe6 | ||
|
|
ac6a0e7667 | ||
|
|
12881e2be7 | ||
|
|
77958da657 | ||
|
|
8a8a60efde | ||
|
|
7a1d648e79 | ||
|
|
3af420e790 | ||
|
|
4f2d13e3ce | ||
|
|
e0b76cd2f4 | ||
|
|
d812636c5b | ||
|
|
21fee0fe96 | ||
|
|
fab14a09de | ||
|
|
710b4ba145 | ||
|
|
34091ae614 | ||
|
|
feb8ec1afc | ||
|
|
ce9139c9f4 | ||
|
|
e2e5d0870c | ||
|
|
04cff60931 | ||
|
|
5dfe4e8af2 | ||
|
|
05ca0b0208 | ||
|
|
ee7c189fdc | ||
|
|
01c08ef202 | ||
|
|
894c0d7731 | ||
|
|
fdf632f03e | ||
|
|
ce80cb4a0d | ||
|
|
ae3c4cc050 | ||
|
|
27a78047c5 | ||
|
|
7a128c271b | ||
|
|
263cc0856e | ||
|
|
2199ac3e4e | ||
|
|
275d52b19d | ||
|
|
7edbb2485f | ||
|
|
304812fb07 | ||
|
|
baca852733 | ||
|
|
7cbf204143 | ||
|
|
c8a59118b5 | ||
|
|
bee397f1e5 | ||
|
|
1e97cf8323 | ||
|
|
c28ad0608e | ||
|
|
e19f16f22c | ||
|
|
6f074a873d | ||
|
|
4af04d6a29 | ||
|
|
97d9714710 | ||
|
|
ca667be68b | ||
|
|
8086a4f816 | ||
|
|
186f7140b6 | ||
|
|
edc1f9418f | ||
|
|
32b734b24d | ||
|
|
656328631c | ||
|
|
dbd1b3cb59 | ||
|
|
8fadec4dcd | ||
|
|
8013b4ef5c | ||
|
|
0a40b541e8 | ||
|
|
728bb6f1b2 | ||
|
|
fd59696b9a | ||
|
|
bfacd2e63a | ||
|
|
6bc9c220b9 | ||
|
|
7c0b98bbb2 | ||
|
|
034463798d | ||
|
|
4c929c6808 | ||
|
|
0fc213e92e | ||
|
|
bbc688975d | ||
|
|
ab9373c188 | ||
|
|
af576788f1 | ||
|
|
fbbf085278 | ||
|
|
d8868c47e1 | ||
|
|
47221c26c4 | ||
|
|
ba83398374 | ||
|
|
0b23d5aeeb | ||
|
|
072947c0bb | ||
|
|
22aef63d8a | ||
|
|
f8341220c3 | ||
|
|
50e5964fcb | ||
|
|
004a781a56 | ||
|
|
31dee48f63 | ||
|
|
c8534ea6bc | ||
|
|
1e0fd60df4 | ||
|
|
3404d22d12 | ||
|
|
d3b56702ad | ||
|
|
d5e6c26420 | ||
|
|
e497f07f7a | ||
|
|
510354d99f | ||
|
|
c3342d0b34 | ||
|
|
45af21f31e | ||
|
|
320da29b69 | ||
|
|
783c4d8209 | ||
|
|
2c708b647d | ||
|
|
7a45be8c88 | ||
|
|
972d15dda5 | ||
|
|
fdf2063943 | ||
|
|
e81267d4df | ||
|
|
563c34f81a | ||
|
|
ba713983e3 | ||
|
|
bf2ee3680b | ||
|
|
b812a3dd6c | ||
|
|
b3f5b50377 | ||
|
|
7bcd4a828d | ||
|
|
cb705922b4 | ||
|
|
1ed58909d3 | ||
|
|
0aca7bbefa | ||
|
|
e1f0324840 | ||
|
|
7bac783490 | ||
|
|
1508c44f68 | ||
|
|
3dd843372f | ||
|
|
d6be4d9391 | ||
|
|
53f2344017 | ||
|
|
86f7631d1e | ||
|
|
3bb107504f | ||
|
|
4c46ebfb45 | ||
|
|
9d0d63ead7 | ||
|
|
39803c1d11 | ||
|
|
46fae57036 | ||
|
|
e9cb07da55 | ||
|
|
114f28f48e | ||
|
|
a1da486c8a | ||
|
|
4fb9cc2a30 | ||
|
|
e2c9eb7f01 | ||
|
|
6fd33c0720 | ||
|
|
72f3ce75b2 | ||
|
|
fd211731cc | ||
|
|
8049776074 | ||
|
|
32b1338d48 | ||
|
|
c2f0ca3fae | ||
|
|
dfc6b879de | ||
|
|
81f16ff0b5 | ||
|
|
e1a2ccd7f6 | ||
|
|
be8cc8a20c | ||
|
|
a253cfc090 | ||
|
|
992c0b5e32 | ||
|
|
e17d661769 | ||
|
|
fef3fc2a4a | ||
|
|
eee695eeeb | ||
|
|
38e38a92dc | ||
|
|
dadc08597d | ||
|
|
e769a2a354 | ||
|
|
0dd0a4be14 | ||
|
|
7193ae63b7 | ||
|
|
4d48224518 | ||
|
|
b4fc073aa5 | ||
|
|
9c0d1eb209 | ||
|
|
6a9f853d12 | ||
|
|
ce3b0f3043 | ||
|
|
94646b2f45 | ||
|
|
29c2ad4492 | ||
|
|
637fadf38e | ||
|
|
0c6c11d583 | ||
|
|
6f9a2c9df7 | ||
|
|
7876a96163 | ||
|
|
ceba4b1837 | ||
|
|
22653c799c | ||
|
|
68109b033f | ||
|
|
38eb2e502c | ||
|
|
270a69fcf6 | ||
|
|
6e3b708599 | ||
|
|
6e8167fe51 | ||
|
|
3449687280 | ||
|
|
3406247a3e | ||
|
|
076d550dfa | ||
|
|
bb45816f05 | ||
|
|
5414ac7f6e | ||
|
|
0b8f032364 | ||
|
|
dc136ff56a | ||
|
|
b73a720fdc | ||
|
|
cf420d6241 | ||
|
|
859e169c91 | ||
|
|
6c2cf0f769 | ||
|
|
1a942aa4e0 | ||
|
|
368dc6b36a | ||
|
|
2151c514e5 | ||
|
|
bb25ce7731 | ||
|
|
e31e968f0d | ||
|
|
1a494761a3 | ||
|
|
b434501d11 | ||
|
|
d1d86277b8 | ||
|
|
d7a11ccf4d | ||
|
|
4c48116947 | ||
|
|
6dd26d3b48 | ||
|
|
6b0154f046 | ||
|
|
7fb63de8fc | ||
|
|
c4d80d133d | ||
|
|
cebe96c001 | ||
|
|
4d2369ce21 | ||
|
|
5293ab4df1 | ||
|
|
e53c01c6c5 | ||
|
|
03faa27787 | ||
|
|
868dd5f0a5 | ||
|
|
fa58ce53cd | ||
|
|
0a0098fdfb | ||
|
|
a5a48d07f6 | ||
|
|
7b16d5c92d | ||
|
|
ee147c14f1 | ||
|
|
e86d5ba25b | ||
|
|
149ca6f636 | ||
|
|
e4223760b0 | ||
|
|
9d3dd4e082 | ||
|
|
5a4ff33bf4 | ||
|
|
a059fa12e9 | ||
|
|
0628d8f1c9 | ||
|
|
19e2d51190 | ||
|
|
60fab42b3f | ||
|
|
469404c6e1 | ||
|
|
c9756e5b57 | ||
|
|
601d24e930 | ||
|
|
b2c16674f2 | ||
|
|
13da804b5e | ||
|
|
c5ca7b6f8c | ||
|
|
f4b68c0dd4 | ||
|
|
4407f70052 | ||
|
|
8bb52a485a | ||
|
|
9fc18d5ce0 | ||
|
|
ada4f400b5 | ||
|
|
06048b87ee | ||
|
|
05dde1db01 | ||
|
|
b5b32c5b3c | ||
|
|
3f0e2078de | ||
|
|
21470bb409 | ||
|
|
772bb87d5c | ||
|
|
dab172fa1d | ||
|
|
a70c5112cd | ||
|
|
7cb423c046 | ||
|
|
4547b35641 | ||
|
|
4c87f9a021 | ||
|
|
4b08c67e06 | ||
|
|
9f5bc9ddfe | ||
|
|
8221db795a | ||
|
|
68b4418956 | ||
|
|
fa09ebfd82 | ||
|
|
b399ffa765 | ||
|
|
180f4667c1 | ||
|
|
9455373611 | ||
|
|
aa804d89c0 | ||
|
|
3ef51a5d1a | ||
|
|
e61089c659 | ||
|
|
97625cf29b | ||
|
|
a5dc6c27aa | ||
|
|
26a51bafc9 | ||
|
|
f40e09d156 | ||
|
|
81650bc8f6 | ||
|
|
c87caafeb6 | ||
|
|
195b26d90f | ||
|
|
7e0189ca84 | ||
|
|
192706f2a8 | ||
|
|
a4ce8ae07d | ||
|
|
e04a980af1 | ||
|
|
47d40eb6b0 | ||
|
|
fc4a39cc7d | ||
|
|
44e1fd9f14 | ||
|
|
02cc5a215f | ||
|
|
d1e8d50c43 | ||
|
|
18bb2d0719 | ||
|
|
45df311dd7 | ||
|
|
62888b4004 | ||
|
|
76c389dba0 | ||
|
|
78fa98c000 | ||
|
|
e9f9e08450 | ||
|
|
e3c59b0aa7 | ||
|
|
705dce7838 | ||
|
|
0fb55981ba | ||
|
|
89378e29ae | ||
|
|
cce35270ec | ||
|
|
d78180bf97 | ||
|
|
0ab415de3e | ||
|
|
ff3969caeb | ||
|
|
c82cc9f8d6 | ||
|
|
ef5c71bd8b | ||
|
|
bd6be3d23b | ||
|
|
0e6deab9c9 | ||
|
|
6cd9e2be32 | ||
|
|
ac8dab1e88 | ||
|
|
38ed725c2c | ||
|
|
a210bad25e | ||
|
|
6929a4f0f8 | ||
|
|
52dacfa5f2 | ||
|
|
27efe86f9c | ||
|
|
882b9055c7 | ||
|
|
e089089413 | ||
|
|
197932752e | ||
|
|
f0b2bdaf34 | ||
|
|
b96362c0f1 | ||
|
|
67f241cd7a | ||
|
|
c8af0bebf7 | ||
|
|
4f35e799a6 | ||
|
|
eb2a52dd26 | ||
|
|
189b1068ae | ||
|
|
7a3b60a5d7 | ||
|
|
99f06fc093 | ||
|
|
22917bca19 | ||
|
|
7f0e25dcba | ||
|
|
d90c9b1cb2 | ||
|
|
c426055f17 | ||
|
|
18c9010b63 | ||
|
|
c3edac62ef | ||
|
|
755de18fd5 | ||
|
|
641dc25076 | ||
|
|
1d58ea785f | ||
|
|
f53dff5043 | ||
|
|
74d1a31f49 | ||
|
|
d1063ab70b | ||
|
|
f4c919d9ec | ||
|
|
aeb23dbaa9 | ||
|
|
6d4f0c0cdd | ||
|
|
303138f309 | ||
|
|
ad373a3dce | ||
|
|
2150fa58f2 | ||
|
|
ece4841b5c | ||
|
|
8103220c05 | ||
|
|
66d500f08d | ||
|
|
5f8e7c7ba7 | ||
|
|
7b8eee6b25 | ||
|
|
1d5947c602 | ||
|
|
53e4028952 | ||
|
|
b38a8d99e5 | ||
|
|
6c4971ae25 | ||
|
|
d1f5ff0f59 | ||
|
|
1d297601e8 | ||
|
|
d9fface0be | ||
|
|
7d5db917da | ||
|
|
6e7529723d | ||
|
|
6cb64b3707 | ||
|
|
bb1c0b809f | ||
|
|
8bcff6138c | ||
|
|
e78d84ee59 | ||
|
|
c23bcb66ce | ||
|
|
5fddcef3ea | ||
|
|
e1e46c6eb1 | ||
|
|
13ad0c8464 | ||
|
|
7700b50470 | ||
|
|
fc4d6165b4 | ||
|
|
251c8aaefc | ||
|
|
1337d38ada | ||
|
|
f5c66e41cb | ||
|
|
0e7da017fe | ||
|
|
f0262ffaae | ||
|
|
36203af88e | ||
|
|
dd2b8bc6c7 | ||
|
|
463065ac21 | ||
|
|
d064e6e96e | ||
|
|
b1ed2df208 | ||
|
|
1fe4ef135c | ||
|
|
e376b5d472 | ||
|
|
952a9b2c41 | ||
|
|
03458dc641 | ||
|
|
14df5b72af | ||
|
|
338968031b | ||
|
|
1aac245b93 | ||
|
|
1faff323c1 | ||
|
|
e7280c7ae2 | ||
|
|
4c38619b5d | ||
|
|
b4e5c5cc1f | ||
|
|
b0dbd84f7f | ||
|
|
4a990963d9 | ||
|
|
7e7c9d5b11 | ||
|
|
775f6eed1d | ||
|
|
1e83b9418c | ||
|
|
ac3f672c80 | ||
|
|
2192aa5821 | ||
|
|
70bb523005 | ||
|
|
10ce6de57a | ||
|
|
3fba4f25a5 | ||
|
|
66c35d8499 | ||
|
|
4c14157dcf | ||
|
|
ef6c382e20 | ||
|
|
ee45b4fdd6 | ||
|
|
668e9e8a9b | ||
|
|
37a6d68543 | ||
|
|
f893198769 | ||
|
|
d3ee1a0ec2 | ||
|
|
d6593412a2 | ||
|
|
d31bf36531 | ||
|
|
a485f550db | ||
|
|
0610b16227 | ||
|
|
72e470c5f0 | ||
|
|
4d12a02e2f | ||
|
|
4a7d6f0a2d | ||
|
|
c80f446b5f | ||
|
|
81a529d8dc | ||
|
|
4f0ab78914 | ||
|
|
8c36f67f0b | ||
|
|
77687d94e6 | ||
|
|
4644511303 | ||
|
|
20005eecdb | ||
|
|
c9dda245bf | ||
|
|
1417470156 | ||
|
|
584e5dfd40 | ||
|
|
805acbb9f5 | ||
|
|
32c4c09072 | ||
|
|
8c5a06bbf8 | ||
|
|
a336cc167c | ||
|
|
21d86cd2be | ||
|
|
1d0f9faa91 | ||
|
|
45237571b7 | ||
|
|
bb6f6cd141 | ||
|
|
729c1f16b8 | ||
|
|
b6059704aa | ||
|
|
fa3c92f44c | ||
|
|
cd82de7742 | ||
|
|
07a6a0044b | ||
|
|
4582832a71 | ||
|
|
07ac1d03e3 | ||
|
|
cbcf1facb8 | ||
|
|
31ff7ac78c | ||
|
|
ed3b31e58f | ||
|
|
759ecb21f7 | ||
|
|
9c29d820c8 | ||
|
|
2ef11a5344 | ||
|
|
9fe47e98d5 | ||
|
|
654510f3ff | ||
|
|
52ec698635 | ||
|
|
1b06f59d1c | ||
|
|
12bcc4d080 | ||
|
|
e1a9f314a7 | ||
|
|
7a111de186 | ||
|
|
90b3fa9dd9 | ||
|
|
c635963747 | ||
|
|
1b17b5e400 | ||
|
|
61d9d96d15 | ||
|
|
7d0c048708 | ||
|
|
8a7416ad50 | ||
|
|
e56899a02c | ||
|
|
30bf3742c9 | ||
|
|
8dbd2c4696 | ||
|
|
6578727c9c | ||
|
|
92ca001cdc | ||
|
|
415de1cc4c | ||
|
|
e23582b1cd | ||
|
|
73c28952c2 | ||
|
|
1bc1e88d6a | ||
|
|
c188f813a4 | ||
|
|
ff981a8697 | ||
|
|
d9ab593b07 | ||
|
|
293527e62b | ||
|
|
5a42a94cf4 | ||
|
|
040808300c | ||
|
|
57975d409e | ||
|
|
306b2c64f3 | ||
|
|
585265e9a5 | ||
|
|
777ae9503a | ||
|
|
4c1798e5fa | ||
|
|
f4d85e2a3e | ||
|
|
a0f0c9c377 | ||
|
|
95ec2a435a | ||
|
|
da9836fe59 | ||
|
|
3a7411f9e8 | ||
|
|
39cee7c6e7 | ||
|
|
0a5753c191 | ||
|
|
76b7d0b651 | ||
|
|
99e3e95a00 | ||
|
|
93ee4ee287 | ||
|
|
c5cc403a29 | ||
|
|
75f4a0a5f0 | ||
|
|
591df5c00a | ||
|
|
f6b4819ae3 | ||
|
|
d483d9cc83 | ||
|
|
453407b93d | ||
|
|
e699f92333 | ||
|
|
6ff47719ef | ||
|
|
3a0694c35c | ||
|
|
74e5243742 | ||
|
|
dcf43b9797 | ||
|
|
77e479c03b | ||
|
|
ec58a99748 | ||
|
|
f1eb66655b | ||
|
|
7f4ae9fe14 | ||
|
|
c0ba56a21f | ||
|
|
4063e28b5e | ||
|
|
b6f7cd7869 | ||
|
|
1a79e429ed | ||
|
|
04066a5678 | ||
|
|
e09ef15349 | ||
|
|
3d70eee959 | ||
|
|
582095e5a3 | ||
|
|
c9ea3a412e | ||
|
|
a2c51c36e9 | ||
|
|
ab3dba5b06 | ||
|
|
3ddff186c2 | ||
|
|
9bd199a6e7 | ||
|
|
01d0825ae6 | ||
|
|
e2f98525d2 | ||
|
|
70a0a03130 | ||
|
|
656d85c62e | ||
|
|
e168dd48fb | ||
|
|
12d43199d5 | ||
|
|
539fa8b21d | ||
|
|
f572f94586 | ||
|
|
c12d00b227 | ||
|
|
e4a5f2caec | ||
|
|
9f9f465238 | ||
|
|
8450ff86d7 | ||
|
|
70139262c5 | ||
|
|
9c0da271eb | ||
|
|
ade3e1949d | ||
|
|
eec63a008f | ||
|
|
52abcdd043 | ||
|
|
f94653424a | ||
|
|
d67a794e2c | ||
|
|
60318083a6 | ||
|
|
7607070452 | ||
|
|
28fb7b6e9c | ||
|
|
aafe15757f | ||
|
|
31d6ef6296 | ||
|
|
32b8fac37f | ||
|
|
e8060de914 | ||
|
|
22b036527c | ||
|
|
feb1e030d7 | ||
|
|
bd271e3952 | ||
|
|
df80938190 | ||
|
|
67bbc0a3fe | ||
|
|
e1ece6dc66 | ||
|
|
fe038822a3 | ||
|
|
dece14486c | ||
|
|
2daffbc2ca | ||
|
|
4c01a34d09 | ||
|
|
3b08267daa | ||
|
|
b98ebddb69 | ||
|
|
9d5bf50676 | ||
|
|
c0972f8158 | ||
|
|
548125a944 | ||
|
|
a7b124ca6e | ||
|
|
4022374620 | ||
|
|
860e4d7af6 | ||
|
|
6376d69b58 | ||
|
|
5cf6f45f19 | ||
|
|
967903673b | ||
|
|
2d897f1844 | ||
|
|
fb2f9bc493 | ||
|
|
6f9ae0c4fc | ||
|
|
9df20fac8a | ||
|
|
a1fb1a6258 | ||
|
|
417d0ef3b5 | ||
|
|
9be256231b | ||
|
|
c122bdc750 | ||
|
|
4ef36ab81c | ||
|
|
cccc0e1015 | ||
|
|
db5312443e | ||
|
|
dbda07424b | ||
|
|
684d38d6c8 | ||
|
|
44fa064eb2 | ||
|
|
9b6fffd880 | ||
|
|
e9993b2643 | ||
|
|
762e9e8a3a | ||
|
|
6ddeb788c7 | ||
|
|
b9245f323c | ||
|
|
c0e630b635 | ||
|
|
e56457a0ef | ||
|
|
ca13849828 | ||
|
|
92c2fbd6d3 | ||
|
|
65b8921f05 | ||
|
|
1ace7f4b73 | ||
|
|
ed2273e2ed |
12
.babelrc
12
.babelrc
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"presets": [
|
||||
["latest", {
|
||||
"es2015": {
|
||||
"modules": false
|
||||
}
|
||||
}]
|
||||
],
|
||||
"plugins": [
|
||||
"external-helpers"
|
||||
]
|
||||
}
|
||||
7
.circleci/config.yml
Normal file
7
.circleci/config.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
version: 2.1
|
||||
orbs:
|
||||
node: circleci/node@3.0.0
|
||||
workflows:
|
||||
node-tests:
|
||||
jobs:
|
||||
- node/test
|
||||
10
.esdoc.json
10
.esdoc.json
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"source": "./src",
|
||||
"destination": "./docs",
|
||||
"plugins": [{
|
||||
"name": "esdoc-standard-plugin",
|
||||
"option": {
|
||||
"accessor": {"access": ["public"], "autoPrivate": true}
|
||||
}
|
||||
}]
|
||||
}
|
||||
14
.flowconfig
14
.flowconfig
@@ -1,14 +0,0 @@
|
||||
[ignore]
|
||||
.*/node_modules/.*
|
||||
.*/dist/.*
|
||||
.*/build/.*
|
||||
|
||||
[include]
|
||||
./src/
|
||||
./tests-lib/
|
||||
./test/
|
||||
|
||||
[libs]
|
||||
./declarations/
|
||||
|
||||
[options]
|
||||
29
.github/workflows/node.js.yml
vendored
Normal file
29
.github/workflows/node.js.yml
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
|
||||
|
||||
name: Node.js CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [10.x, 12.x, 14.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- run: npm ci
|
||||
- run: npm run build --if-present
|
||||
- run: npm test
|
||||
31
.github/workflows/nodejs.yml
vendored
Normal file
31
.github/workflows/nodejs.yml
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
|
||||
|
||||
name: Node.js CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [10.x, 12.x, 13.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- run: npm ci
|
||||
- run: npm run lint
|
||||
- run: npm run test-extensive
|
||||
env:
|
||||
CI: true
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,5 +1,4 @@
|
||||
node_modules
|
||||
bower_components
|
||||
dist
|
||||
.vscode
|
||||
docs
|
||||
/y.*
|
||||
/examples/yjs-dist.js*
|
||||
|
||||
52
.jsdoc.json
Normal file
52
.jsdoc.json
Normal file
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"sourceType": "module",
|
||||
"tags": {
|
||||
"allowUnknownTags": true,
|
||||
"dictionaries": ["jsdoc"]
|
||||
},
|
||||
"source": {
|
||||
"include": ["./src"],
|
||||
"includePattern": ".js$"
|
||||
},
|
||||
"plugins": [
|
||||
"plugins/markdown"
|
||||
],
|
||||
"templates": {
|
||||
"referenceTitle": "Yjs",
|
||||
"disableSort": false,
|
||||
"useCollapsibles": true,
|
||||
"collapse": true,
|
||||
"resources": {
|
||||
"yjs.dev": "Website",
|
||||
"docs.yjs.dev": "Docs",
|
||||
"discuss.yjs.dev": "Forum",
|
||||
"https://gitter.im/Yjs/community": "Chat"
|
||||
},
|
||||
"logo": {
|
||||
"url": "https://yjs.dev/images/logo/yjs-512x512.png",
|
||||
"width": "162px",
|
||||
"height": "162px",
|
||||
"link": "/"
|
||||
},
|
||||
"tabNames": {
|
||||
"api": "API",
|
||||
"tutorials": "Examples"
|
||||
},
|
||||
"footerText": "Shared Editing",
|
||||
"css": [
|
||||
"./style.css"
|
||||
],
|
||||
"default": {
|
||||
"staticFiles": {
|
||||
"include": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"opts": {
|
||||
"destination": "./docs/",
|
||||
"encoding": "utf8",
|
||||
"private": false,
|
||||
"recurse": true,
|
||||
"template": "./node_modules/tui-jsdoc-template"
|
||||
}
|
||||
}
|
||||
4
.markdownlint.json
Normal file
4
.markdownlint.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"default": true,
|
||||
"no-inline-html": false
|
||||
}
|
||||
179
INTERNALS.md
Normal file
179
INTERNALS.md
Normal file
@@ -0,0 +1,179 @@
|
||||
# Yjs Internals
|
||||
|
||||
This document roughly explains how Yjs works internally. There is a complete
|
||||
walkthrough of the Yjs codebase available as a recording:
|
||||
https://youtu.be/0l5XgnQ6rB4
|
||||
|
||||
The Yjs CRDT algorithm is described in the [YATA
|
||||
paper](https://www.researchgate.net/publication/310212186_Near_Real-Time_Peer-to-Peer_Shared_Editing_on_Extensible_Data_Types)
|
||||
from 2016. For an algorithmic view of how it works, the paper is a reasonable
|
||||
place to start. There are a handful of small improvements implemented in Yjs
|
||||
which aren't described in the paper. The most notable is that items have an
|
||||
`originRight` as well as an `origin` property, which improves performance when
|
||||
many concurrent inserts happen after the same character.
|
||||
|
||||
At its heart, Yjs is a list CRDT. Everything is squeezed into a list in order to
|
||||
reuse the CRDT resolution algorithm:
|
||||
|
||||
- Arrays are easy - they're lists of arbitrary items.
|
||||
- Text is a list of characters, optionally punctuated by formatting markers and
|
||||
embeds for rich text support. Several characters can be wrapped in a single
|
||||
linked list `Item` (this is also known as the compound representation of
|
||||
CRDTs). More information about this in [this blog
|
||||
article](https://blog.kevinjahns.de/are-crdts-suitable-for-shared-editing/).
|
||||
- Maps are lists of entries. The last inserted entry for each key is used, and
|
||||
all other duplicates for each key are flagged as deleted.
|
||||
|
||||
Each client is assigned a unique *clientID* property on first insert. This is a
|
||||
random 53-bit integer (53 bits because that fits in the javascript safe integer
|
||||
range).
|
||||
|
||||
## List items
|
||||
|
||||
Each item in a Yjs list is made up of two objects:
|
||||
|
||||
- An `Item` (*src/structs/Item.js*). This is used to relate the item to other
|
||||
adjacent items.
|
||||
- An object in the `AbstractType` hierarchy (subclasses of
|
||||
*src/types/AbstractType.js* - eg `YText`). This stores the actual content in
|
||||
the Yjs document.
|
||||
|
||||
The item and type object pair have a 1-1 mapping. The item's `content` field
|
||||
references the AbstractType object and the AbstractType object's `_item` field
|
||||
references the item.
|
||||
|
||||
Everything inserted in a Yjs document is given a unique ID, formed from a
|
||||
*ID(clientID, clock)* pair (also known as a [Lamport
|
||||
Timestamp](https://en.wikipedia.org/wiki/Lamport_timestamp)). The clock counts
|
||||
up from 0 with the first inserted character or item a client makes. This is
|
||||
similar to automerge's operation IDs, but note that the clock is only
|
||||
incremented by inserts. Deletes are handled in a very different way (see
|
||||
below).
|
||||
|
||||
If a run of characters is inserted into a document (eg `"abc"`), the clock will
|
||||
be incremented for each character (eg 3 times here). But Yjs will only add a
|
||||
single `Item` into the list. This has no effect on the core CRDT algorithm, but
|
||||
the optimization dramatically decreases the number of javascript objects
|
||||
created during normal text editing. This optimization only applies if the
|
||||
characters share the same clientID, they're inserted in order, and all
|
||||
characters have either been deleted or all characters are not deleted. The item
|
||||
will be split if the run is interrupted for any reason (eg a character in the
|
||||
middle of the run is deleted).
|
||||
|
||||
When an item is created, it stores a reference to the IDs of the preceeding and
|
||||
succeeding item. These are stored in the item's `origin` and `originRight`
|
||||
fields, respectively. These are used when peers concurrently insert at the same
|
||||
location in a document. Though quite rare in practice, Yjs needs to make sure
|
||||
the list items always resolve to the same order on all peers. The actual logic
|
||||
is relatively simple - its only a couple dozen lines of code and it lives in
|
||||
the `Item#integrate()` method. The YATA paper has much more detail on the this
|
||||
algorithm.
|
||||
|
||||
### Item Storage
|
||||
|
||||
The items themselves are stored in two data structures and a cache:
|
||||
|
||||
- The items are stored in a tree of doubly-linked lists in *document order*.
|
||||
Each item has `left` and `right` properties linking to its siblings in the
|
||||
document. Items also have a `parent` property to reference their parent in the
|
||||
document tree (null at the root). (And you can access an item's children, if
|
||||
any, through `item.content`).
|
||||
- All items are referenced in *insertion order* inside the struct store
|
||||
(*src/utils/StructStore.js*). This references the list of items inserted by
|
||||
for each client, in chronological order. This is used to find an item in the
|
||||
tree with a given ID (using a binary search). It is also used to efficiently
|
||||
gather the operations a peer is missing during sync (more on this below).
|
||||
|
||||
When a local insert happens, Yjs needs to map the insert position in the
|
||||
document (eg position 1000) to an ID. With just the linked list, this would
|
||||
require a slow O(n) linear scan of the list. But when editing a document, most
|
||||
inserts are either at the same position as the last insert, or nearby. To
|
||||
improve performance, Yjs stores a cache of the 10 most recently looked up
|
||||
insert positions in the document. This is consulted and updated when a position
|
||||
is looked up to improve performance in the average case. The cache is updated
|
||||
using a heuristic that is still changing (currently, it is updated when a new
|
||||
position significantly diverges from existing markers in the cache). Internally
|
||||
this is referred to as the skip list / fast search marker.
|
||||
|
||||
### Deletions
|
||||
|
||||
Deletions in Yjs are treated very differently from insertions. Insertions are
|
||||
implemented as a sequential operation based CRDT, but deletions are treated as
|
||||
a simpler state based CRDT.
|
||||
|
||||
When an item has been deleted by any peer, at any point in history, it is
|
||||
flagged as deleted on the item. (Internally Yjs uses the `info` bitfield.) Yjs
|
||||
does not record metadata about a deletion:
|
||||
|
||||
- No data is kept on *when* an item was deleted, or which user deleted it.
|
||||
- The struct store does not contain deletion records
|
||||
- The clientID's clock is not incremented
|
||||
|
||||
If garbage collection is enabled in Yjs, when an object is deleted its content
|
||||
is discarded. If a deleted object contains children (eg a field is deleted in
|
||||
an object), the content is replaced with a `GC` object (*src/structs/GC.js*).
|
||||
This is a very lightweight structure - it only stores the length of the removed
|
||||
content.
|
||||
|
||||
Yjs has some special logic to share which content in a document has been
|
||||
deleted:
|
||||
|
||||
- When a delete happens, as well as marking the item, the deleted IDs are
|
||||
listed locally within the transaction. (See below for more information about
|
||||
transactions.) When a transaction has been committed locally, the set of
|
||||
deleted items is appended to a transaction's update message.
|
||||
- A snapshot (a marked point in time in the Yjs history) is specified using
|
||||
both the set of (clientID, clock) pairs *and* the set of all deleted item
|
||||
IDs. The deleted set is O(n), but because deletions usually happen in runs,
|
||||
this data set is usually tiny in practice. (The real world editing trace from
|
||||
the B4 benchmark document contains 182k inserts and 77k deleted characters. The
|
||||
deleted set size in a snapshot is only 4.5Kb).
|
||||
|
||||
## Transactions
|
||||
|
||||
All updates in Yjs happen within a *transaction*. (Defined in
|
||||
*src/utils/Transaction.js*.)
|
||||
|
||||
The transaction collects a set of updates to the Yjs document to be applied on
|
||||
remote peers atomically. Once a transaction has been committed locally, it
|
||||
generates a compressed *update message* which is broadcast to synchronized
|
||||
remote peers to notify them of the local change. The update message contains:
|
||||
|
||||
- The set of newly inserted items
|
||||
- The set of items deleted within the transaction.
|
||||
|
||||
## Network protocol
|
||||
|
||||
The network protocol is not really a part of Yjs. There are a few relevant
|
||||
concepts that can be used to create a custom network protocol:
|
||||
|
||||
* `update`: The Yjs document can be encoded to an *update* object that can be
|
||||
parsed to reconstruct the document. Also every change on the document fires
|
||||
an incremental document updates that allows clients to sync with each other.
|
||||
The update object is an Uint8Array that efficiently encodes `Item` objects and
|
||||
the delete set.
|
||||
* `state vector`: A state vector defines the know state of each user (a set of
|
||||
tubles `(client, clock)`). This object is also efficiently encoded as a
|
||||
Uint8Array.
|
||||
|
||||
The client can ask a remote client for missing document updates by sending
|
||||
their state vector (often referred to as *sync step 1*). The remote peer can
|
||||
compute the missing `Item` objects using the `clocks` of the respective clients
|
||||
and compute a minimal update message that reflects all missing updates (sync
|
||||
step 2).
|
||||
|
||||
An implementation of the syncing process is in
|
||||
[y-protocols](https://github.com/yjs/y-protocols).
|
||||
|
||||
## Snapshots
|
||||
|
||||
A snapshot can be used to restore an old document state. It is a `state vector`
|
||||
\+ `delete set`. I client can restore an old document state by iterating through
|
||||
the sequence CRDT and ignoring all Items that have an `id.clock >
|
||||
stateVector[id.client].clock`. Instead of using `item.deleted` the client will
|
||||
use the delete set to find out if an item was deleted or not.
|
||||
|
||||
It is not recommended to restore an old document state using snapshots,
|
||||
although that would certainly be possible. Instead, the old state should be
|
||||
computed by iterating through the newest state and using the additional
|
||||
information from the state vector.
|
||||
@@ -1,33 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style type="text/css" media="screen">
|
||||
#aceContainer {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
.inserted {
|
||||
position:absolute;
|
||||
z-index:20;
|
||||
background-color: #FFC107;
|
||||
}
|
||||
.deleted {
|
||||
position:absolute;
|
||||
z-index:20;
|
||||
background-color: #FFC107;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="aceContainer"></div>
|
||||
<script src="../../y.js"></script>
|
||||
<script src='../../../y-websockets-client/y-websockets-client.js'></script>
|
||||
<script src="../bower_components/ace-builds/src/ace.js"></script>
|
||||
|
||||
<script src="./index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,17 +0,0 @@
|
||||
/* global Y, ace */
|
||||
|
||||
let y = new Y('ace-example', {
|
||||
connector: {
|
||||
name: 'websockets-client',
|
||||
url: 'http://127.0.0.1:1234'
|
||||
}
|
||||
})
|
||||
|
||||
window.yAce = y
|
||||
|
||||
// bind the textarea to a shared text element
|
||||
var editor = ace.edit('aceContainer')
|
||||
editor.setTheme('ace/theme/chrome')
|
||||
editor.getSession().setMode('ace/mode/javascript')
|
||||
|
||||
y.define('ace', Y.Text).bindAce(editor)
|
||||
@@ -1,19 +0,0 @@
|
||||
{
|
||||
"name": "yjs-examples",
|
||||
"version": "0.0.0",
|
||||
"homepage": "y-js.org",
|
||||
"authors": [
|
||||
"Kevin Jahns <kevin.jahns@rwth-aachen.de>"
|
||||
],
|
||||
"description": "Examples for Yjs",
|
||||
"license": "MIT",
|
||||
"ignore": [],
|
||||
"dependencies": {
|
||||
"quill": "^1.0.0-rc.2",
|
||||
"ace": "~1.2.3",
|
||||
"ace-builds": "~1.2.3",
|
||||
"jquery": "~2.2.2",
|
||||
"d3": "^3.5.16",
|
||||
"codemirror": "^5.25.0"
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<style>
|
||||
#chat p span {
|
||||
color: blue;
|
||||
}
|
||||
</style>
|
||||
<div id="chat"></div>
|
||||
<form id="chatform">
|
||||
<input name="username" type="text" style="width:15%;">
|
||||
<input name="message" type="text" style="width:60%;">
|
||||
<input type="submit" value="Send">
|
||||
</form>
|
||||
<script src="../../y.js"></script>
|
||||
<script src='../../../y-websockets-client/y-websockets-client.js'></script>
|
||||
<script src="./index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,65 +0,0 @@
|
||||
/* global Y */
|
||||
|
||||
let y = new Y('chat-example', {
|
||||
connector: {
|
||||
name: 'websockets-client',
|
||||
url: 'http://127.0.0.1:1234'
|
||||
}
|
||||
})
|
||||
|
||||
window.yChat = y
|
||||
|
||||
let chatprotocol = y.define('chatprotocol', Y.Array)
|
||||
|
||||
let chatcontainer = document.querySelector('#chat')
|
||||
|
||||
// This functions inserts a message at the specified position in the DOM
|
||||
function appendMessage (message, position) {
|
||||
var p = document.createElement('p')
|
||||
var uname = document.createElement('span')
|
||||
uname.appendChild(document.createTextNode(message.username + ': '))
|
||||
p.appendChild(uname)
|
||||
p.appendChild(document.createTextNode(message.message))
|
||||
chatcontainer.insertBefore(p, chatcontainer.children[position] || null)
|
||||
}
|
||||
|
||||
// This function makes sure that only 7 messages exist in the chat history.
|
||||
// The rest is deleted
|
||||
function cleanupChat () {
|
||||
if (chatprotocol.length > 7) {
|
||||
chatprotocol.delete(0, chatprotocol.length - 7)
|
||||
}
|
||||
}
|
||||
cleanupChat()
|
||||
|
||||
// Insert the initial content
|
||||
chatprotocol.toArray().forEach(appendMessage)
|
||||
|
||||
// whenever content changes, make sure to reflect the changes in the DOM
|
||||
chatprotocol.observe(function (event) {
|
||||
// concurrent insertions may result in a history > 7, so cleanup here
|
||||
cleanupChat()
|
||||
chatcontainer.innerHTML = ''
|
||||
chatprotocol.toArray().forEach(appendMessage)
|
||||
})
|
||||
document.querySelector('#chatform').onsubmit = function (event) {
|
||||
// the form is submitted
|
||||
var message = {
|
||||
username: this.querySelector('[name=username]').value,
|
||||
message: this.querySelector('[name=message]').value
|
||||
}
|
||||
if (message.username.length > 0 && message.message.length > 0) {
|
||||
if (chatprotocol.length > 6) {
|
||||
// If we are goint to insert the 8th element, make sure to delete first.
|
||||
chatprotocol.delete(0)
|
||||
}
|
||||
// Here we insert a message in the shared chat type.
|
||||
// This will call the observe function (see line 40)
|
||||
// and reflect the change in the DOM
|
||||
chatprotocol.push([message])
|
||||
this.querySelector('[name=message]').value = ''
|
||||
}
|
||||
// Do not send this form!
|
||||
event.preventDefault()
|
||||
return false
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<div id="codeMirrorContainer"></div>
|
||||
|
||||
<script src="../../y.js"></script>
|
||||
<script src='../../../y-websockets-client/y-websockets-client.js'></script>
|
||||
<script src="../bower_components/codemirror/lib/codemirror.js"></script>
|
||||
<script src="../bower_components/codemirror/mode/javascript/javascript.js"></script>
|
||||
<link rel="stylesheet" href="../bower_components/codemirror/lib/codemirror.css">
|
||||
<style>
|
||||
.CodeMirror {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
<script src="./index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,16 +0,0 @@
|
||||
/* global Y, CodeMirror */
|
||||
|
||||
let y = new Y('codemirror-example', {
|
||||
connector: {
|
||||
name: 'websockets-client',
|
||||
url: 'http://127.0.0.1:1234'
|
||||
}
|
||||
})
|
||||
|
||||
window.yCodeMirror = y
|
||||
|
||||
var editor = CodeMirror(document.querySelector('#codeMirrorContainer'), {
|
||||
mode: 'javascript',
|
||||
lineNumbers: true
|
||||
})
|
||||
y.define('codemirror', Y.Text).bindCodeMirror(editor)
|
||||
@@ -1,20 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<style>
|
||||
path {
|
||||
fill: none;
|
||||
stroke: blue;
|
||||
stroke-width: 1px;
|
||||
stroke-linejoin: round;
|
||||
stroke-linecap: round;
|
||||
}
|
||||
</style>
|
||||
<button type="button" id="clearDrawingCanvas">Clear Drawing</button>
|
||||
<svg id="drawingCanvas" viewbox="0 0 100 100" width="100%"></svg>
|
||||
<script src="../../y.js"></script>
|
||||
<script src='../../../y-websockets-client/y-websockets-client.js'></script>
|
||||
<script src="../bower_components/d3/d3.min.js"></script>
|
||||
<script src="./index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,74 +0,0 @@
|
||||
/* globals Y, d3 */
|
||||
|
||||
let y = new Y('drawing-example', {
|
||||
connector: {
|
||||
name: 'websockets-client',
|
||||
url: 'http://127.0.0.1:1234'
|
||||
}
|
||||
})
|
||||
|
||||
window.yDrawing = y
|
||||
var drawing = y.define('drawing', Y.Array)
|
||||
var renderPath = d3.svg.line()
|
||||
.x(function (d) { return d[0] })
|
||||
.y(function (d) { return d[1] })
|
||||
.interpolate('basic')
|
||||
|
||||
var svg = d3.select('#drawingCanvas')
|
||||
.call(d3.behavior.drag()
|
||||
.on('dragstart', dragstart)
|
||||
.on('drag', drag)
|
||||
.on('dragend', dragend))
|
||||
|
||||
// create line from a shared array object and update the line when the array changes
|
||||
function drawLine (yarray) {
|
||||
var line = svg.append('path').datum(yarray.toArray())
|
||||
line.attr('d', renderPath)
|
||||
yarray.observe(function (event) {
|
||||
line.remove()
|
||||
line = svg.append('path').datum(yarray.toArray())
|
||||
line.attr('d', renderPath)
|
||||
})
|
||||
}
|
||||
// call drawLine every time an array is appended
|
||||
drawing.observe(function (event) {
|
||||
event.removedElements.forEach(function () {
|
||||
// if one is deleted, all will be deleted!!
|
||||
svg.selectAll('path').remove()
|
||||
})
|
||||
event.addedElements.forEach(function (path) {
|
||||
drawLine(path)
|
||||
})
|
||||
})
|
||||
// draw all existing content
|
||||
for (var i = 0; i < drawing.length; i++) {
|
||||
drawLine(drawing.get(i))
|
||||
}
|
||||
|
||||
// clear canvas on request
|
||||
document.querySelector('#clearDrawingCanvas').onclick = function () {
|
||||
drawing.delete(0, drawing.length)
|
||||
}
|
||||
|
||||
var sharedLine = null
|
||||
function dragstart () {
|
||||
drawing.insert(drawing.length, [Y.Array])
|
||||
sharedLine = drawing.get(drawing.length - 1)
|
||||
}
|
||||
|
||||
// After one dragged event is recognized, we ignore them for 33ms.
|
||||
var ignoreDrag = null
|
||||
function drag () {
|
||||
if (sharedLine != null && ignoreDrag == null) {
|
||||
ignoreDrag = window.setTimeout(function () {
|
||||
ignoreDrag = null
|
||||
}, 10)
|
||||
sharedLine.push([d3.mouse(this)])
|
||||
}
|
||||
}
|
||||
|
||||
function dragend () {
|
||||
sharedLine = null
|
||||
window.clearTimeout(ignoreDrag)
|
||||
ignoreDrag = null
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
</head>
|
||||
<script src="../../y.js"></script>
|
||||
<script src='../../../y-websockets-client/y-websockets-client.js'></script>
|
||||
<script src="../bower_components/d3/d3.min.js"></script>
|
||||
<script src="./index.js"></script>
|
||||
<style>
|
||||
magic-drawing .drawingCanvas path {
|
||||
fill: none;
|
||||
stroke: blue;
|
||||
stroke-width: 2px;
|
||||
stroke-linejoin: round;
|
||||
stroke-linecap: round;
|
||||
}
|
||||
magic-drawing .drawingCanvas {
|
||||
width: 500px;
|
||||
height: 500px;
|
||||
cursor: default;
|
||||
padding:1px;
|
||||
border:1px solid #021a40;
|
||||
}
|
||||
magic-drawing .clearDrawingButton {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
magic-drawing {
|
||||
position: relative;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body contenteditable="true">
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,134 +0,0 @@
|
||||
/* global Y, d3 */
|
||||
|
||||
const hooks = {
|
||||
'magic-drawing': {
|
||||
fillType: function (dom, type) {
|
||||
initDrawingBindings(type, dom)
|
||||
},
|
||||
createDom: function (type) {
|
||||
const dom = document.createElement('magic-drawing')
|
||||
initDrawingBindings(type, dom)
|
||||
return dom
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.onload = function () {
|
||||
window.domBinding = new Y.DomBinding(window.yXmlType, document.body, { hooks })
|
||||
}
|
||||
|
||||
window.addMagicDrawing = function addMagicDrawing () {
|
||||
let mt = document.createElement('magic-drawing')
|
||||
mt.setAttribute('data-yjs-hook', 'magic-drawing')
|
||||
document.body.append(mt)
|
||||
}
|
||||
|
||||
var renderPath = d3.svg.line()
|
||||
.x(function (d) { return d[0] })
|
||||
.y(function (d) { return d[1] })
|
||||
.interpolate('basic')
|
||||
|
||||
function initDrawingBindings (type, dom) {
|
||||
dom.contentEditable = 'false'
|
||||
dom.setAttribute('data-yjs-hook', 'magic-drawing')
|
||||
var drawing = type.get('drawing')
|
||||
if (drawing === undefined) {
|
||||
drawing = type.set('drawing', new Y.Array())
|
||||
}
|
||||
var canvas = dom.querySelector('.drawingCanvas')
|
||||
if (canvas == null) {
|
||||
canvas = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
|
||||
canvas.setAttribute('class', 'drawingCanvas')
|
||||
canvas.setAttribute('viewbox', '0 0 100 100')
|
||||
dom.insertBefore(canvas, null)
|
||||
}
|
||||
var clearDrawingButton = dom.querySelector('.clearDrawingButton')
|
||||
if (clearDrawingButton == null) {
|
||||
clearDrawingButton = document.createElement('button')
|
||||
clearDrawingButton.setAttribute('type', 'button')
|
||||
clearDrawingButton.setAttribute('class', 'clearDrawingButton')
|
||||
clearDrawingButton.innerText = 'Clear Drawing'
|
||||
dom.insertBefore(clearDrawingButton, null)
|
||||
}
|
||||
var svg = d3.select(canvas)
|
||||
.call(d3.behavior.drag()
|
||||
.on('dragstart', dragstart)
|
||||
.on('drag', drag)
|
||||
.on('dragend', dragend))
|
||||
// create line from a shared array object and update the line when the array changes
|
||||
function drawLine (yarray, svg) {
|
||||
var line = svg.append('path').datum(yarray.toArray())
|
||||
line.attr('d', renderPath)
|
||||
yarray.observe(function (event) {
|
||||
line.remove()
|
||||
line = svg.append('path').datum(yarray.toArray())
|
||||
line.attr('d', renderPath)
|
||||
})
|
||||
}
|
||||
// call drawLine every time an array is appended
|
||||
drawing.observe(function (event) {
|
||||
event.removedElements.forEach(function () {
|
||||
// if one is deleted, all will be deleted!!
|
||||
svg.selectAll('path').remove()
|
||||
})
|
||||
event.addedElements.forEach(function (path) {
|
||||
drawLine(path, svg)
|
||||
})
|
||||
})
|
||||
// draw all existing content
|
||||
for (var i = 0; i < drawing.length; i++) {
|
||||
drawLine(drawing.get(i), svg)
|
||||
}
|
||||
|
||||
// clear canvas on request
|
||||
clearDrawingButton.onclick = function () {
|
||||
drawing.delete(0, drawing.length)
|
||||
}
|
||||
|
||||
var sharedLine = null
|
||||
function dragstart () {
|
||||
drawing.insert(drawing.length, [Y.Array])
|
||||
sharedLine = drawing.get(drawing.length - 1)
|
||||
}
|
||||
|
||||
// After one dragged event is recognized, we ignore them for 33ms.
|
||||
var ignoreDrag = null
|
||||
function drag () {
|
||||
if (sharedLine != null && ignoreDrag == null) {
|
||||
ignoreDrag = window.setTimeout(function () {
|
||||
ignoreDrag = null
|
||||
}, 10)
|
||||
sharedLine.push([d3.mouse(this)])
|
||||
}
|
||||
}
|
||||
|
||||
function dragend () {
|
||||
sharedLine = null
|
||||
window.clearTimeout(ignoreDrag)
|
||||
ignoreDrag = null
|
||||
}
|
||||
}
|
||||
|
||||
let y = new Y('html-editor-drawing-hook-example', {
|
||||
connector: {
|
||||
name: 'websockets-client',
|
||||
url: 'http://127.0.0.1:1234'
|
||||
}
|
||||
})
|
||||
|
||||
window.yXml = y
|
||||
window.yXmlType = y.define('xml', Y.XmlFragment)
|
||||
window.undoManager = new Y.utils.UndoManager(window.yXmlType, {
|
||||
captureTimeout: 500
|
||||
})
|
||||
|
||||
document.onkeydown = function interceptUndoRedo (e) {
|
||||
if (e.keyCode === 90 && e.metaKey) {
|
||||
if (!e.shiftKey) {
|
||||
window.undoManager.undo()
|
||||
} else {
|
||||
window.undoManager.redo()
|
||||
}
|
||||
e.preventDefault()
|
||||
}
|
||||
}
|
||||
645
examples/html-editor/canvasjs.min.js
vendored
645
examples/html-editor/canvasjs.min.js
vendored
@@ -1,645 +0,0 @@
|
||||
/*
|
||||
CanvasJS HTML5 & JavaScript Charts - v1.9.10 GA - https://canvasjs.com/
|
||||
Copyright 2017 fenopix
|
||||
|
||||
--------------------- License Information --------------------
|
||||
CanvasJS is a commercial product which requires purchase of license. Without a commercial license you can use it for evaluation purposes for upto 30 days. Please refer to the following link for further details.
|
||||
https://canvasjs.com/license-canvasjs/
|
||||
|
||||
|
||||
*/
|
||||
(function(){function T(a,c){a.prototype=Sa(c.prototype);a.prototype.constructor=a;a.base=c.prototype}function Sa(a){function c(){}c.prototype=a;return new c}function Ia(a,c,b){"millisecond"===b?a.setMilliseconds(a.getMilliseconds()+1*c):"second"===b?a.setSeconds(a.getSeconds()+1*c):"minute"===b?a.setMinutes(a.getMinutes()+1*c):"hour"===b?a.setHours(a.getHours()+1*c):"day"===b?a.setDate(a.getDate()+1*c):"week"===b?a.setDate(a.getDate()+7*c):"month"===b?a.setMonth(a.getMonth()+1*c):"year"===b&&a.setFullYear(a.getFullYear()+
|
||||
1*c);return a}function P(a,c){var b=!1;0>a&&(b=!0,a*=-1);a=""+a;for(c=c?c:1;a.length<c;)a="0"+a;return b?"-"+a:a}function ma(a){if(!a)return a;a=a.replace(/^\s\s*/,"");for(var c=/\s/,b=a.length;c.test(a.charAt(--b)););return a.slice(0,b+1)}function Ja(a){a.roundRect=function(a,b,d,f,g,l,k,h){k&&(this.fillStyle=k);h&&(this.strokeStyle=h);"undefined"===typeof g&&(g=5);this.lineWidth=l;this.beginPath();this.moveTo(a+g,b);this.lineTo(a+d-g,b);this.quadraticCurveTo(a+d,b,a+d,b+g);this.lineTo(a+d,b+f-g);
|
||||
this.quadraticCurveTo(a+d,b+f,a+d-g,b+f);this.lineTo(a+g,b+f);this.quadraticCurveTo(a,b+f,a,b+f-g);this.lineTo(a,b+g);this.quadraticCurveTo(a,b,a+g,b);this.closePath();k&&this.fill();h&&0<l&&this.stroke()}}function Aa(a,c){return a-c}function Ka(a,c){return a.x-c.x}function D(a){var c=((a&16711680)>>16).toString(16),b=((a&65280)>>8).toString(16);a=((a&255)>>0).toString(16);c=2>c.length?"0"+c:c;b=2>b.length?"0"+b:b;a=2>a.length?"0"+a:a;return"#"+c+b+a}function Ta(a,c){var b=this.length>>>0,d=Number(c)||
|
||||
0,d=0>d?Math.ceil(d):Math.floor(d);for(0>d&&(d+=b);d<b;d++)if(d in this&&this[d]===a)return d;return-1}function y(a){return null===a||"undefined"===typeof a}function sa(a){a.indexOf||(a.indexOf=Ta);return a}function Ua(a){if(I.fSDec)a[I.fSDec("`eeDwdouMhrudods")](I.fSDec("e`u`@ohl`uhnoHuds`uhnoDoe"),function(){I._fTWm&&I._fTWm(a)})}function La(a,c,b){b=b||"normal";var d=a+"_"+c+"_"+b,f=Ma[d];if(isNaN(f)){try{a="position:absolute; left:0px; top:-20000px; padding:0px;margin:0px;border:none;white-space:pre;line-height:normal;font-family:"+
|
||||
a+"; font-size:"+c+"px; font-weight:"+b+";";if(!da){var g=document.body;da=document.createElement("span");da.innerHTML="";var l=document.createTextNode("Mpgyi");da.appendChild(l);g.appendChild(da)}da.style.display="";da.setAttribute("style",a);f=Math.round(da.offsetHeight);da.style.display="none"}catch(k){f=Math.ceil(1.1*c)}f=Math.max(f,c);Ma[d]=f}return f}function F(a,c){var b=[];if(b={solid:[],shortDash:[3,1],shortDot:[1,1],shortDashDot:[3,1,1,1],shortDashDotDot:[3,1,1,1,1,1],dot:[1,2],dash:[4,
|
||||
2],dashDot:[4,2,1,2],longDash:[8,2],longDashDot:[8,2,1,2],longDashDotDot:[8,2,1,2,1,2]}[a||"solid"])for(var d=0;d<b.length;d++)b[d]*=c;else b=[];return b}function J(a,c,b,d){return a.addEventListener?(a.addEventListener(c,b,d||!1),b):a.attachEvent?(d=function(d){d=d||window.event;d.preventDefault=d.preventDefault||function(){d.returnValue=!1};d.stopPropagation=d.stopPropagation||function(){d.cancelBubble=!0};b.call(a,d)},a.attachEvent("on"+c,d),d):!1}function Na(a,c,b){a*=Q;c*=Q;a=b.getImageData(a,
|
||||
c,2,2).data;c=!0;for(b=0;4>b;b++)if(a[b]!==a[b+4]|a[b]!==a[b+8]|a[b]!==a[b+12]){c=!1;break}return c?a[0]<<16|a[1]<<8|a[2]:0}function K(a,c,b){return a in c?c[a]:b[a]}function ta(a,c,b){if(t&&Oa){var d=a.getContext("2d");ua=d.webkitBackingStorePixelRatio||d.mozBackingStorePixelRatio||d.msBackingStorePixelRatio||d.oBackingStorePixelRatio||d.backingStorePixelRatio||1;Q=Ba/ua;a.width=c*Q;a.height=b*Q;Ba!==ua&&(a.style.width=c+"px",a.style.height=b+"px",d.scale(Q,Q))}else a.width=c,a.height=b}function Va(a){if(!Pa){var c=
|
||||
!1,b=!1;"undefined"===typeof ea.Chart.creditHref?(a.creditHref=S("iuuqr;..b`ow`rkr/bnl."),a.creditText=S("B`ow`rKR/bnl")):(c=a.updateOption("creditText"),b=a.updateOption("creditHref"));if(a.creditHref&&a.creditText){a._creditLink||(a._creditLink=document.createElement("a"),a._creditLink.setAttribute("class","canvasjs-chart-credit"),a._creditLink.setAttribute("style","outline:none;margin:0px;position:absolute;right:2px;top:"+(a.height-14)+"px;color:dimgrey;text-decoration:none;font-size:11px;font-family: Calibri, Lucida Grande, Lucida Sans Unicode, Arial, sans-serif"),
|
||||
a._creditLink.setAttribute("tabIndex",-1),a._creditLink.setAttribute("target","_blank"));if(0===a.renderCount||c||b)a._creditLink.setAttribute("href",a.creditHref),a._creditLink.innerHTML=a.creditText;a._creditLink&&a.creditHref&&a.creditText?(a._creditLink.parentElement||a._canvasJSContainer.appendChild(a._creditLink),a._creditLink.style.top=a.height-14+"px"):a._creditLink.parentElement&&a._canvasJSContainer.removeChild(a._creditLink)}}}function ia(a,c){var b=document.createElement("canvas");b.setAttribute("class",
|
||||
"canvasjs-chart-canvas");ta(b,a,c);t||"undefined"===typeof G_vmlCanvasManager||G_vmlCanvasManager.initElement(b);return b}function Ca(a,c,b){if(a&&c&&b){b=b+"."+c;var d="image/"+c;a=a.toDataURL(d);var f=!1,g=document.createElement("a");g.download=b;g.href=a;g.target="_blank";if("undefined"!==typeof Blob&&new Blob){for(var l=a.replace(/^data:[a-z\/]*;base64,/,""),l=atob(l),k=new ArrayBuffer(l.length),k=new Uint8Array(k),h=0;h<l.length;h++)k[h]=l.charCodeAt(h);c=new Blob([k.buffer],{type:"image/"+c});
|
||||
try{window.navigator.msSaveBlob(c,b),f=!0}catch(m){g.dataset.downloadurl=[d,g.download,g.href].join(":"),g.href=window.URL.createObjectURL(c)}}if(!f)try{event=document.createEvent("MouseEvents"),event.initMouseEvent("click",!0,!1,window,0,0,0,0,0,!1,!1,!1,!1,0,null),g.dispatchEvent?g.dispatchEvent(event):g.fireEvent&&g.fireEvent("onclick")}catch(p){c=window.open(),c.document.write("<img src='"+a+"'></img><div>Please right click on the image and save it to your device</div>"),c.document.close()}}}
|
||||
function $(a,c,b){c.getAttribute("state")!==b&&(c.setAttribute("state",b),c.setAttribute("type","button"),c.style.position="relative",c.style.margin="0px 0px 0px 0px",c.style.padding="3px 4px 0px 4px",c.style.cssFloat="left",c.setAttribute("title",a._cultureInfo[b+"Text"]),c.innerHTML="<img style='height:16px;' src='"+Wa[b].image+"' alt='"+a._cultureInfo[b+"Text"]+"' />")}function va(){for(var a=null,c=0;c<arguments.length;c++)a=arguments[c],a.style&&(a.style.display="inline")}function aa(){for(var a=
|
||||
null,c=0;c<arguments.length;c++)(a=arguments[c])&&a.style&&(a.style.display="none")}function L(a,c,b,d){this._defaultsKey=a;this.parent=d;this._eventListeners=[];d={};b&&(ka[b]&&ka[b][a])&&(d=ka[b][a]);this.options=c?c:{_isPlaceholder:!0};this.setOptions(this.options,d)}function A(a,c){c=c||{};A.base.constructor.call(this,"Chart",c,c.theme?c.theme:"theme1");var b=this;this._containerId=a;this._objectsInitialized=!1;this.overlaidCanvasCtx=this.ctx=null;this._indexLabels=[];this._panTimerId=0;this._lastTouchEventType=
|
||||
"";this._lastTouchData=null;this.isAnimating=!1;this.renderCount=0;this.panEnabled=this.disableToolTip=this.animatedRender=!1;this._defaultCursor="default";this.plotArea={canvas:null,ctx:null,x1:0,y1:0,x2:0,y2:0,width:0,height:0};this._dataInRenderedOrder=[];if(this.container="string"===typeof this._containerId?document.getElementById(this._containerId):this._containerId){this.container.innerHTML="";var d=0,f=0,d=this.options.width?this.width:0<this.container.clientWidth?this.container.clientWidth:
|
||||
this.width,f=this.options.height?this.height:0<this.container.clientHeight?this.container.clientHeight:this.height;this.width=d;this.height=f;this.x1=this.y1=0;this.x2=this.width;this.y2=this.height;this._selectedColorSet="undefined"!==typeof ja[this.colorSet]?ja[this.colorSet]:ja.colorSet1;this._canvasJSContainer=document.createElement("div");this._canvasJSContainer.setAttribute("class","canvasjs-chart-container");this._canvasJSContainer.style.position="relative";this._canvasJSContainer.style.textAlign=
|
||||
"left";this._canvasJSContainer.style.cursor="auto";t||(this._canvasJSContainer.style.height="0px");this.container.appendChild(this._canvasJSContainer);this.canvas=ia(d,f);this.canvas.style.position="absolute";this.canvas.getContext&&(this._canvasJSContainer.appendChild(this.canvas),this.ctx=this.canvas.getContext("2d"),this.ctx.textBaseline="top",Ja(this.ctx),t?this.plotArea.ctx=this.ctx:(this.plotArea.canvas=ia(d,f),this.plotArea.canvas.style.position="absolute",this.plotArea.canvas.setAttribute("class",
|
||||
"plotAreaCanvas"),this._canvasJSContainer.appendChild(this.plotArea.canvas),this.plotArea.ctx=this.plotArea.canvas.getContext("2d")),this.overlaidCanvas=ia(d,f),this.overlaidCanvas.style.position="absolute",this._canvasJSContainer.appendChild(this.overlaidCanvas),this.overlaidCanvasCtx=this.overlaidCanvas.getContext("2d"),this.overlaidCanvasCtx.textBaseline="top",this._eventManager=new na(this),this.windowResizeHandler=J(window,"resize",function(){b._updateSize()&&b.render()}),this._toolBar=document.createElement("div"),
|
||||
this._toolBar.setAttribute("class","canvasjs-chart-toolbar"),this._toolBar.style.cssText="position: absolute; right: 1px; top: 1px;",this._canvasJSContainer.appendChild(this._toolBar),this.bounds={x1:0,y1:0,x2:this.width,y2:this.height},J(this.overlaidCanvas,"click",function(a){b._mouseEventHandler(a)}),J(this.overlaidCanvas,"mousemove",function(a){b._mouseEventHandler(a)}),J(this.overlaidCanvas,"mouseup",function(a){b._mouseEventHandler(a)}),J(this.overlaidCanvas,"mousedown",function(a){b._mouseEventHandler(a);
|
||||
aa(b._dropdownMenu)}),J(this.overlaidCanvas,"mouseout",function(a){b._mouseEventHandler(a)}),J(this.overlaidCanvas,window.navigator.msPointerEnabled?"MSPointerDown":"touchstart",function(a){b._touchEventHandler(a)}),J(this.overlaidCanvas,window.navigator.msPointerEnabled?"MSPointerMove":"touchmove",function(a){b._touchEventHandler(a)}),J(this.overlaidCanvas,window.navigator.msPointerEnabled?"MSPointerUp":"touchend",function(a){b._touchEventHandler(a)}),J(this.overlaidCanvas,window.navigator.msPointerEnabled?
|
||||
"MSPointerCancel":"touchcancel",function(a){b._touchEventHandler(a)}),this.toolTip=new R(this,this.options.toolTip),this.data=null,this.axisX=[],this.axisX2=[],this.axisY=[],this.axisY2=[],this.sessionVariables={axisX:[],axisX2:[],axisY:[],axisY2:[]})}else window.console&&window.console.log('CanvasJS Error: Chart Container with id "'+this._containerId+'" was not found')}function wa(a,c){for(var b=[],d,f=0;f<a.length;f++)if(0==f)b.push(a[0]);else{var g,l,k;k=f-1;g=0===k?0:k-1;l=k===a.length-1?k:k+
|
||||
1;d=Math.abs((a[l].x-a[g].x)/(0===a[l].x-a[k].x?0.01:a[l].x-a[k].x))*(c-1)/2+1;var h=(a[l].x-a[g].x)/d;d=(a[l].y-a[g].y)/d;b[b.length]=a[k].x>a[g].x&&0<h||a[k].x<a[g].x&&0>h?{x:a[k].x+h/3,y:a[k].y+d/3}:{x:a[k].x,y:a[k].y+d/9};k=f;g=0===k?0:k-1;l=k===a.length-1?k:k+1;d=Math.abs((a[l].x-a[g].x)/(0===a[k].x-a[g].x?0.01:a[k].x-a[g].x))*(c-1)/2+1;h=(a[l].x-a[g].x)/d;d=(a[l].y-a[g].y)/d;b[b.length]=a[k].x>a[g].x&&0<h||a[k].x<a[g].x&&0>h?{x:a[k].x-h/3,y:a[k].y-d/3}:{x:a[k].x,y:a[k].y-d/9};b[b.length]=a[f]}return b}
|
||||
function Qa(a,c){if(null===a||"undefined"===typeof a)return c;var b=parseFloat(a.toString())*(0<=a.toString().indexOf("%")?c/100:1);return!isNaN(b)&&b<=c&&0<=b?b:c}function la(a,c,b,d,f){"undefined"===typeof f&&(f=0);this._padding=f;this._x1=a;this._y1=c;this._x2=b;this._y2=d;this._rightOccupied=this._leftOccupied=this._bottomOccupied=this._topOccupied=this._padding}function V(a,c){V.base.constructor.call(this,"TextBlock",c);this.ctx=a;this._isDirty=!0;this._wrappedText=null}function oa(a,c){oa.base.constructor.call(this,
|
||||
"Title",c,a.theme,a);this.chart=a;this.canvas=a.canvas;this.ctx=this.chart.ctx;this.optionsName="title";if(y(this.options.margin)&&a.options.subtitles)for(var b=a.options.subtitles,d=0;d<b.length;d++)if((y(b[d].horizontalAlign)&&"center"===this.horizontalAlign||b[d].horizontalAlign===this.horizontalAlign)&&(y(b[d].verticalAlign)&&"top"===this.verticalAlign||b[d].verticalAlign===this.verticalAlign)&&!b[d].dockInsidePlotArea===!this.dockInsidePlotArea){this.margin=0;break}"undefined"===typeof this.options.fontSize&&
|
||||
(this.fontSize=this.chart.getAutoFontSize(this.fontSize));this.height=this.width=null;this.bounds={x1:null,y1:null,x2:null,y2:null}}function xa(a,c){xa.base.constructor.call(this,"Subtitle",c,a.theme,a);this.chart=a;this.canvas=a.canvas;this.ctx=this.chart.ctx;this.optionsName="subtitles";this.isOptionsInArray=!0;"undefined"===typeof this.options.fontSize&&(this.fontSize=this.chart.getAutoFontSize(this.fontSize));this.height=this.width=null;this.bounds={x1:null,y1:null,x2:null,y2:null}}function ya(a,
|
||||
c){ya.base.constructor.call(this,"Legend",c,a.theme,a);this.chart=a;this.canvas=a.canvas;this.ctx=this.chart.ctx;this.ghostCtx=this.chart._eventManager.ghostCtx;this.items=[];this.optionsName="legend";this.height=this.width=0;this.orientation=null;this.dataSeries=[];this.bounds={x1:null,y1:null,x2:null,y2:null};"undefined"===typeof this.options.fontSize&&(this.fontSize=this.chart.getAutoFontSize(this.fontSize));this.lineHeight=La(this.fontFamily,this.fontSize,this.fontWeight);this.horizontalSpacing=
|
||||
this.fontSize}function Da(a,c){Da.base.constructor.call(this,c);this.chart=a;this.canvas=a.canvas;this.ctx=this.chart.ctx}function ca(a,c,b,d){ca.base.constructor.call(this,"DataSeries",c,a.theme,a);this.chart=a;this.canvas=a.canvas;this._ctx=a.canvas.ctx;this.index=b;this.noDataPointsInPlotArea=0;this.id=d;this.chart._eventManager.objectMap[d]={id:d,objectType:"dataSeries",dataSeriesIndex:b};this.dataPointIds=[];this.plotUnit=[];this.axisY=this.axisX=null;this.optionsName="data";this.isOptionsInArray=
|
||||
!0;null===this.fillOpacity&&(this.type.match(/area/i)?this.fillOpacity=0.7:this.fillOpacity=1);this.axisPlacement=this.getDefaultAxisPlacement();"undefined"===typeof this.options.indexLabelFontSize&&(this.indexLabelFontSize=this.chart.getAutoFontSize(this.indexLabelFontSize))}function B(a,c,b,d,f){B.base.constructor.call(this,"Axis",c,a.theme,a);this.chart=a;this.canvas=a.canvas;this.ctx=a.ctx;this.intervalStartPosition=this.maxHeight=this.maxWidth=0;this.labels=[];this.dataSeries=[];this._stripLineLabels=
|
||||
this._ticks=this._labels=null;this.dataInfo={min:Infinity,max:-Infinity,viewPortMin:Infinity,viewPortMax:-Infinity,minDiff:Infinity};this.isOptionsInArray=!0;"axisX"===b?("left"===d||"bottom"===d?(this.optionsName="axisX",y(this.chart.sessionVariables.axisX[f])&&(this.chart.sessionVariables.axisX[f]={}),this.sessionVariables=this.chart.sessionVariables.axisX[f]):(this.optionsName="axisX2",y(this.chart.sessionVariables.axisX2[f])&&(this.chart.sessionVariables.axisX2[f]={}),this.sessionVariables=this.chart.sessionVariables.axisX2[f]),
|
||||
this.options.interval||(this.intervalType=null),"theme2"===this.chart.theme&&y(this.options.lineThickness)&&(this.lineThickness=2)):"left"===d||"top"===d?(this.optionsName="axisY",y(this.chart.sessionVariables.axisY[f])&&(this.chart.sessionVariables.axisY[f]={}),this.sessionVariables=this.chart.sessionVariables.axisY[f]):(this.optionsName="axisY2",y(this.chart.sessionVariables.axisY2[f])&&(this.chart.sessionVariables.axisY2[f]={}),this.sessionVariables=this.chart.sessionVariables.axisY2[f]);"undefined"===
|
||||
typeof this.options.titleFontSize&&(this.titleFontSize=this.chart.getAutoFontSize(this.titleFontSize));"undefined"===typeof this.options.labelFontSize&&(this.labelFontSize=this.chart.getAutoFontSize(this.labelFontSize));this.type=b;"axisX"!==b||c&&"undefined"!==typeof c.gridThickness||(this.gridThickness=0);this._position=d;this.lineCoordinates={x1:null,y1:null,x2:null,y2:null,width:null};this.labelAngle=(this.labelAngle%360+360)%360;90<this.labelAngle&&270>this.labelAngle?this.labelAngle-=180:270<=
|
||||
this.labelAngle&&360>=this.labelAngle&&(this.labelAngle-=360);if(this.options.stripLines&&0<this.options.stripLines.length)for(this.stripLines=[],c=0;c<this.options.stripLines.length;c++)this.stripLines.push(new pa(this.chart,this.options.stripLines[c],a.theme,++this.chart._eventManager.lastObjectId,this));this._titleTextBlock=null;this.hasOptionChanged("viewportMinimum")&&null===this.viewportMinimum&&(this.options.viewportMinimum=void 0,this.sessionVariables.viewportMinimum=null);this.hasOptionChanged("viewportMinimum")||
|
||||
isNaN(this.sessionVariables.newViewportMinimum)||null===this.sessionVariables.newViewportMinimum?this.sessionVariables.newViewportMinimum=null:this.viewportMinimum=this.sessionVariables.newViewportMinimum;this.hasOptionChanged("viewportMaximum")&&null===this.viewportMaximum&&(this.options.viewportMaximum=void 0,this.sessionVariables.viewportMaximum=null);this.hasOptionChanged("viewportMaximum")||isNaN(this.sessionVariables.newViewportMaximum)||null===this.sessionVariables.newViewportMaximum?this.sessionVariables.newViewportMaximum=
|
||||
null:this.viewportMaximum=this.sessionVariables.newViewportMaximum;null!==this.minimum&&null!==this.viewportMinimum&&(this.viewportMinimum=Math.max(this.viewportMinimum,this.minimum));null!==this.maximum&&null!==this.viewportMaximum&&(this.viewportMaximum=Math.min(this.viewportMaximum,this.maximum));this.trackChanges("viewportMinimum");this.trackChanges("viewportMaximum")}function pa(a,c,b,d,f){pa.base.constructor.call(this,"StripLine",c,b,f);this.id=d;this.chart=a;this.ctx=this.chart.ctx;this.label=
|
||||
this.label;this.axis=f;this.optionsName="stripLines";this.isOptionsInArray=!0;this._thicknessType="pixel";null!==this.startValue&&null!==this.endValue&&(this.value=f.logarithmic?Math.sqrt((this.startValue.getTime?this.startValue.getTime():this.startValue)*(this.endValue.getTime?this.endValue.getTime():this.endValue)):((this.startValue.getTime?this.startValue.getTime():this.startValue)+(this.endValue.getTime?this.endValue.getTime():this.endValue))/2,this.thickness=f.logarithmic?Math.log(this.endValue/
|
||||
this.startValue)/Math.log(f.logarithmBase):Math.max(this.endValue-this.startValue),this._thicknessType="value")}function R(a,c){R.base.constructor.call(this,"ToolTip",c,a.theme,a);this.chart=a;this.canvas=a.canvas;this.ctx=this.chart.ctx;this.currentDataPointIndex=this.currentSeriesIndex=-1;this._timerId=0;this._prevY=this._prevX=NaN;this.optionsName="toolTip";this._initialize()}function na(a){this.chart=a;this.lastObjectId=0;this.objectMap=[];this.rectangularRegionEventSubscriptions=[];this.previousDataPointEventObject=
|
||||
null;this.ghostCanvas=ia(this.chart.width,this.chart.height);this.ghostCtx=this.ghostCanvas.getContext("2d");this.mouseoveredObjectMaps=[]}function qa(a){var c;a&&ra[a]&&(c=ra[a]);qa.base.constructor.call(this,"CultureInfo",c)}function Ea(a){this.chart=a;this.ctx=this.chart.plotArea.ctx;this.animations=[];this.animationRequestId=null}var I={},t=!!document.createElement("canvas").getContext,ea={Chart:{width:500,height:400,zoomEnabled:!1,zoomType:"x",backgroundColor:"white",theme:"theme1",animationEnabled:!1,
|
||||
animationDuration:1200,dataPointWidth:null,dataPointMinWidth:null,dataPointMaxWidth:null,colorSet:"colorSet1",culture:"en",creditHref:"",creditText:"CanvasJS",interactivityEnabled:!0,exportEnabled:!1,exportFileName:"Chart",rangeChanging:null,rangeChanged:null,publicProperties:{title:"readWrite",subtitles:"readWrite",toolTip:"readWrite",legend:"readWrite",axisX:"readWrite",axisY:"readWrite",axisX2:"readWrite",axisY2:"readWrite",data:"readWrite",options:"readWrite",bounds:"readOnly",container:"readOnly"}},
|
||||
Title:{padding:0,text:null,verticalAlign:"top",horizontalAlign:"center",fontSize:20,fontFamily:"Calibri",fontWeight:"normal",fontColor:"black",fontStyle:"normal",borderThickness:0,borderColor:"black",cornerRadius:0,backgroundColor:t?"transparent":null,margin:5,wrap:!0,maxWidth:null,dockInsidePlotArea:!1,publicProperties:{options:"readWrite",bounds:"readOnly",chart:"readOnly"}},Subtitle:{padding:0,text:null,verticalAlign:"top",horizontalAlign:"center",fontSize:14,fontFamily:"Calibri",fontWeight:"normal",
|
||||
fontColor:"black",fontStyle:"normal",borderThickness:0,borderColor:"black",cornerRadius:0,backgroundColor:null,margin:2,wrap:!0,maxWidth:null,dockInsidePlotArea:!1,publicProperties:{options:"readWrite",bounds:"readOnly",chart:"readOnly"}},Legend:{name:null,verticalAlign:"center",horizontalAlign:"right",fontSize:14,fontFamily:"calibri",fontWeight:"normal",fontColor:"black",fontStyle:"normal",cursor:null,itemmouseover:null,itemmouseout:null,itemmousemove:null,itemclick:null,dockInsidePlotArea:!1,reversed:!1,
|
||||
backgroundColor:t?"transparent":null,borderColor:t?"transparent":null,borderThickness:0,cornerRadius:0,maxWidth:null,maxHeight:null,markerMargin:null,itemMaxWidth:null,itemWidth:null,itemWrap:!0,itemTextFormatter:null,publicProperties:{options:"readWrite",bounds:"readOnly",chart:"readOnly"}},ToolTip:{enabled:!0,shared:!1,animationEnabled:!0,content:null,contentFormatter:null,reversed:!1,backgroundColor:t?"rgba(255,255,255,.9)":"rgb(255,255,255)",borderColor:null,borderThickness:2,cornerRadius:5,fontSize:14,
|
||||
fontColor:"black",fontFamily:"Calibri, Arial, Georgia, serif;",fontWeight:"normal",fontStyle:"italic",publicProperties:{options:"readWrite",chart:"readOnly"}},Axis:{minimum:null,maximum:null,viewportMinimum:null,viewportMaximum:null,interval:null,intervalType:null,reversed:!1,logarithmic:!1,logarithmBase:10,title:null,titleFontColor:"black",titleFontSize:20,titleFontFamily:"arial",titleFontWeight:"normal",titleFontStyle:"normal",titleWrap:!0,titleMaxWidth:null,titleBackgroundColor:t?"transparent":
|
||||
null,titleBorderColor:t?"transparent":null,titleBorderThickness:0,titleCornerRadius:0,labelAngle:0,labelFontFamily:"arial",labelFontColor:"black",labelFontSize:12,labelFontWeight:"normal",labelFontStyle:"normal",labelAutoFit:!0,labelWrap:!0,labelMaxWidth:null,labelFormatter:null,labelBackgroundColor:t?"transparent":null,labelBorderColor:t?"transparent":null,labelBorderThickness:0,labelCornerRadius:0,prefix:"",suffix:"",includeZero:!0,tickLength:5,tickColor:"black",tickThickness:1,lineColor:"black",
|
||||
lineThickness:1,lineDashType:"solid",gridColor:"A0A0A0",gridThickness:0,gridDashType:"solid",interlacedColor:t?"transparent":null,valueFormatString:null,margin:2,stripLines:[],publicProperties:{options:"readWrite",bounds:"readOnly",chart:"readOnly"}},StripLine:{value:null,startValue:null,endValue:null,color:"orange",opacity:null,thickness:2,lineDashType:"solid",label:"",labelPlacement:"inside",labelAlign:"far",labelWrap:!0,labelMaxWidth:null,labelBackgroundColor:t?"transparent":null,labelBorderColor:t?
|
||||
"transparent":null,labelBorderThickness:0,labelCornerRadius:0,labelFontFamily:"arial",labelFontColor:"orange",labelFontSize:12,labelFontWeight:"normal",labelFontStyle:"normal",labelFormatter:null,showOnTop:!1,publicProperties:{options:"readWrite",axis:"readOnly",bounds:"readOnly",chart:"readOnly"}},DataSeries:{name:null,dataPoints:null,label:"",bevelEnabled:!1,highlightEnabled:!0,cursor:"default",indexLabel:"",indexLabelPlacement:"auto",indexLabelOrientation:"horizontal",indexLabelFontColor:"black",
|
||||
indexLabelFontSize:12,indexLabelFontStyle:"normal",indexLabelFontFamily:"Arial",indexLabelFontWeight:"normal",indexLabelBackgroundColor:null,indexLabelLineColor:"gray",indexLabelLineThickness:1,indexLabelLineDashType:"solid",indexLabelMaxWidth:null,indexLabelWrap:!0,indexLabelFormatter:null,lineThickness:2,lineDashType:"solid",connectNullData:!1,nullDataLineDashType:"dash",color:null,lineColor:null,risingColor:"white",fillOpacity:null,startAngle:0,radius:null,innerRadius:null,type:"column",xValueType:"number",
|
||||
axisXType:"primary",axisYType:"primary",axisXIndex:0,axisYIndex:0,xValueFormatString:null,yValueFormatString:null,zValueFormatString:null,percentFormatString:null,showInLegend:null,legendMarkerType:null,legendMarkerColor:null,legendText:null,legendMarkerBorderColor:t?"transparent":null,legendMarkerBorderThickness:0,markerType:"circle",markerColor:null,markerSize:null,markerBorderColor:t?"transparent":null,markerBorderThickness:0,mouseover:null,mouseout:null,mousemove:null,click:null,toolTipContent:null,
|
||||
visible:!0,publicProperties:{options:"readWrite",axisX:"readWrite",axisY:"readWrite",chart:"readOnly"}},TextBlock:{x:0,y:0,width:null,height:null,maxWidth:null,maxHeight:null,padding:0,angle:0,text:"",horizontalAlign:"center",fontSize:12,fontFamily:"calibri",fontWeight:"normal",fontColor:"black",fontStyle:"normal",borderThickness:0,borderColor:"black",cornerRadius:0,backgroundColor:null,textBaseline:"top"},CultureInfo:{decimalSeparator:".",digitGroupSeparator:",",zoomText:"Zoom",panText:"Pan",resetText:"Reset",
|
||||
menuText:"More Options",saveJPGText:"Save as JPEG",savePNGText:"Save as PNG",printText:"Print",days:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),shortDays:"Sun Mon Tue Wed Thu Fri Sat".split(" "),months:"January February March April May June July August September October November December".split(" "),shortMonths:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" ")}},ra={en:{}},ja={colorSet1:"#369EAD #C24642 #7F6084 #86B402 #A2D1CF #C8B631 #6DBCEB #52514E #4F81BC #A064A1 #F79647".split(" "),
|
||||
colorSet2:"#4F81BC #C0504E #9BBB58 #23BFAA #8064A1 #4AACC5 #F79647 #33558B".split(" "),colorSet3:"#8CA1BC #36845C #017E82 #8CB9D0 #708C98 #94838D #F08891 #0366A7 #008276 #EE7757 #E5BA3A #F2990B #03557B #782970".split(" ")},ka={theme1:{Chart:{colorSet:"colorSet1"},Title:{fontFamily:t?"Calibri, Optima, Candara, Verdana, Geneva, sans-serif":"calibri",fontSize:33,fontColor:"#3A3A3A",fontWeight:"bold",verticalAlign:"top",margin:5},Subtitle:{fontFamily:t?"Calibri, Optima, Candara, Verdana, Geneva, sans-serif":
|
||||
"calibri",fontSize:16,fontColor:"#3A3A3A",fontWeight:"bold",verticalAlign:"top",margin:5},Axis:{titleFontSize:26,titleFontColor:"#666666",titleFontFamily:t?"Calibri, Optima, Candara, Verdana, Geneva, sans-serif":"calibri",labelFontFamily:t?"Calibri, Optima, Candara, Verdana, Geneva, sans-serif":"calibri",labelFontSize:18,labelFontColor:"grey",tickColor:"#BBBBBB",tickThickness:2,gridThickness:2,gridColor:"#BBBBBB",lineThickness:2,lineColor:"#BBBBBB"},Legend:{verticalAlign:"bottom",horizontalAlign:"center",
|
||||
fontFamily:t?"monospace, sans-serif,arial black":"calibri"},DataSeries:{indexLabelFontColor:"grey",indexLabelFontFamily:t?"Calibri, Optima, Candara, Verdana, Geneva, sans-serif":"calibri",indexLabelFontSize:18,indexLabelLineThickness:1}},theme2:{Chart:{colorSet:"colorSet2"},Title:{fontFamily:"impact, charcoal, arial black, sans-serif",fontSize:32,fontColor:"#333333",verticalAlign:"top",margin:5},Subtitle:{fontFamily:"impact, charcoal, arial black, sans-serif",fontSize:14,fontColor:"#333333",verticalAlign:"top",
|
||||
margin:5},Axis:{titleFontSize:22,titleFontColor:"rgb(98,98,98)",titleFontFamily:t?"monospace, sans-serif,arial black":"arial",titleFontWeight:"bold",labelFontFamily:t?"monospace, Courier New, Courier":"arial",labelFontSize:16,labelFontColor:"grey",labelFontWeight:"bold",tickColor:"grey",tickThickness:2,gridThickness:2,gridColor:"grey",lineColor:"grey",lineThickness:0},Legend:{verticalAlign:"bottom",horizontalAlign:"center",fontFamily:t?"monospace, sans-serif,arial black":"arial"},DataSeries:{indexLabelFontColor:"grey",
|
||||
indexLabelFontFamily:t?"Courier New, Courier, monospace":"arial",indexLabelFontWeight:"bold",indexLabelFontSize:18,indexLabelLineThickness:1}},theme3:{Chart:{colorSet:"colorSet1"},Title:{fontFamily:t?"Candara, Optima, Trebuchet MS, Helvetica Neue, Helvetica, Trebuchet MS, serif":"calibri",fontSize:32,fontColor:"#3A3A3A",fontWeight:"bold",verticalAlign:"top",margin:5},Subtitle:{fontFamily:t?"Candara, Optima, Trebuchet MS, Helvetica Neue, Helvetica, Trebuchet MS, serif":"calibri",fontSize:16,fontColor:"#3A3A3A",
|
||||
fontWeight:"bold",verticalAlign:"top",margin:5},Axis:{titleFontSize:22,titleFontColor:"rgb(98,98,98)",titleFontFamily:t?"Verdana, Geneva, Calibri, sans-serif":"calibri",labelFontFamily:t?"Calibri, Optima, Candara, Verdana, Geneva, sans-serif":"calibri",labelFontSize:18,labelFontColor:"grey",tickColor:"grey",tickThickness:2,gridThickness:2,gridColor:"grey",lineThickness:2,lineColor:"grey"},Legend:{verticalAlign:"bottom",horizontalAlign:"center",fontFamily:t?"monospace, sans-serif,arial black":"calibri"},
|
||||
DataSeries:{bevelEnabled:!0,indexLabelFontColor:"grey",indexLabelFontFamily:t?"Candara, Optima, Calibri, Verdana, Geneva, sans-serif":"calibri",indexLabelFontSize:18,indexLabelLineColor:"lightgrey",indexLabelLineThickness:2}}},G={numberDuration:1,yearDuration:314496E5,monthDuration:2592E6,weekDuration:6048E5,dayDuration:864E5,hourDuration:36E5,minuteDuration:6E4,secondDuration:1E3,millisecondDuration:1,dayOfWeekFromInt:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" ")};(function(){I.fSDec=
|
||||
function(a){for(var c="",b=0;b<a.length;b++)c+=String.fromCharCode(Math.ceil(a.length/57/5)^a.charCodeAt(b));return c};I.obj={trVs:"Ush`m!Wdsrhno",fntStr:"qy!B`mhcsh-!Mtbhe`!Fs`oed-!Mtbhe`!R`or!Tohbned-!@sh`m-!r`or,rdshg",txtBl:"udyuC`rdmhod",fnt:"gnou",fSy:"ghmmRuxmd",fTx:"ghmmUdyu",grClr:"fsdx",cntx:"buy",tp:"unq"};delete ea[I.fSDec("Bi`su")][I.fSDec("bsdehuIsdg")];I.pro={sCH:ea[I.fSDec("Bi`su")][I.fSDec("bsdehuIsdg")]};I._fTWm=function(a){if("undefined"===typeof I.pro.sCH&&!Pa)try{var c=a[I.fSDec(I.obj.cntx)];
|
||||
c[I.fSDec(I.obj.txtBl)]=I.fSDec(I.obj.tp);c[I.fSDec(I.obj.fnt)]=11+I.fSDec(I.obj.fntStr);c[I.fSDec(I.obj.fSy)]=I.fSDec(I.obj.grClr);c[I.fSDec(I.obj.fTx)](I.fSDec(I.obj.trVs),2,a.height-11-2)}catch(b){}}})();var Ma={},da=null,Fa=function(){var a=/D{1,4}|M{1,4}|Y{1,4}|h{1,2}|H{1,2}|m{1,2}|s{1,2}|f{1,3}|t{1,2}|T{1,2}|K|z{1,3}|"[^"]*"|'[^']*'/g,c="Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),b="Sun Mon Tue Wed Thu Fri Sat".split(" "),d="January February March April May June July August September October November December".split(" "),
|
||||
f="Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),g=/\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,l=/[^-+\dA-Z]/g;return function(k,h,m){var p=m?m.days:c,n=m?m.months:d,e=m?m.shortDays:b,q=m?m.shortMonths:f;m="";var r=!1;k=k&&k.getTime?k:k?new Date(k):new Date;if(isNaN(k))throw SyntaxError("invalid date");"UTC:"===h.slice(0,4)&&(h=h.slice(4),r=!0);m=r?"getUTC":"get";var s=k[m+"Date"](),x=k[m+"Day"](),
|
||||
u=k[m+"Month"](),v=k[m+"FullYear"](),z=k[m+"Hours"](),w=k[m+"Minutes"](),t=k[m+"Seconds"](),y=k[m+"Milliseconds"](),A=r?0:k.getTimezoneOffset();return m=h.replace(a,function(a){switch(a){case "D":return s;case "DD":return P(s,2);case "DDD":return e[x];case "DDDD":return p[x];case "M":return u+1;case "MM":return P(u+1,2);case "MMM":return q[u];case "MMMM":return n[u];case "Y":return parseInt(String(v).slice(-2));case "YY":return P(String(v).slice(-2),2);case "YYY":return P(String(v).slice(-3),3);case "YYYY":return P(v,
|
||||
4);case "h":return z%12||12;case "hh":return P(z%12||12,2);case "H":return z;case "HH":return P(z,2);case "m":return w;case "mm":return P(w,2);case "s":return t;case "ss":return P(t,2);case "f":return String(y).slice(0,1);case "ff":return P(String(y).slice(0,2),2);case "fff":return P(String(y).slice(0,3),3);case "t":return 12>z?"a":"p";case "tt":return 12>z?"am":"pm";case "T":return 12>z?"A":"P";case "TT":return 12>z?"AM":"PM";case "K":return r?"UTC":(String(k).match(g)||[""]).pop().replace(l,"");
|
||||
case "z":return(0<A?"-":"+")+Math.floor(Math.abs(A)/60);case "zz":return(0<A?"-":"+")+P(Math.floor(Math.abs(A)/60),2);case "zzz":return(0<A?"-":"+")+P(Math.floor(Math.abs(A)/60),2)+P(Math.abs(A)%60,2);default:return a.slice(1,a.length-1)}})}}(),fa=function(a,c,b){if(null===a)return"";a=Number(a);var d=0>a?!0:!1;d&&(a*=-1);var f=b?b.decimalSeparator:".",g=b?b.digitGroupSeparator:",",l="";c=String(c);var l=1,k=b="",h=-1,m=[],p=[],n=0,e=0,q=0,r=!1,s=0,k=c.match(/"[^"]*"|'[^']*'|[eE][+-]*[0]+|[,]+[.]|\u2030|./g);
|
||||
c=null;for(var x=0;k&&x<k.length;x++)if(c=k[x],"."===c&&0>h)h=x;else{if("%"===c)l*=100;else if("\u2030"===c){l*=1E3;continue}else if(","===c[0]&&"."===c[c.length-1]){l/=Math.pow(1E3,c.length-1);h=x+c.length-1;continue}else"E"!==c[0]&&"e"!==c[0]||"0"!==c[c.length-1]||(r=!0);0>h?(m.push(c),"#"===c||"0"===c?n++:","===c&&q++):(p.push(c),"#"!==c&&"0"!==c||e++)}r&&(c=Math.floor(a),k=-Math.floor(Math.log(a)/Math.LN10+1),s=0===a?0:0===c?-(n+k):String(c).length-n,l/=Math.pow(10,s));0>h&&(h=x);l=(a*l).toFixed(e);
|
||||
c=l.split(".");l=(c[0]+"").split("");a=(c[1]+"").split("");l&&"0"===l[0]&&l.shift();for(r=k=x=e=h=0;0<m.length;)if(c=m.pop(),"#"===c||"0"===c)if(h++,h===n){var u=l,l=[];if("0"===c)for(c=n-e-(u?u.length:0);0<c;)u.unshift("0"),c--;for(;0<u.length;)b=u.pop()+b,r++,0===r%k&&(x===q&&0<u.length)&&(b=g+b)}else 0<l.length?(b=l.pop()+b,e++,r++):"0"===c&&(b="0"+b,e++,r++),0===r%k&&(x===q&&0<l.length)&&(b=g+b);else"E"!==c[0]&&"e"!==c[0]||"0"!==c[c.length-1]||!/[eE][+-]*[0]+/.test(c)?","===c?(x++,k=r,r=0,0<l.length&&
|
||||
(b=g+b)):b=1<c.length&&('"'===c[0]&&'"'===c[c.length-1]||"'"===c[0]&&"'"===c[c.length-1])?c.slice(1,c.length-1)+b:c+b:(c=0>s?c.replace("+","").replace("-",""):c.replace("-",""),b+=c.replace(/[0]+/,function(a){return P(s,a.length)}));g="";for(m=!1;0<p.length;)c=p.shift(),"#"===c||"0"===c?0<a.length&&0!==Number(a.join(""))?(g+=a.shift(),m=!0):"0"===c&&(g+="0",m=!0):1<c.length&&('"'===c[0]&&'"'===c[c.length-1]||"'"===c[0]&&"'"===c[c.length-1])?g+=c.slice(1,c.length-1):"E"!==c[0]&&"e"!==c[0]||"0"!==c[c.length-
|
||||
1]||!/[eE][+-]*[0]+/.test(c)?g+=c:(c=0>s?c.replace("+","").replace("-",""):c.replace("-",""),g+=c.replace(/[0]+/,function(a){return P(s,a.length)}));b+=(m?f:"")+g;return d?"-"+b:b},za=function(a){var c=0,b=0;a=a||window.event;a.offsetX||0===a.offsetX?(c=a.offsetX,b=a.offsetY):a.layerX||0==a.layerX?(c=a.layerX,b=a.layerY):(c=a.pageX-a.target.offsetLeft,b=a.pageY-a.target.offsetTop);return{x:c,y:b}},Oa=!0,Ba=window.devicePixelRatio||1,ua=1,Q=Oa?Ba/ua:1,S=function(a){for(var c="",b=0;b<a.length;b++)c+=
|
||||
String.fromCharCode(Math.ceil(a.length/57/5)^a.charCodeAt(b));return c},Pa=window&&window[S("mnb`uhno")]&&window[S("mnb`uhno")].href&&window[S("mnb`uhno")].href.indexOf&&(-1!==window[S("mnb`uhno")].href.indexOf(S("b`ow`rkr/bnl"))||-1!==window[S("mnb`uhno")].href.indexOf(S("gdonqhy/bnl"))||-1!==window[S("mnb`uhno")].href.indexOf(S("gheemd"))),Wa={reset:{image:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAcCAYAAAAAwr0iAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAAAKRSURBVEiJrdY/iF1FFMfxzwnZrGISUSR/JLGIhoh/QiRNBLWxMLIWEkwbgiAoFgoW2mhlY6dgpY2IlRBRxBSKhSAKIklWJRYuMZKAhiyopAiaTY7FvRtmZ+/ed9/zHRjezLw5v/O9d86cuZGZpmURAfdn5o9DfdZNLXpjz+LziPgyIl6MiG0jPTJzZBuyDrP4BVm0P/AKbljTb4ToY/gGewYA7KyCl+1b3DUYANvwbiHw0gCAGRzBOzjTAXEOu0cC4Ch+r5x/HrpdrcZmvIDFSucMtnYCYC++6HmNDw8FKDT34ETrf639/azOr5vwRk/g5fbeuABtgC04XWk9VQLciMP4EH/3AFzErRNC7MXlQmsesSoHsGPE23hmEoBW+61K66HMXFmIMvN8myilXS36R01ub+KfYvw43ZXwYDX+AHP4BAci4pFJomfmr/ihmNofESsBImJGk7mlncrM45n5JPbhz0kAWpsv+juxaX21YIPmVJS2uNzJMS6ZNexC0d+I7fUWXLFyz2kSZlpWPvASlmqAf/FXNXf3FAF2F/1LuFifAlionB6dRuSI2IwHi6lzmXmp6xR8XY0fiIh7psAwh+3FuDkRHQVjl+a8lkXjo0kLUKH7XaV5oO86PmZ1FTzyP4K/XGl9v/zwfbW7BriiuETGCP5ch9bc9f97HF/vcFzCa5gdEPgWq+t/4v0V63oE1uF4h0DiFJ7HnSWMppDdh1dxtsPvJ2wcBNAKbsJXa0Ck5opdaBPsRNu/usba09i1KsaAVzmLt3sghrRjuK1Tf4xkegInxwy8gKf7dKMVH2QRsV5zXR/Cftyu+aKaKbbkQrsdH+PTzLzcqzkOQAVzM+7FHdiqqe2/YT4zF/t8S/sPmawyvC974vcAAAAASUVORK5CYII="},
|
||||
pan:{image:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAAAJVSURBVFiFvZe7a1RBGMV/x2hWI4JpfKCIiSBKOoOCkID/wP4BFqIIFkE02ChIiC8QDKlSiI3YqRBsBVGwUNAUdiIEUgjiAzQIIsuKJsfizsXr5t7d+8jmwLDfzHz3nLOzc7+ZxTZlGyDgZiWOCuJ9wH2gCUyuqQFgF/AGcKJNrYkBYBj40CIet+muGQi/96kM4WS7C/Tm5VUg7whJg8BkEGkCR4BDYfodsADUgP6wErO5iCtswsuJb32hdbXy8qzL5TIdmzJinHdZoZIBZcSFkGlAKs1Z3YCketZcBtouuaQNkrblMiBpBrhme7mAgU4wMCvpcFsDkq4C54DFVRTH9h+i6vlE0r5UA5ImgCuh28jB28iIs7BIVCOeStoZD64P4uPAjUTygKSx2FsK2TIwkugfk9Qkfd/E+yMWHQCeSRqx/R3gOp3LazfaS2C4B5gHDgD7U9x3E3uAH7KNpC3AHHAwTL4FHgM9GQ8vAaPA0dB/Abxqk2/gBLA9MXba9r1k/d4LfA3JtwueBeM58ucS+edXnAW23wP10N3advEi9CXizTnyN4bPS7Zn4sH/dq3t18AY4e1YLYSy3g/csj2VnFshZPuOpOeSKHCodUINuGj7YetE6je1PV9QoNPJ9StNHKodx7nRbiWrGHBGXAi5DUiqtQwtpcWK0Jubt8CltA5MEV1IfwO7+VffPwGfia5m34CT4bXujIIX0Qna1/cGMNqV/wUJE2czxD8CQ4X5Sl7Jz7SILwCDpbjKPBRMHAd+EtX4HWV5Spdc2w8kDQGPbH8py/MXMygM69/FKz4AAAAASUVORK5CYII="},
|
||||
zoom:{image:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAK6wAACusBgosNWgAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAAAMqSURBVFiFvdfbj91TFMDxz57U6GUEMS1aYzyMtCSSDhWjCZMInpAI3khE/QHtgzdRkXgSCS8SES9epKLi0oRKNETjRahREq2KS1stdRujtDPtbA97n5zdn9+5zJxTK9k5v3POXmt991p7r71+IcaoGwkhTOIebMRqzOBTvIG3Y4zTXRmqSoyx5cAKbMJOHMFJnMZ8/jyFaXyMR7G6nb1aH22cP4BvcBxziG3GKfyTIR9D6BYg1KUghPBCDveFlb/24Av8iuUYw41YVsz5G7uxKcZ4aMEpwGt5NY3V/YbHsQ6rcAHOw/kYxigewr5CZw4fYGxBKcCLOFEYehXrMdRhr5yLETxVScsOLOkKAPfn1TYMPIvLFrShUlS2FDZm8XRHACzFAWl3R2xbqPMCYhmeLCAOYEMngAczbcTvuHYxzguIy/FesR9e6gSwU/OoPYHBHgHgviIKX2Flq7k34KhmcVnbi/PC8JX4MgMcxb118wZwdz5aISscqx7VRcox7MrPQ7i+btIAJrAkf9+bI9EPmZY2IAxiTSuAldLq4Y9+AcSUh78KP0tbAcwU35cXMD1JCIFUoGiehlqAz6TNB1f1C0DK+0h+nsNPrQC2a4bqGmlD9kOGcWt+Po6pVgDvSxfJaSkFd4UQBvoAsBYbCoB3a2flM7slA0R8iyt6rAFDeDPbm8eOTpVwGD9qVq7nLbIaZnmksPU1JtsCZMXNmpdRxFasWITzh6Xj3LCzra1OxcD2QjHiGVzdpfORnMqZio2PcF23ABdJF1Np4BPptlyPi6WzPYBzpJZtHe7A6xW9cnyP8TqA//SEIYRL8Bxul7rihvwgtVn78WcGGZXa9HGd5TDujDHuOePXNiHdKjWgZX/YbsxLx/ktqbjVzTlcjUSnvI5JrdlUVp6WesZZ6R1hRrpq9+EVTGS9jTjYAuKIouGpbcurEkIYxC051KNSamazsc+xK8b4S0VnEi/j0hqTP+M27O258egQwZuzs7pI7Mf4WQXIEDc5s9sux+5+1Py2EmP8UOq6GvWhIScxfdYjUERiAt9Jd84J6a16zf8JEKT3yCm8g1UxRv8CC4pyRhzR1uUAAAAASUVORK5CYII="},
|
||||
menu:{image:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAgCAYAAAAbifjMAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAK6wAACusBgosNWgAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAAAAWdEVYdENyZWF0aW9uIFRpbWUAMDcvMTUvMTTPsvU0AAAAP0lEQVRIie2SMQoAIBDDUvH/X667g8sJJ9KOhYYOkW0qGaU1MPdC0vGSbV19EACo3YMPAFH5BUBUjsqfAPpVXtNgGDfxEDCtAAAAAElFTkSuQmCC"}};L.prototype.setOptions=function(a,c){if(ea[this._defaultsKey]){var b=ea[this._defaultsKey],d;for(d in b)"publicProperties"!==d&&b.hasOwnProperty(d)&&(this[d]=
|
||||
a&&d in a?a[d]:c&&d in c?c[d]:b[d])}};L.prototype.get=function(a){var c=ea[this._defaultsKey];if("options"===a)return this.options&&this.options._isPlaceholder?null:this.options;if(c.hasOwnProperty(a)||c.publicProperties&&c.publicProperties.hasOwnProperty(a))return this[a];window.console&&window.console.log('Property "'+a+"\" doesn't exist. Please check for typo.")};L.prototype.set=function(a,c,b){b="undefined"===typeof b?!0:b;var d=ea[this._defaultsKey];if("options"===a)this.createUserOptions(c);
|
||||
else if(d.hasOwnProperty(a)||d.publicProperties&&d.publicProperties.hasOwnProperty(a)&&"readWrite"===d.publicProperties[a])this.options._isPlaceholder&&this.createUserOptions(),this.options[a]=c;else{window.console&&(d.publicProperties&&d.publicProperties.hasOwnProperty(a)&&"readOnly"===d.publicProperties[a]?window.console.log('Property "'+a+'" is read-only.'):window.console.log('Property "'+a+"\" doesn't exist. Please check for typo."));return}b&&(this.chart||this).render()};L.prototype.addTo=function(a,
|
||||
c,b,d){d="undefined"===typeof d?!0:d;var f=ea[this._defaultsKey];f.hasOwnProperty(a)||f.publicProperties&&f.publicProperties.hasOwnProperty(a)&&"readWrite"===f.publicProperties[a]?(this.options._isPlaceholder&&this.createUserOptions(),"undefined"===typeof this.options[a]&&(this.options[a]=[]),a=this.options[a],b="undefined"===typeof b||null===b?a.length:b,a.splice(b,0,c),d&&(this.chart||this).render()):window.console&&(f.publicProperties&&f.publicProperties.hasOwnProperty(a)&&"readOnly"===f.publicProperties[a]?
|
||||
window.console.log('Property "'+a+'" is read-only.'):window.console.log('Property "'+a+"\" doesn't exist. Please check for typo."))};L.prototype.createUserOptions=function(a){if("undefined"!==typeof a||this.options._isPlaceholder)if(this.parent.options._isPlaceholder&&this.parent.createUserOptions(),this.isOptionsInArray){this.parent.options[this.optionsName]||(this.parent.options[this.optionsName]=[]);var c=this.parent.options[this.optionsName],b=c.length;this.options._isPlaceholder||(sa(c),b=c.indexOf(this.options));
|
||||
this.options="undefined"===typeof a?{}:a;c[b]=this.options}else this.options="undefined"===typeof a?{}:a,a=this.parent.options,this.optionsName?c=this.optionsName:(c=this._defaultsKey)&&0!==c.length?(b=c.charAt(0).toLowerCase(),1<c.length&&(b=b.concat(c.slice(1))),c=b):c=void 0,a[c]=this.options};L.prototype.remove=function(a){a="undefined"===typeof a?!0:a;if(this.isOptionsInArray){var c=this.parent.options[this.optionsName];sa(c);var b=c.indexOf(this.options);0<=b&&c.splice(b,1)}else delete this.parent.options[this.optionsName];
|
||||
a&&(this.chart||this).render()};L.prototype.updateOption=function(a){var c=ea[this._defaultsKey],b=this.options.theme?this.options.theme:this.chart&&this.chart.options.theme?this.chart.options.theme:"theme1",d={},f=this[a];b&&(ka[b]&&ka[b][this._defaultsKey])&&(d=ka[b][this._defaultsKey]);a in c&&(f=a in this.options?this.options[a]:d&&a in d?d[a]:c[a]);if(f===this[a])return!1;this[a]=f;return!0};L.prototype.trackChanges=function(a){if(!this.sessionVariables)throw"Session Variable Store not set";
|
||||
this.sessionVariables[a]=this.options[a]};L.prototype.isBeingTracked=function(a){this.options._oldOptions||(this.options._oldOptions={});return this.options._oldOptions[a]?!0:!1};L.prototype.hasOptionChanged=function(a){if(!this.sessionVariables)throw"Session Variable Store not set";return this.sessionVariables[a]!==this.options[a]};L.prototype.addEventListener=function(a,c,b){a&&c&&(this._eventListeners[a]=this._eventListeners[a]||[],this._eventListeners[a].push({context:b||this,eventHandler:c}))};
|
||||
L.prototype.removeEventListener=function(a,c){if(a&&c&&this._eventListeners[a])for(var b=this._eventListeners[a],d=0;d<b.length;d++)if(b[d].eventHandler===c){b[d].splice(d,1);break}};L.prototype.removeAllEventListeners=function(){this._eventListeners=[]};L.prototype.dispatchEvent=function(a,c,b){if(a&&this._eventListeners[a]){c=c||{};for(var d=this._eventListeners[a],f=0;f<d.length;f++)d[f].eventHandler.call(d[f].context,c)}"function"===typeof this[a]&&this[a].call(b||this.chart,c)};T(A,L);A.prototype.destroy=
|
||||
function(){var a=window,c=this.windowResizeHandler;a.removeEventListener?a.removeEventListener("resize",c):a.detachEvent&&a.detachEvent("onresize",c)};A.prototype._updateOptions=function(){var a=this;this.updateOption("width");this.updateOption("height");this.updateOption("dataPointWidth");this.updateOption("dataPointMinWidth");this.updateOption("dataPointMaxWidth");this.updateOption("interactivityEnabled");this.updateOption("theme");this.updateOption("colorSet")&&(this._selectedColorSet="undefined"!==
|
||||
typeof ja[this.colorSet]?ja[this.colorSet]:ja.colorSet1);this.updateOption("backgroundColor");this.backgroundColor||(this.backgroundColor="rgba(0,0,0,0)");this.updateOption("culture");this._cultureInfo=new qa(this.options.culture);this.updateOption("animationEnabled");this.animationEnabled=this.animationEnabled&&t;this.updateOption("animationDuration");this.updateOption("rangeChanging");this.updateOption("rangeChanged");this.updateOption("exportEnabled");this.updateOption("exportFileName");this.updateOption("zoomType");
|
||||
this.options.zoomEnabled?(this._zoomButton||(aa(this._zoomButton=document.createElement("button")),$(this,this._zoomButton,"pan"),this._toolBar.appendChild(this._zoomButton),J(this._zoomButton,"click",function(){a.zoomEnabled?(a.zoomEnabled=!1,a.panEnabled=!0,$(a,a._zoomButton,"zoom")):(a.zoomEnabled=!0,a.panEnabled=!1,$(a,a._zoomButton,"pan"));a.render()})),this._resetButton||(aa(this._resetButton=document.createElement("button")),$(this,this._resetButton,"reset"),this._toolBar.appendChild(this._resetButton),
|
||||
J(this._resetButton,"click",function(){a.toolTip.hide();a.zoomEnabled||a.panEnabled?(a.zoomEnabled=!0,a.panEnabled=!1,$(a,a._zoomButton,"pan"),a._defaultCursor="default",a.overlaidCanvas.style.cursor=a._defaultCursor):(a.zoomEnabled=!1,a.panEnabled=!1);if(a.sessionVariables.axisX)for(var b=0;b<a.sessionVariables.axisX.length;b++)a.sessionVariables.axisX[b].newViewportMinimum=null,a.sessionVariables.axisX[b].newViewportMaximum=null;if(a.sessionVariables.axisX2)for(b=0;b<a.sessionVariables.axisX2.length;b++)a.sessionVariables.axisX2[b].newViewportMinimum=
|
||||
null,a.sessionVariables.axisX2[b].newViewportMaximum=null;if(a.sessionVariables.axisY)for(b=0;b<a.sessionVariables.axisY.length;b++)a.sessionVariables.axisY[b].newViewportMinimum=null,a.sessionVariables.axisY[b].newViewportMaximum=null;if(a.sessionVariables.axisY2)for(b=0;b<a.sessionVariables.axisY2.length;b++)a.sessionVariables.axisY2[b].newViewportMinimum=null,a.sessionVariables.axisY2[b].newViewportMaximum=null;a.resetOverlayedCanvas();aa(a._zoomButton,a._resetButton);a._dispatchRangeEvent("rangeChanging",
|
||||
"reset");a.render();a._dispatchRangeEvent("rangeChanged","reset")}),this.overlaidCanvas.style.cursor=a._defaultCursor),this.zoomEnabled||this.panEnabled||(this._zoomButton?(a._zoomButton.getAttribute("state")===a._cultureInfo.zoomText?(this.panEnabled=!0,this.zoomEnabled=!1):(this.zoomEnabled=!0,this.panEnabled=!1),va(a._zoomButton,a._resetButton)):(this.zoomEnabled=!0,this.panEnabled=!1))):this.panEnabled=this.zoomEnabled=!1;this._menuButton?this.exportEnabled?va(this._menuButton):aa(this._menuButton):
|
||||
this.exportEnabled&&t&&(this._menuButton=document.createElement("button"),$(this,this._menuButton,"menu"),this._toolBar.appendChild(this._menuButton),J(this._menuButton,"click",function(){"none"!==a._dropdownMenu.style.display||a._dropDownCloseTime&&500>=(new Date).getTime()-a._dropDownCloseTime.getTime()||(a._dropdownMenu.style.display="block",a._menuButton.blur(),a._dropdownMenu.focus())},!0));if(!this._dropdownMenu&&this.exportEnabled&&t){this._dropdownMenu=document.createElement("div");this._dropdownMenu.setAttribute("tabindex",
|
||||
-1);this._dropdownMenu.style.cssText="position: absolute; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; cursor: pointer;right: 1px;top: 25px;min-width: 120px;outline: 0;border: 1px solid silver;font-size: 14px;font-family: Calibri, Verdana, sans-serif;padding: 5px 0px 5px 0px;text-align: left;background-color: #fff;line-height: 20px;box-shadow: 2px 2px 10px #888888;";a._dropdownMenu.style.display="none";this._toolBar.appendChild(this._dropdownMenu);J(this._dropdownMenu,
|
||||
"blur",function(){aa(a._dropdownMenu);a._dropDownCloseTime=new Date},!0);var c=document.createElement("div");c.style.cssText="padding: 2px 15px 2px 10px";c.innerHTML=this._cultureInfo.printText;this._dropdownMenu.appendChild(c);J(c,"mouseover",function(){this.style.backgroundColor="#EEEEEE"},!0);J(c,"mouseout",function(){this.style.backgroundColor="transparent"},!0);J(c,"click",function(){a.print();aa(a._dropdownMenu)},!0);c=document.createElement("div");c.style.cssText="padding: 2px 15px 2px 10px";
|
||||
c.innerHTML=this._cultureInfo.saveJPGText;this._dropdownMenu.appendChild(c);J(c,"mouseover",function(){this.style.backgroundColor="#EEEEEE"},!0);J(c,"mouseout",function(){this.style.backgroundColor="transparent"},!0);J(c,"click",function(){Ca(a.canvas,"jpeg",a.exportFileName);aa(a._dropdownMenu)},!0);c=document.createElement("div");c.style.cssText="padding: 2px 15px 2px 10px";c.innerHTML=this._cultureInfo.savePNGText;this._dropdownMenu.appendChild(c);J(c,"mouseover",function(){this.style.backgroundColor=
|
||||
"#EEEEEE"},!0);J(c,"mouseout",function(){this.style.backgroundColor="transparent"},!0);J(c,"click",function(){Ca(a.canvas,"png",a.exportFileName);aa(a._dropdownMenu)},!0)}"none"!==this._toolBar.style.display&&this._zoomButton&&(this.panEnabled?$(a,a._zoomButton,"zoom"):$(a,a._zoomButton,"pan"),a._resetButton.getAttribute("state")!==a._cultureInfo.resetText&&$(a,a._resetButton,"reset"));this.options.toolTip&&this.toolTip.options!==this.options.toolTip&&(this.toolTip.options=this.options.toolTip);for(var b in this.toolTip.options)this.toolTip.options.hasOwnProperty(b)&&
|
||||
this.toolTip.updateOption(b)};A.prototype._updateSize=function(){var a=0,c=0;this.options.width?a=this.width:this.width=a=0<this.container.clientWidth?this.container.clientWidth:this.width;this.options.height?c=this.height:this.height=c=0<this.container.clientHeight?this.container.clientHeight:this.height;return this.canvas.width!==a*Q||this.canvas.height!==c*Q?(ta(this.canvas,a,c),ta(this.overlaidCanvas,a,c),ta(this._eventManager.ghostCanvas,a,c),!0):!1};A.prototype._initialize=function(){this._animator?
|
||||
this._animator.cancelAllAnimations():this._animator=new Ea(this);this.removeAllEventListeners();this.disableToolTip=!1;this._axes=[];this.pieDoughnutClickHandler=null;this.animationRequestId&&this.cancelRequestAnimFrame.call(window,this.animationRequestId);this._updateOptions();this.animatedRender=t&&this.animationEnabled&&0===this.renderCount;this._updateSize();this.clearCanvas();this.ctx.beginPath();this.axisX=[];this.axisX2=[];this.axisY=[];this.axisY2=[];this._indexLabels=[];this._dataInRenderedOrder=
|
||||
[];this._events=[];this._eventManager&&this._eventManager.reset();this.plotInfo={axisPlacement:null,axisXValueType:null,plotTypes:[]};this.layoutManager=new la(0,0,this.width,this.height,2);this.plotArea.layoutManager&&this.plotArea.layoutManager.reset();this.data=[];var a=0;if(this.options.data)for(var c=0;c<this.options.data.length;c++)if(a++,!this.options.data[c].type||0<=A._supportedChartTypes.indexOf(this.options.data[c].type)){var b=new ca(this,this.options.data[c],a-1,++this._eventManager.lastObjectId);
|
||||
null===b.name&&(b.name="DataSeries "+a);null===b.color?1<this.options.data.length?(b._colorSet=[this._selectedColorSet[b.index%this._selectedColorSet.length]],b.color=this._selectedColorSet[b.index%this._selectedColorSet.length]):b._colorSet="line"===b.type||"stepLine"===b.type||"spline"===b.type||"area"===b.type||"stepArea"===b.type||"splineArea"===b.type||"stackedArea"===b.type||"stackedArea100"===b.type||"rangeArea"===b.type||"rangeSplineArea"===b.type||"candlestick"===b.type||"ohlc"===b.type?
|
||||
[this._selectedColorSet[0]]:this._selectedColorSet:b._colorSet=[b.color];null===b.markerSize&&(("line"===b.type||"stepLine"===b.type||"spline"===b.type||0<=b.type.toLowerCase().indexOf("area"))&&b.dataPoints&&b.dataPoints.length<this.width/16||"scatter"===b.type)&&(b.markerSize=8);"bubble"!==b.type&&"scatter"!==b.type||!b.dataPoints||(b.dataPoints.some?b.dataPoints.some(function(a){return a.x})&&b.dataPoints.sort(Ka):b.dataPoints.sort(Ka));this.data.push(b);var d=b.axisPlacement,f;"normal"===d?"xySwapped"===
|
||||
this.plotInfo.axisPlacement?f='You cannot combine "'+b.type+'" with bar chart':"none"===this.plotInfo.axisPlacement?f='You cannot combine "'+b.type+'" with pie chart':null===this.plotInfo.axisPlacement&&(this.plotInfo.axisPlacement="normal"):"xySwapped"===d?"normal"===this.plotInfo.axisPlacement?f='You cannot combine "'+b.type+'" with line, area, column or pie chart':"none"===this.plotInfo.axisPlacement?f='You cannot combine "'+b.type+'" with pie chart':null===this.plotInfo.axisPlacement&&(this.plotInfo.axisPlacement=
|
||||
"xySwapped"):"none"==d&&("normal"===this.plotInfo.axisPlacement?f='You cannot combine "'+b.type+'" with line, area, column or bar chart':"xySwapped"===this.plotInfo.axisPlacement?f='You cannot combine "'+b.type+'" with bar chart':null===this.plotInfo.axisPlacement&&(this.plotInfo.axisPlacement="none"));if(f&&window.console){window.console.log(f);return}}this._objectsInitialized=!0};A._supportedChartTypes=sa("line stepLine spline column area stepArea splineArea bar bubble scatter stackedColumn stackedColumn100 stackedBar stackedBar100 stackedArea stackedArea100 candlestick ohlc rangeColumn rangeBar rangeArea rangeSplineArea pie doughnut funnel".split(" "));
|
||||
A.prototype.render=function(a){a&&(this.options=a);this._initialize();Ua(this);Va(this);var c=[];for(a=0;a<this.data.length;a++)if("normal"===this.plotInfo.axisPlacement||"xySwapped"===this.plotInfo.axisPlacement){if(!this.data[a].axisYType||"primary"===this.data[a].axisYType)if(this.options.axisY&&0<this.options.axisY.length){if(!this.axisY.length)for(var b=0;b<this.options.axisY.length;b++)"normal"===this.plotInfo.axisPlacement?this._axes.push(this.axisY[b]=new B(this,this.options.axisY[b],"axisY",
|
||||
"left",b)):"xySwapped"===this.plotInfo.axisPlacement&&this._axes.push(this.axisY[b]=new B(this,this.options.axisY[b],"axisY","bottom",b));this.data[a].axisY=this.axisY[0<=this.data[a].axisYIndex&&this.data[a].axisYIndex<this.axisY.length?this.data[a].axisYIndex:0];this.axisY[0<=this.data[a].axisYIndex&&this.data[a].axisYIndex<this.axisY.length?this.data[a].axisYIndex:0].dataSeries.push(this.data[a])}else this.axisY.length||("normal"===this.plotInfo.axisPlacement?this._axes.push(this.axisY[0]=new B(this,
|
||||
this.options.axisY,"axisY","left",0)):"xySwapped"===this.plotInfo.axisPlacement&&this._axes.push(this.axisY[0]=new B(this,this.options.axisY,"axisY","bottom",0))),this.data[a].axisY=this.axisY[0],this.axisY[0].dataSeries.push(this.data[a]);if("secondary"===this.data[a].axisYType)if(this.options.axisY2&&0<this.options.axisY2.length){if(!this.axisY2.length)for(b=0;b<this.options.axisY2.length;b++)"normal"===this.plotInfo.axisPlacement?this._axes.push(this.axisY2[b]=new B(this,this.options.axisY2[b],
|
||||
"axisY","right",b)):"xySwapped"===this.plotInfo.axisPlacement&&this._axes.push(this.axisY2[b]=new B(this,this.options.axisY2[b],"axisY","top",b));this.data[a].axisY=this.axisY2[0<=this.data[a].axisYIndex&&this.data[a].axisYIndex<this.axisY2.length?this.data[a].axisYIndex:0];this.axisY2[0<=this.data[a].axisYIndex&&this.data[a].axisYIndex<this.axisY2.length?this.data[a].axisYIndex:0].dataSeries.push(this.data[a])}else this.axisY2.length||("normal"===this.plotInfo.axisPlacement?this._axes.push(this.axisY2[0]=
|
||||
new B(this,this.options.axisY2,"axisY","right",0)):"xySwapped"===this.plotInfo.axisPlacement&&this._axes.push(this.axisY2[0]=new B(this,this.options.axisY2,"axisY","top",0))),this.data[a].axisY=this.axisY2[0],this.axisY2[0].dataSeries.push(this.data[a]);if(!this.data[a].axisXType||"primary"===this.data[a].axisXType)if(this.options.axisX&&0<this.options.axisX.length){if(!this.axisX.length)for(b=0;b<this.options.axisX.length;b++)"normal"===this.plotInfo.axisPlacement?this._axes.push(this.axisX[b]=new B(this,
|
||||
this.options.axisX[b],"axisX","bottom",b)):"xySwapped"===this.plotInfo.axisPlacement&&this._axes.push(this.axisX[b]=new B(this,this.options.axisX[b],"axisX","left",b));this.data[a].axisX=this.axisX[0<=this.data[a].axisXIndex&&this.data[a].axisXIndex<this.axisX.length?this.data[a].axisXIndex:0];this.axisX[0<=this.data[a].axisXIndex&&this.data[a].axisXIndex<this.axisX.length?this.data[a].axisXIndex:0].dataSeries.push(this.data[a])}else this.axisX.length||("normal"===this.plotInfo.axisPlacement?this._axes.push(this.axisX[0]=
|
||||
new B(this,this.options.axisX,"axisX","bottom",0)):"xySwapped"===this.plotInfo.axisPlacement&&this._axes.push(this.axisX[0]=new B(this,this.options.axisX,"axisX","left",0))),this.data[a].axisX=this.axisX[0],this.axisX[0].dataSeries.push(this.data[a]);if("secondary"===this.data[a].axisXType)if(this.options.axisX2&&0<this.options.axisX2.length){if(!this.axisX2.length)for(b=0;b<this.options.axisX2.length;b++)"normal"===this.plotInfo.axisPlacement?this._axes.push(this.axisX2[b]=new B(this,this.options.axisX2[b],
|
||||
"axisX","top",b)):"xySwapped"===this.plotInfo.axisPlacement&&this._axes.push(this.axisX2[b]=new B(this,this.options.axisX2[b],"axisX","right",b));this.data[a].axisX=this.axisX2[0<=this.data[a].axisXIndex&&this.data[a].axisXIndex<this.axisX2.length?this.data[a].axisXIndex:0];this.axisX2[0<=this.data[a].axisXIndex&&this.data[a].axisXIndex<this.axisX2.length?this.data[a].axisXIndex:0].dataSeries.push(this.data[a])}else this.axisX2.length||("normal"===this.plotInfo.axisPlacement?this._axes.push(this.axisX2[0]=
|
||||
new B(this,this.options.axisX2,"axisX","top",0)):"xySwapped"===this.plotInfo.axisPlacement&&this._axes.push(this.axisX2[0]=new B(this,this.options.axisX2,"axisX","right",0))),this.data[a].axisX=this.axisX2[0],this.axisX2[0].dataSeries.push(this.data[a])}if(this.axisY){for(b=1;b<this.axisY.length;b++)"undefined"===typeof this.axisY[b].options.gridThickness&&(this.axisY[b].gridThickness=0);for(b=0;b<this.axisY.length-1;b++)"undefined"===typeof this.axisY[b].options.margin&&(this.axisY[b].margin=10)}if(this.axisY2){for(b=
|
||||
1;b<this.axisY2.length;b++)"undefined"===typeof this.axisY2[b].options.gridThickness&&(this.axisY2[b].gridThickness=0);for(b=0;b<this.axisY2.length-1;b++)"undefined"===typeof this.axisY2[b].options.margin&&(this.axisY2[b].margin=10)}this.axisY&&0<this.axisY.length&&(this.axisY2&&0<this.axisY2.length)&&(0<this.axisY[0].gridThickness&&"undefined"===typeof this.axisY2[0].options.gridThickness?this.axisY2[0].gridThickness=0:0<this.axisY2[0].gridThickness&&"undefined"===typeof this.axisY[0].options.gridThickness&&
|
||||
(this.axisY[0].gridThickness=0));if(this.axisX)for(b=0;b<this.axisX.length;b++)"undefined"===typeof this.axisX[b].options.gridThickness&&(this.axisX[b].gridThickness=0);if(this.axisX2)for(b=0;b<this.axisX2.length;b++)"undefined"===typeof this.axisX2[b].options.gridThickness&&(this.axisX2[b].gridThickness=0);this.axisX&&0<this.axisX.length&&(this.axisX2&&0<this.axisX2.length)&&(0<this.axisX[0].gridThickness&&"undefined"===typeof this.axisX2[0].options.gridThickness?this.axisX2[0].gridThickness=0:0<
|
||||
this.axisX2[0].gridThickness&&"undefined"===typeof this.axisX[0].options.gridThickness&&(this.axisX[0].gridThickness=0));b=!1;if(0<this._axes.length&&(this.zoomEnabled||this.panEnabled))for(a=0;a<this._axes.length;a++)if(null!==this._axes[a].viewportMinimum||null!==this._axes[a].viewportMaximum){b=!0;break}b?va(this._zoomButton,this._resetButton):(aa(this._zoomButton,this._resetButton),this.options.zoomEnabled&&(this.zoomEnabled=!0,this.panEnabled=!1));this._processData();this.options.title&&(this.title=
|
||||
new oa(this,this.options.title),this.title.dockInsidePlotArea?c.push(this.title):this.title.render());if(this.options.subtitles)for(this.subtitles=[],a=0;a<this.options.subtitles.length;a++)b=new xa(this,this.options.subtitles[a]),this.subtitles.push(b),b.dockInsidePlotArea?c.push(b):b.render();this.legend=new ya(this,this.options.legend);for(a=0;a<this.data.length;a++)(this.data[a].showInLegend||"pie"===this.data[a].type||"doughnut"===this.data[a].type)&&this.legend.dataSeries.push(this.data[a]);
|
||||
this.legend.dockInsidePlotArea?c.push(this.legend):this.legend.render();if("normal"===this.plotInfo.axisPlacement||"xySwapped"===this.plotInfo.axisPlacement)B.setLayoutAndRender(this.axisX,this.axisX2,this.axisY,this.axisY2,this.plotInfo.axisPlacement,this.layoutManager.getFreeSpace());else if("none"===this.plotInfo.axisPlacement)this.preparePlotArea();else return;for(a=0;a<c.length;a++)c[a].render();var d=[];if(this.animatedRender){var f=ia(this.width,this.height);f.getContext("2d").drawImage(this.canvas,
|
||||
0,0,this.width,this.height)}var c=this.ctx.miterLimit,g;this.ctx.miterLimit=3;for(a=0;a<this.plotInfo.plotTypes.length;a++)for(var l=this.plotInfo.plotTypes[a],k=0;k<l.plotUnits.length;k++){var h=l.plotUnits[k],m=null;h.targetCanvas=null;this.animatedRender&&(h.targetCanvas=ia(this.width,this.height),h.targetCanvasCtx=h.targetCanvas.getContext("2d"),g=h.targetCanvasCtx.miterLimit,h.targetCanvasCtx.miterLimit=3);"line"===h.type?m=this.renderLine(h):"stepLine"===h.type?m=this.renderStepLine(h):"spline"===
|
||||
h.type?m=this.renderSpline(h):"column"===h.type?m=this.renderColumn(h):"bar"===h.type?m=this.renderBar(h):"area"===h.type?m=this.renderArea(h):"stepArea"===h.type?m=this.renderStepArea(h):"splineArea"===h.type?m=this.renderSplineArea(h):"stackedColumn"===h.type?m=this.renderStackedColumn(h):"stackedColumn100"===h.type?m=this.renderStackedColumn100(h):"stackedBar"===h.type?m=this.renderStackedBar(h):"stackedBar100"===h.type?m=this.renderStackedBar100(h):"stackedArea"===h.type?m=this.renderStackedArea(h):
|
||||
"stackedArea100"===h.type?m=this.renderStackedArea100(h):"bubble"===h.type?m=m=this.renderBubble(h):"scatter"===h.type?m=this.renderScatter(h):"pie"===h.type?this.renderPie(h):"doughnut"===h.type?this.renderPie(h):"candlestick"===h.type?m=this.renderCandlestick(h):"ohlc"===h.type?m=this.renderCandlestick(h):"rangeColumn"===h.type?m=this.renderRangeColumn(h):"rangeBar"===h.type?m=this.renderRangeBar(h):"rangeArea"===h.type?m=this.renderRangeArea(h):"rangeSplineArea"===h.type&&(m=this.renderRangeSplineArea(h));
|
||||
for(b=0;b<h.dataSeriesIndexes.length;b++)this._dataInRenderedOrder.push(this.data[h.dataSeriesIndexes[b]]);this.animatedRender&&(h.targetCanvasCtx.miterLimit=g,m&&d.push(m))}this.ctx.miterLimit=c;this.animatedRender&&0<this._indexLabels.length&&(g=ia(this.width,this.height).getContext("2d"),d.push(this.renderIndexLabels(g)));var p=this;0<d.length?(p.disableToolTip=!0,p._animator.animate(200,p.animationDuration,function(a){p.ctx.clearRect(0,0,p.width,p.height);p.ctx.drawImage(f,0,0,Math.floor(p.width*
|
||||
Q),Math.floor(p.height*Q),0,0,p.width,p.height);for(var b=0;b<d.length;b++)m=d[b],1>a&&"undefined"!==typeof m.startTimePercent?a>=m.startTimePercent&&m.animationCallback(m.easingFunction(a-m.startTimePercent,0,1,1-m.startTimePercent),m):m.animationCallback(m.easingFunction(a,0,1,1),m);p.dispatchEvent("dataAnimationIterationEnd",{chart:p})},function(){d=[];for(var a=0;a<p.plotInfo.plotTypes.length;a++)for(var b=p.plotInfo.plotTypes[a],c=0;c<b.plotUnits.length;c++)b.plotUnits[c].targetCanvas=null;f=
|
||||
null;p.disableToolTip=!1})):(0<p._indexLabels.length&&p.renderIndexLabels(),p.dispatchEvent("dataAnimationIterationEnd",{chart:p}));this.attachPlotAreaEventHandlers();this.zoomEnabled||(this.panEnabled||!this._zoomButton||"none"===this._zoomButton.style.display)||aa(this._zoomButton,this._resetButton);this.toolTip._updateToolTip();this.renderCount++};A.prototype.attachPlotAreaEventHandlers=function(){this.attachEvent({context:this,chart:this,mousedown:this._plotAreaMouseDown,mouseup:this._plotAreaMouseUp,
|
||||
mousemove:this._plotAreaMouseMove,cursor:this.panEnabled?"move":"default",capture:!0,bounds:this.plotArea})};A.prototype.categoriseDataSeries=function(){for(var a="",c=0;c<this.data.length;c++)if(a=this.data[c],a.dataPoints&&(0!==a.dataPoints.length&&a.visible)&&0<=A._supportedChartTypes.indexOf(a.type)){for(var b=null,d=!1,f=null,g=!1,l=0;l<this.plotInfo.plotTypes.length;l++)if(this.plotInfo.plotTypes[l].type===a.type){d=!0;b=this.plotInfo.plotTypes[l];break}d||(b={type:a.type,totalDataSeries:0,
|
||||
plotUnits:[]},this.plotInfo.plotTypes.push(b));for(l=0;l<b.plotUnits.length;l++)if(b.plotUnits[l].axisYType===a.axisYType&&b.plotUnits[l].axisXType===a.axisXType&&b.plotUnits[l].axisYIndex===a.axisYIndex&&b.plotUnits[l].axisXIndex===a.axisXIndex){g=!0;f=b.plotUnits[l];break}g||(f={type:a.type,previousDataSeriesCount:0,index:b.plotUnits.length,plotType:b,axisXType:a.axisXType,axisYType:a.axisYType,axisYIndex:a.axisYIndex,axisXIndex:a.axisXIndex,axisY:"primary"===a.axisYType?this.axisY[0<=a.axisYIndex&&
|
||||
a.axisYIndex<this.axisY.length?a.axisYIndex:0]:this.axisY2[0<=a.axisYIndex&&a.axisYIndex<this.axisY2.length?a.axisYIndex:0],axisX:"primary"===a.axisXType?this.axisX[0<=a.axisXIndex&&a.axisXIndex<this.axisX.length?a.axisXIndex:0]:this.axisX2[0<=a.axisXIndex&&a.axisXIndex<this.axisX2.length?a.axisXIndex:0],dataSeriesIndexes:[],yTotals:[]},b.plotUnits.push(f));b.totalDataSeries++;f.dataSeriesIndexes.push(c);a.plotUnit=f}for(c=0;c<this.plotInfo.plotTypes.length;c++)for(b=this.plotInfo.plotTypes[c],l=
|
||||
a=0;l<b.plotUnits.length;l++)b.plotUnits[l].previousDataSeriesCount=a,a+=b.plotUnits[l].dataSeriesIndexes.length};A.prototype.assignIdToDataPoints=function(){for(var a=0;a<this.data.length;a++){var c=this.data[a];if(c.dataPoints)for(var b=c.dataPoints.length,d=0;d<b;d++)c.dataPointIds[d]=++this._eventManager.lastObjectId}};A.prototype._processData=function(){this.assignIdToDataPoints();this.categoriseDataSeries();for(var a=0;a<this.plotInfo.plotTypes.length;a++)for(var c=this.plotInfo.plotTypes[a],
|
||||
b=0;b<c.plotUnits.length;b++){var d=c.plotUnits[b];"line"===d.type||"stepLine"===d.type||"spline"===d.type||"column"===d.type||"area"===d.type||"stepArea"===d.type||"splineArea"===d.type||"bar"===d.type||"bubble"===d.type||"scatter"===d.type?this._processMultiseriesPlotUnit(d):"stackedColumn"===d.type||"stackedBar"===d.type||"stackedArea"===d.type?this._processStackedPlotUnit(d):"stackedColumn100"===d.type||"stackedBar100"===d.type||"stackedArea100"===d.type?this._processStacked100PlotUnit(d):"candlestick"!==
|
||||
d.type&&"ohlc"!==d.type&&"rangeColumn"!==d.type&&"rangeBar"!==d.type&&"rangeArea"!==d.type&&"rangeSplineArea"!==d.type||this._processMultiYPlotUnit(d)}};A.prototype._processMultiseriesPlotUnit=function(a){if(a.dataSeriesIndexes&&!(1>a.dataSeriesIndexes.length))for(var c=a.axisY.dataInfo,b=a.axisX.dataInfo,d,f,g=!1,l=0;l<a.dataSeriesIndexes.length;l++){var k=this.data[a.dataSeriesIndexes[l]],h=0,m=!1,p=!1,n;if("normal"===k.axisPlacement||"xySwapped"===k.axisPlacement)var e=a.axisX.sessionVariables.newViewportMinimum?
|
||||
a.axisX.sessionVariables.newViewportMinimum:this.options.axisX&&this.options.axisX.viewportMinimum?this.options.axisX.viewportMinimum:this.options.axisX&&this.options.axisX.minimum?this.options.axisX.minimum:a.axisX.logarithmic?0:-Infinity,q=a.axisX.sessionVariables.newViewportMaximum?a.axisX.sessionVariables.newViewportMaximum:this.options.axisX&&this.options.axisX.viewportMaximum?this.options.axisX.viewportMaximum:this.options.axisX&&this.options.axisX.maximum?this.options.axisX.maximum:Infinity;
|
||||
if(k.dataPoints[h].x&&k.dataPoints[h].x.getTime||"dateTime"===k.xValueType)g=!0;for(h=0;h<k.dataPoints.length;h++){"undefined"===typeof k.dataPoints[h].x&&(k.dataPoints[h].x=h+(a.axisX.logarithmic?1:0));k.dataPoints[h].x.getTime?(g=!0,d=k.dataPoints[h].x.getTime()):d=k.dataPoints[h].x;f=k.dataPoints[h].y;d<b.min&&(b.min=d);d>b.max&&(b.max=d);f<c.min&&"number"===typeof f&&(c.min=f);f>c.max&&"number"===typeof f&&(c.max=f);if(0<h){if(a.axisX.logarithmic){var r=d/k.dataPoints[h-1].x;1>r&&(r=1/r);b.minDiff>
|
||||
r&&1!==r&&(b.minDiff=r)}else r=d-k.dataPoints[h-1].x,0>r&&(r*=-1),b.minDiff>r&&0!==r&&(b.minDiff=r);null!==f&&null!==k.dataPoints[h-1].y&&(a.axisY.logarithmic?(r=f/k.dataPoints[h-1].y,1>r&&(r=1/r),c.minDiff>r&&1!==r&&(c.minDiff=r)):(r=f-k.dataPoints[h-1].y,0>r&&(r*=-1),c.minDiff>r&&0!==r&&(c.minDiff=r)))}if(d<e&&!m)null!==f&&(n=d);else{if(!m&&(m=!0,0<h)){h-=2;continue}if(d>q&&!p)p=!0;else if(d>q&&p)continue;k.dataPoints[h].label&&(a.axisX.labels[d]=k.dataPoints[h].label);d<b.viewPortMin&&(b.viewPortMin=
|
||||
d);d>b.viewPortMax&&(b.viewPortMax=d);null===f?b.viewPortMin===d&&n<d&&(b.viewPortMin=n):(f<c.viewPortMin&&"number"===typeof f&&(c.viewPortMin=f),f>c.viewPortMax&&"number"===typeof f&&(c.viewPortMax=f))}}this.plotInfo.axisXValueType=k.xValueType=g?"dateTime":"number"}};A.prototype._processStackedPlotUnit=function(a){if(a.dataSeriesIndexes&&!(1>a.dataSeriesIndexes.length)){for(var c=a.axisY.dataInfo,b=a.axisX.dataInfo,d,f,g=!1,l=[],k=[],h=Infinity,m=-Infinity,p=0;p<a.dataSeriesIndexes.length;p++){var n=
|
||||
this.data[a.dataSeriesIndexes[p]],e=0,q=!1,r=!1,s;if("normal"===n.axisPlacement||"xySwapped"===n.axisPlacement)var x=this.sessionVariables.axisX.newViewportMinimum?this.sessionVariables.axisX.newViewportMinimum:this.options.axisX&&this.options.axisX.viewportMinimum?this.options.axisX.viewportMinimum:this.options.axisX&&this.options.axisX.minimum?this.options.axisX.minimum:-Infinity,u=this.sessionVariables.axisX.newViewportMaximum?this.sessionVariables.axisX.newViewportMaximum:this.options.axisX&&
|
||||
this.options.axisX.viewportMaximum?this.options.axisX.viewportMaximum:this.options.axisX&&this.options.axisX.maximum?this.options.axisX.maximum:Infinity;if(n.dataPoints[e].x&&n.dataPoints[e].x.getTime||"dateTime"===n.xValueType)g=!0;for(e=0;e<n.dataPoints.length;e++){"undefined"===typeof n.dataPoints[e].x&&(n.dataPoints[e].x=e+(a.axisX.logarithmic?1:0));n.dataPoints[e].x.getTime?(g=!0,d=n.dataPoints[e].x.getTime()):d=n.dataPoints[e].x;f=y(n.dataPoints[e].y)?0:n.dataPoints[e].y;d<b.min&&(b.min=d);
|
||||
d>b.max&&(b.max=d);if(0<e){if(a.axisX.logarithmic){var v=d/n.dataPoints[e-1].x;1>v&&(v=1/v);b.minDiff>v&&1!==v&&(b.minDiff=v)}else v=d-n.dataPoints[e-1].x,0>v&&(v*=-1),b.minDiff>v&&0!==v&&(b.minDiff=v);null!==f&&null!==n.dataPoints[e-1].y&&(a.axisY.logarithmic?0<f&&(v=f/n.dataPoints[e-1].y,1>v&&(v=1/v),c.minDiff>v&&1!==v&&(c.minDiff=v)):(v=f-n.dataPoints[e-1].y,0>v&&(v*=-1),c.minDiff>v&&0!==v&&(c.minDiff=v)))}if(d<x&&!q)null!==n.dataPoints[e].y&&(s=d);else{if(!q&&(q=!0,0<e)){e-=2;continue}if(d>u&&
|
||||
!r)r=!0;else if(d>u&&r)continue;n.dataPoints[e].label&&(a.axisX.labels[d]=n.dataPoints[e].label);d<b.viewPortMin&&(b.viewPortMin=d);d>b.viewPortMax&&(b.viewPortMax=d);null===n.dataPoints[e].y?b.viewPortMin===d&&s<d&&(b.viewPortMin=s):(a.yTotals[d]=(a.yTotals[d]?a.yTotals[d]:0)+Math.abs(f),0<=f?l[d]?l[d]+=f:(l[d]=f,h=Math.min(f,h)):k[d]?k[d]+=f:(k[d]=f,m=Math.max(f,m)))}}this.plotInfo.axisXValueType=n.xValueType=g?"dateTime":"number"}for(e in l)l.hasOwnProperty(e)&&!isNaN(e)&&(a=l[e],a<c.min&&(c.min=
|
||||
Math.min(a,h)),a>c.max&&(c.max=a),e<b.viewPortMin||e>b.viewPortMax||(a<c.viewPortMin&&(c.viewPortMin=Math.min(a,h)),a>c.viewPortMax&&(c.viewPortMax=a)));for(e in k)k.hasOwnProperty(e)&&!isNaN(e)&&(a=k[e],a<c.min&&(c.min=a),a>c.max&&(c.max=Math.max(a,m)),e<b.viewPortMin||e>b.viewPortMax||(a<c.viewPortMin&&(c.viewPortMin=a),a>c.viewPortMax&&(c.viewPortMax=Math.max(a,m))))}};A.prototype._processStacked100PlotUnit=function(a){if(a.dataSeriesIndexes&&!(1>a.dataSeriesIndexes.length)){for(var c=a.axisY.dataInfo,
|
||||
b=a.axisX.dataInfo,d,f,g=!1,l=!1,k=!1,h=[],m=0;m<a.dataSeriesIndexes.length;m++){var p=this.data[a.dataSeriesIndexes[m]],n=0,e=!1,q=!1,r;if("normal"===p.axisPlacement||"xySwapped"===p.axisPlacement)var s=this.sessionVariables.axisX.newViewportMinimum?this.sessionVariables.axisX.newViewportMinimum:this.options.axisX&&this.options.axisX.viewportMinimum?this.options.axisX.viewportMinimum:this.options.axisX&&this.options.axisX.minimum?this.options.axisX.minimum:-Infinity,x=this.sessionVariables.axisX.newViewportMaximum?
|
||||
this.sessionVariables.axisX.newViewportMaximum:this.options.axisX&&this.options.axisX.viewportMaximum?this.options.axisX.viewportMaximum:this.options.axisX&&this.options.axisX.maximum?this.options.axisX.maximum:Infinity;if(p.dataPoints[n].x&&p.dataPoints[n].x.getTime||"dateTime"===p.xValueType)g=!0;for(n=0;n<p.dataPoints.length;n++){"undefined"===typeof p.dataPoints[n].x&&(p.dataPoints[n].x=n+(a.axisX.logarithmic?1:0));p.dataPoints[n].x.getTime?(g=!0,d=p.dataPoints[n].x.getTime()):d=p.dataPoints[n].x;
|
||||
f=y(p.dataPoints[n].y)?null:p.dataPoints[n].y;d<b.min&&(b.min=d);d>b.max&&(b.max=d);if(0<n){if(a.axisX.logarithmic){var u=d/p.dataPoints[n-1].x;1>u&&(u=1/u);b.minDiff>u&&1!==u&&(b.minDiff=u)}else u=d-p.dataPoints[n-1].x,0>u&&(u*=-1),b.minDiff>u&&0!==u&&(b.minDiff=u);y(f)||null===p.dataPoints[n-1].y||(a.axisY.logarithmic?0<f&&(u=f/p.dataPoints[n-1].y,1>u&&(u=1/u),c.minDiff>u&&1!==u&&(c.minDiff=u)):(u=f-p.dataPoints[n-1].y,0>u&&(u*=-1),c.minDiff>u&&0!==u&&(c.minDiff=u)))}if(d<s&&!e)null!==f&&(r=d);
|
||||
else{if(!e&&(e=!0,0<n)){n-=2;continue}if(d>x&&!q)q=!0;else if(d>x&&q)continue;p.dataPoints[n].label&&(a.axisX.labels[d]=p.dataPoints[n].label);d<b.viewPortMin&&(b.viewPortMin=d);d>b.viewPortMax&&(b.viewPortMax=d);null===f?b.viewPortMin===d&&r<d&&(b.viewPortMin=r):(a.yTotals[d]=(a.yTotals[d]?a.yTotals[d]:0)+Math.abs(f),0<=f?l=!0:0>f&&(k=!0),h[d]=h[d]?h[d]+Math.abs(f):Math.abs(f))}}this.plotInfo.axisXValueType=p.xValueType=g?"dateTime":"number"}a.axisY.logarithmic?(c.max=y(c.viewPortMax)?99*Math.pow(a.axisY.logarithmBase,
|
||||
-0.05):Math.max(c.viewPortMax,99*Math.pow(a.axisY.logarithmBase,-0.05)),c.min=y(c.viewPortMin)?1:Math.min(c.viewPortMin,1)):l&&!k?(c.max=y(c.viewPortMax)?99:Math.max(c.viewPortMax,99),c.min=y(c.viewPortMin)?1:Math.min(c.viewPortMin,1)):l&&k?(c.max=y(c.viewPortMax)?99:Math.max(c.viewPortMax,99),c.min=y(c.viewPortMin)?-99:Math.min(c.viewPortMin,-99)):!l&&k&&(c.max=y(c.viewPortMax)?-1:Math.max(c.viewPortMax,-1),c.min=y(c.viewPortMin)?-99:Math.min(c.viewPortMin,-99));c.viewPortMin=c.min;c.viewPortMax=
|
||||
c.max;a.dataPointYSums=h}};A.prototype._processMultiYPlotUnit=function(a){if(a.dataSeriesIndexes&&!(1>a.dataSeriesIndexes.length))for(var c=a.axisY.dataInfo,b=a.axisX.dataInfo,d,f,g,l,k=!1,h=0;h<a.dataSeriesIndexes.length;h++){var m=this.data[a.dataSeriesIndexes[h]],p=0,n=!1,e=!1,q,r,s;if("normal"===m.axisPlacement||"xySwapped"===m.axisPlacement)var x=this.sessionVariables.axisX.newViewportMinimum?this.sessionVariables.axisX.newViewportMinimum:this.options.axisX&&this.options.axisX.viewportMinimum?
|
||||
this.options.axisX.viewportMinimum:this.options.axisX&&this.options.axisX.minimum?this.options.axisX.minimum:-Infinity,u=this.sessionVariables.axisX.newViewportMaximum?this.sessionVariables.axisX.newViewportMaximum:this.options.axisX&&this.options.axisX.viewportMaximum?this.options.axisX.viewportMaximum:this.options.axisX&&this.options.axisX.maximum?this.options.axisX.maximum:Infinity;if(m.dataPoints[p].x&&m.dataPoints[p].x.getTime||"dateTime"===m.xValueType)k=!0;for(p=0;p<m.dataPoints.length;p++){"undefined"===
|
||||
typeof m.dataPoints[p].x&&(m.dataPoints[p].x=p+(a.axisX.logarithmic?1:0));m.dataPoints[p].x.getTime?(k=!0,d=m.dataPoints[p].x.getTime()):d=m.dataPoints[p].x;if((f=m.dataPoints[p].y)&&f.length){g=Math.min.apply(null,f);l=Math.max.apply(null,f);r=!0;for(var v=0;v<f.length;v++)null===f.k&&(r=!1);r&&(n||(s=q),q=d)}d<b.min&&(b.min=d);d>b.max&&(b.max=d);g<c.min&&(c.min=g);l>c.max&&(c.max=l);0<p&&(a.axisX.logarithmic?(r=d/m.dataPoints[p-1].x,1>r&&(r=1/r),b.minDiff>r&&1!==r&&(b.minDiff=r)):(r=d-m.dataPoints[p-
|
||||
1].x,0>r&&(r*=-1),b.minDiff>r&&0!==r&&(b.minDiff=r)),f&&(null!==f[0]&&m.dataPoints[p-1].y&&null!==m.dataPoints[p-1].y[0])&&(a.axisY.logarithmic?(r=f[0]/m.dataPoints[p-1].y[0],1>r&&(r=1/r),c.minDiff>r&&1!==r&&(c.minDiff=r)):(r=f[0]-m.dataPoints[p-1].y[0],0>r&&(r*=-1),c.minDiff>r&&0!==r&&(c.minDiff=r))));if(!(d<x)||n){if(!n&&(n=!0,0<p)){p-=2;q=s;continue}if(d>u&&!e)e=!0;else if(d>u&&e)continue;m.dataPoints[p].label&&(a.axisX.labels[d]=m.dataPoints[p].label);d<b.viewPortMin&&(b.viewPortMin=d);d>b.viewPortMax&&
|
||||
(b.viewPortMax=d);if(b.viewPortMin===d&&f)for(v=0;v<f.length;v++)if(null===f[v]&&q<d){b.viewPortMin=q;break}null===f?b.viewPortMin===d&&q<d&&(b.viewPortMin=q):(g<c.viewPortMin&&(c.viewPortMin=g),l>c.viewPortMax&&(c.viewPortMax=l))}}this.plotInfo.axisXValueType=m.xValueType=k?"dateTime":"number"}};A.prototype.getDataPointAtXY=function(a,c,b){b=b||!1;for(var d=[],f=this._dataInRenderedOrder.length-1;0<=f;f--){var g=null;(g=this._dataInRenderedOrder[f].getDataPointAtXY(a,c,b))&&d.push(g)}a=null;c=!1;
|
||||
for(b=0;b<d.length;b++)if("line"===d[b].dataSeries.type||"stepLine"===d[b].dataSeries.type||"area"===d[b].dataSeries.type||"stepArea"===d[b].dataSeries.type)if(f=K("markerSize",d[b].dataPoint,d[b].dataSeries)||8,d[b].distance<=f/2){c=!0;break}for(b=0;b<d.length;b++)c&&"line"!==d[b].dataSeries.type&&"stepLine"!==d[b].dataSeries.type&&"area"!==d[b].dataSeries.type&&"stepArea"!==d[b].dataSeries.type||(a?d[b].distance<=a.distance&&(a=d[b]):a=d[b]);return a};A.prototype.getObjectAtXY=function(a,c,b){var d=
|
||||
null;if(b=this.getDataPointAtXY(a,c,b||!1))d=b.dataSeries.dataPointIds[b.dataPointIndex];else if(t)d=Na(a,c,this._eventManager.ghostCtx);else for(b=0;b<this.legend.items.length;b++){var f=this.legend.items[b];a>=f.x1&&(a<=f.x2&&c>=f.y1&&c<=f.y2)&&(d=f.id)}return d};A.prototype.getAutoFontSize=function(a,c,b){a/=400;return Math.max(10,Math.round(Math.min(this.width,this.height)*a))};A.prototype.resetOverlayedCanvas=function(){this.overlaidCanvasCtx.clearRect(0,0,this.width,this.height)};A.prototype.clearCanvas=
|
||||
function(){this.ctx.clearRect(0,0,this.width,this.height);this.backgroundColor&&(this.ctx.fillStyle=this.backgroundColor,this.ctx.fillRect(0,0,this.width,this.height))};A.prototype.attachEvent=function(a){this._events.push(a)};A.prototype._touchEventHandler=function(a){if(a.changedTouches&&this.interactivityEnabled){var c=[],b=a.changedTouches,d=b?b[0]:a,f=null;switch(a.type){case "touchstart":case "MSPointerDown":c=["mousemove","mousedown"];this._lastTouchData=za(d);this._lastTouchData.time=new Date;
|
||||
break;case "touchmove":case "MSPointerMove":c=["mousemove"];break;case "touchend":case "MSPointerUp":c="touchstart"===this._lastTouchEventType||"MSPointerDown"===this._lastTouchEventType?["mouseup","click"]:["mouseup"];break;default:return}if(!(b&&1<b.length)){f=za(d);f.time=new Date;try{var g=f.y-this._lastTouchData.y;if(15<Math.abs(g)&&this._lastTouchData.scroll){this._lastTouchData.scroll=!0;var l=window.parent||window;l&&l.scrollBy&&l.scrollBy(0,-g)}}catch(k){}this._lastTouchEventType=a.type;
|
||||
if(this._lastTouchData.scroll&&this.zoomEnabled)this.isDrag&&this.resetOverlayedCanvas(),this.isDrag=!1;else for(b=0;b<c.length;b++)f=c[b],g=document.createEvent("MouseEvent"),g.initMouseEvent(f,!0,!0,window,1,d.screenX,d.screenY,d.clientX,d.clientY,!1,!1,!1,!1,0,null),d.target.dispatchEvent(g),a.preventManipulation&&a.preventManipulation()}}};A.prototype._dispatchRangeEvent=function(a,c){var b={chart:this};b.type=a;b.trigger=c;var d=[];this.axisX&&0<this.axisX.length&&d.push("axisX");this.axisX2&&
|
||||
0<this.axisX2.length&&d.push("axisX2");this.axisY&&0<this.axisY.length&&d.push("axisY");this.axisY2&&0<this.axisY2.length&&d.push("axisY2");for(var f=0;f<d.length;f++)if(y(b[d[f]])&&(b[d[f]]=[]),"axisY"===d[f])for(var g=0;g<this.axisY.length;g++)b[d[f]].push({viewportMinimum:this[d[f]][g].sessionVariables.newViewportMinimum,viewportMaximum:this[d[f]][g].sessionVariables.newViewportMaximum});else if("axisY2"===d[f])for(g=0;g<this.axisY2.length;g++)b[d[f]].push({viewportMinimum:this[d[f]][g].sessionVariables.newViewportMinimum,
|
||||
viewportMaximum:this[d[f]][g].sessionVariables.newViewportMaximum});else if("axisX"===d[f])for(g=0;g<this.axisX.length;g++)b[d[f]].push({viewportMinimum:this[d[f]][g].sessionVariables.newViewportMinimum,viewportMaximum:this[d[f]][g].sessionVariables.newViewportMaximum});else if("axisX2"===d[f])for(g=0;g<this.axisX2.length;g++)b[d[f]].push({viewportMinimum:this[d[f]][g].sessionVariables.newViewportMinimum,viewportMaximum:this[d[f]][g].sessionVariables.newViewportMaximum});this.dispatchEvent(a,b,this)};
|
||||
A.prototype._mouseEventHandler=function(a){"undefined"===typeof a.target&&a.srcElement&&(a.target=a.srcElement);var c=za(a),b=a.type,d,f;a.which?f=3==a.which:a.button&&(f=2==a.button);A.capturedEventParam&&(d=A.capturedEventParam,"mouseup"===b&&(A.capturedEventParam=null,d.chart.overlaidCanvas.releaseCapture?d.chart.overlaidCanvas.releaseCapture():document.documentElement.removeEventListener("mouseup",d.chart._mouseEventHandler,!1)),d.hasOwnProperty(b)&&("mouseup"!==b||d.chart.overlaidCanvas.releaseCapture?
|
||||
a.target===d.chart.overlaidCanvas&&d[b].call(d.context,c.x,c.y):a.target!==d.chart.overlaidCanvas&&(d.chart.isDrag=!1)));if(this.interactivityEnabled)if(this._ignoreNextEvent)this._ignoreNextEvent=!1;else if(a.preventManipulation&&a.preventManipulation(),a.preventDefault&&a.preventDefault(),!f){if(!A.capturedEventParam&&this._events){for(var g=0;g<this._events.length;g++)if(this._events[g].hasOwnProperty(b))if(d=this._events[g],f=d.bounds,c.x>=f.x1&&c.x<=f.x2&&c.y>=f.y1&&c.y<=f.y2){d[b].call(d.context,
|
||||
c.x,c.y);"mousedown"===b&&!0===d.capture?(A.capturedEventParam=d,this.overlaidCanvas.setCapture?this.overlaidCanvas.setCapture():document.documentElement.addEventListener("mouseup",this._mouseEventHandler,!1)):"mouseup"===b&&(d.chart.overlaidCanvas.releaseCapture?d.chart.overlaidCanvas.releaseCapture():document.documentElement.removeEventListener("mouseup",this._mouseEventHandler,!1));break}else d=null;a.target.style.cursor=d&&d.cursor?d.cursor:this._defaultCursor}b=this.plotArea;if(c.x<b.x1||c.x>
|
||||
b.x2||c.y<b.y1||c.y>b.y2)this.toolTip&&this.toolTip.enabled?this.toolTip.hide():this.resetOverlayedCanvas();this.isDrag&&this.zoomEnabled||!this._eventManager||this._eventManager.mouseEventHandler(a)}};A.prototype._plotAreaMouseDown=function(a,c){this.isDrag=!0;this.dragStartPoint={x:a,y:c}};A.prototype._plotAreaMouseUp=function(a,c){if(("normal"===this.plotInfo.axisPlacement||"xySwapped"===this.plotInfo.axisPlacement)&&this.isDrag){var b=c-this.dragStartPoint.y,d=a-this.dragStartPoint.x,f=0<=this.zoomType.indexOf("x"),
|
||||
g=0<=this.zoomType.indexOf("y"),l=!1;this.resetOverlayedCanvas();if("xySwapped"===this.plotInfo.axisPlacement)var k=g,g=f,f=k;if(this.panEnabled||this.zoomEnabled){if(this.panEnabled)for(f=g=0;f<this._axes.length;f++)b=this._axes[f],b.logarithmic?b.viewportMinimum<b.minimum?(g=b.minimum/b.viewportMinimum,b.sessionVariables.newViewportMinimum=b.viewportMinimum*g,b.sessionVariables.newViewportMaximum=b.viewportMaximum*g,l=!0):b.viewportMaximum>b.maximum&&(g=b.viewportMaximum/b.maximum,b.sessionVariables.newViewportMinimum=
|
||||
b.viewportMinimum/g,b.sessionVariables.newViewportMaximum=b.viewportMaximum/g,l=!0):b.viewportMinimum<b.minimum?(g=b.minimum-b.viewportMinimum,b.sessionVariables.newViewportMinimum=b.viewportMinimum+g,b.sessionVariables.newViewportMaximum=b.viewportMaximum+g,l=!0):b.viewportMaximum>b.maximum&&(g=b.viewportMaximum-b.maximum,b.sessionVariables.newViewportMinimum=b.viewportMinimum-g,b.sessionVariables.newViewportMaximum=b.viewportMaximum-g,l=!0);else if((!f||2<Math.abs(d))&&(!g||2<Math.abs(b))&&this.zoomEnabled){if(!this.dragStartPoint)return;
|
||||
b=f?this.dragStartPoint.x:this.plotArea.x1;d=g?this.dragStartPoint.y:this.plotArea.y1;f=f?a:this.plotArea.x2;g=g?c:this.plotArea.y2;2<Math.abs(b-f)&&2<Math.abs(d-g)&&this._zoomPanToSelectedRegion(b,d,f,g)&&(l=!0)}l&&(this._ignoreNextEvent=!0,this._dispatchRangeEvent("rangeChanging","zoom"),this.render(),this._dispatchRangeEvent("rangeChanged","zoom"),l&&(this.zoomEnabled&&"none"===this._zoomButton.style.display)&&(va(this._zoomButton,this._resetButton),$(this,this._zoomButton,"pan"),$(this,this._resetButton,
|
||||
"reset")))}}this.isDrag=!1};A.prototype._plotAreaMouseMove=function(a,c){if(this.isDrag&&"none"!==this.plotInfo.axisPlacement){var b=0,d=0,f=b=null,f=0<=this.zoomType.indexOf("x"),g=0<=this.zoomType.indexOf("y"),l=this;"xySwapped"===this.plotInfo.axisPlacement&&(b=g,g=f,f=b);b=this.dragStartPoint.x-a;d=this.dragStartPoint.y-c;2<Math.abs(b)&&8>Math.abs(b)&&(this.panEnabled||this.zoomEnabled)?this.toolTip.hide():this.panEnabled||this.zoomEnabled||this.toolTip.mouseMoveHandler(a,c);if((!f||2<Math.abs(b)||
|
||||
!g||2<Math.abs(d))&&(this.panEnabled||this.zoomEnabled))if(this.panEnabled)f={x1:f?this.plotArea.x1+b:this.plotArea.x1,y1:g?this.plotArea.y1+d:this.plotArea.y1,x2:f?this.plotArea.x2+b:this.plotArea.x2,y2:g?this.plotArea.y2+d:this.plotArea.y2},clearTimeout(l._panTimerId),l._panTimerId=setTimeout(function(b,d,e,f){return function(){l._zoomPanToSelectedRegion(b,d,e,f,!0)&&(l._dispatchRangeEvent("rangeChanging","pan"),l.render(),l._dispatchRangeEvent("rangeChanged","pan"),l.dragStartPoint.x=a,l.dragStartPoint.y=
|
||||
c)}}(f.x1,f.y1,f.x2,f.y2),0);else if(this.zoomEnabled){this.resetOverlayedCanvas();b=this.overlaidCanvasCtx.globalAlpha;this.overlaidCanvasCtx.fillStyle="#A89896";var d=f?this.dragStartPoint.x:this.plotArea.x1,k=g?this.dragStartPoint.y:this.plotArea.y1,h=f?a-this.dragStartPoint.x:this.plotArea.x2-this.plotArea.x1,m=g?c-this.dragStartPoint.y:this.plotArea.y2-this.plotArea.y1;this.validateRegion(d,k,f?a:this.plotArea.x2-this.plotArea.x1,g?c:this.plotArea.y2-this.plotArea.y1,"xy"!==this.zoomType).isValid&&
|
||||
(this.resetOverlayedCanvas(),this.overlaidCanvasCtx.fillStyle="#99B2B5");this.overlaidCanvasCtx.globalAlpha=0.7;this.overlaidCanvasCtx.fillRect(d,k,h,m);this.overlaidCanvasCtx.globalAlpha=b}}else this.toolTip.mouseMoveHandler(a,c)};A.prototype._zoomPanToSelectedRegion=function(a,c,b,d,f){a=this.validateRegion(a,c,b,d,f);c=a.axesWithValidRange;b=a.axesRanges;if(a.isValid)for(d=0;d<c.length;d++)f=b[d],c[d].setViewPortRange(f.val1,f.val2);return a.isValid};A.prototype.validateRegion=function(a,c,b,d,
|
||||
f){f=f||!1;for(var g=0<=this.zoomType.indexOf("x"),l=0<=this.zoomType.indexOf("y"),k=!1,h=[],m=[],p=[],n=0;n<this.axisX.length;n++)this.axisX[n]&&g&&m.push(this.axisX[n]);for(n=0;n<this.axisX2.length;n++)this.axisX2[n]&&g&&m.push(this.axisX2[n]);for(n=0;n<this.axisY.length;n++)this.axisY[n]&&l&&m.push(this.axisY[n]);for(n=0;n<this.axisY2.length;n++)this.axisY2[n]&&l&&m.push(this.axisY2[n]);for(g=0;g<m.length;g++){var l=m[g],n=l.convertPixelToValue({x:a,y:c}),e=l.convertPixelToValue({x:b,y:d});if(n>
|
||||
e)var q=e,e=n,n=q;if(isFinite(l.dataInfo.minDiff))if(!(l.logarithmic&&e/n<Math.pow(l.dataInfo.minDiff,3)||!l.logarithmic&&Math.abs(e-n)<3*Math.abs(l.dataInfo.minDiff)||n<l.minimum||e>l.maximum))h.push(l),p.push({val1:n,val2:e}),k=!0;else if(!f){k=!1;break}}return{isValid:k,axesWithValidRange:h,axesRanges:p}};A.prototype.preparePlotArea=function(){var a=this.plotArea;!t&&(0<a.x1||0<a.y1)&&a.ctx.translate(a.x1,a.y1);if((this.axisX[0]||this.axisX2[0])&&(this.axisY[0]||this.axisY2[0])){var c=this.axisX[0]?
|
||||
this.axisX[0].lineCoordinates:this.axisX2[0].lineCoordinates;if(this.axisY&&0<this.axisY.length&&this.axisY[0]){var b=this.axisY[0];a.x1=c.x1<c.x2?c.x1:b.lineCoordinates.x1;a.y1=c.y1<b.lineCoordinates.y1?c.y1:b.lineCoordinates.y1;a.x2=c.x2>b.lineCoordinates.x2?c.x2:b.lineCoordinates.x2;a.y2=c.y2>c.y1?c.y2:b.lineCoordinates.y2;a.width=a.x2-a.x1;a.height=a.y2-a.y1}this.axisY2&&0<this.axisY2.length&&this.axisY2[0]&&(b=this.axisY2[0],a.x1=c.x1<c.x2?c.x1:b.lineCoordinates.x1,a.y1=c.y1<b.lineCoordinates.y1?
|
||||
c.y1:b.lineCoordinates.y1,a.x2=c.x2>b.lineCoordinates.x2?c.x2:b.lineCoordinates.x2,a.y2=c.y2>c.y1?c.y2:b.lineCoordinates.y2,a.width=a.x2-a.x1,a.height=a.y2-a.y1)}else c=this.layoutManager.getFreeSpace(),a.x1=c.x1,a.x2=c.x2,a.y1=c.y1,a.y2=c.y2,a.width=c.width,a.height=c.height;t||(a.canvas.width=a.width,a.canvas.height=a.height,a.canvas.style.left=a.x1+"px",a.canvas.style.top=a.y1+"px",(0<a.x1||0<a.y1)&&a.ctx.translate(-a.x1,-a.y1));a.layoutManager=new la(a.x1,a.y1,a.x2,a.y2,2)};A.prototype.renderIndexLabels=
|
||||
function(a){var c=a||this.plotArea.ctx,b=this.plotArea,d=0,f=0,g=0,l=0,k=d=l=f=g=0,h=0;for(a=0;a<this._indexLabels.length;a++){var m=this._indexLabels[a],p=m.chartType.toLowerCase(),n,e,k=K("indexLabelFontColor",m.dataPoint,m.dataSeries),h=K("indexLabelFontSize",m.dataPoint,m.dataSeries);n=K("indexLabelFontFamily",m.dataPoint,m.dataSeries);e=K("indexLabelFontStyle",m.dataPoint,m.dataSeries);var l=K("indexLabelFontWeight",m.dataPoint,m.dataSeries),q=K("indexLabelBackgroundColor",m.dataPoint,m.dataSeries),
|
||||
f=K("indexLabelMaxWidth",m.dataPoint,m.dataSeries),g=K("indexLabelWrap",m.dataPoint,m.dataSeries),r=K("indexLabelLineDashType",m.dataPoint,m.dataSeries),s=K("indexLabelLineColor",m.dataPoint,m.dataSeries),x=y(m.dataPoint.indexLabelLineThickness)?y(m.dataSeries.options.indexLabelLineThickness)?0:m.dataSeries.options.indexLabelLineThickness:m.dataPoint.indexLabelLineThickness,d=0<x?Math.min(10,("normal"===this.plotInfo.axisPlacement?this.plotArea.height:this.plotArea.width)<<0):0,u={percent:null,total:null},
|
||||
v=null;if(0<=m.dataSeries.type.indexOf("stacked")||"pie"===m.dataSeries.type||"doughnut"===m.dataSeries.type)u=this.getPercentAndTotal(m.dataSeries,m.dataPoint);if(m.dataSeries.indexLabelFormatter||m.dataPoint.indexLabelFormatter)v={chart:this,dataSeries:m.dataSeries,dataPoint:m.dataPoint,index:m.indexKeyword,total:u.total,percent:u.percent};var z=m.dataPoint.indexLabelFormatter?m.dataPoint.indexLabelFormatter(v):m.dataPoint.indexLabel?this.replaceKeywordsWithValue(m.dataPoint.indexLabel,m.dataPoint,
|
||||
m.dataSeries,null,m.indexKeyword):m.dataSeries.indexLabelFormatter?m.dataSeries.indexLabelFormatter(v):m.dataSeries.indexLabel?this.replaceKeywordsWithValue(m.dataSeries.indexLabel,m.dataPoint,m.dataSeries,null,m.indexKeyword):null;if(null!==z&&""!==z){var u=K("indexLabelPlacement",m.dataPoint,m.dataSeries),v=K("indexLabelOrientation",m.dataPoint,m.dataSeries),w=m.direction,Z=m.dataSeries.axisX,ba=m.dataSeries.axisY,A=!1,q=new V(c,{x:0,y:0,maxWidth:f?f:0.5*this.width,maxHeight:g?5*h:1.5*h,angle:"horizontal"===
|
||||
v?0:-90,text:z,padding:0,backgroundColor:q,horizontalAlign:"left",fontSize:h,fontFamily:n,fontWeight:l,fontColor:k,fontStyle:e,textBaseline:"top"});q.measureText();m.dataSeries.indexLabelMaxWidth=q.maxWidth;if("stackedarea100"===p){if(m.point.x<b.x1||m.point.x>b.x2||m.point.y<b.y1-1||m.point.y>b.y2+1)continue}else if("rangearea"===p||"rangesplinearea"===p){if(m.dataPoint.x<Z.viewportMinimum||m.dataPoint.x>Z.viewportMaximum||Math.max.apply(null,m.dataPoint.y)<ba.viewportMinimum||Math.min.apply(null,
|
||||
m.dataPoint.y)>ba.viewportMaximum)continue}else if(0<=p.indexOf("line")||0<=p.indexOf("area")||0<=p.indexOf("bubble")||0<=p.indexOf("scatter")){if(m.dataPoint.x<Z.viewportMinimum||m.dataPoint.x>Z.viewportMaximum||m.dataPoint.y<ba.viewportMinimum||m.dataPoint.y>ba.viewportMaximum)continue}else if(0<=p.indexOf("column")){if(m.dataPoint.x<Z.viewportMinimum||m.dataPoint.x>Z.viewportMaximum||m.bounds.y1>b.y2||m.bounds.y2<b.y1)continue}else if(0<=p.indexOf("bar")){if(m.dataPoint.x<Z.viewportMinimum||m.dataPoint.x>
|
||||
Z.viewportMaximum||m.bounds.x1>b.x2||m.bounds.x2<b.x1)continue}else if("candlestick"===p||"ohlc"===p){if(m.dataPoint.x<Z.viewportMinimum||m.dataPoint.x>Z.viewportMaximum||Math.max.apply(null,m.dataPoint.y)<ba.viewportMinimum||Math.min.apply(null,m.dataPoint.y)>ba.viewportMaximum)continue}else if(m.dataPoint.x<Z.viewportMinimum||m.dataPoint.x>Z.viewportMaximum)continue;f=l=2;"horizontal"===v?(k=q.width,h=q.height):(h=q.width,k=q.height);if("normal"===this.plotInfo.axisPlacement){if(0<=p.indexOf("line")||
|
||||
0<=p.indexOf("area"))u="auto",l=4;else if(0<=p.indexOf("stacked"))"auto"===u&&(u="inside");else if("bubble"===p||"scatter"===p)u="inside";n=m.point.x-k/2;"inside"!==u?(f=b.y1,g=b.y2,0<w?(e=m.point.y-h-l-d,e<f&&(e="auto"===u?Math.max(m.point.y,f)+l+d:f+l+d,A=e+h>m.point.y)):(e=m.point.y+l+d,e>g-h-l-d&&(e="auto"===u?Math.min(m.point.y,g)-h-l-d:g-h-l-d,A=e<m.point.y))):(f=Math.max(m.bounds.y1,b.y1),g=Math.min(m.bounds.y2,b.y2),d=0<=p.indexOf("range")?0<w?Math.max(m.bounds.y1,b.y1)+h/2+l:Math.min(m.bounds.y2,
|
||||
b.y2)-h/2-l:(Math.max(m.bounds.y1,b.y1)+Math.min(m.bounds.y2,b.y2))/2,0<w?(e=Math.max(m.point.y,d)-h/2,e<f&&("bubble"===p||"scatter"===p)&&(e=Math.max(m.point.y-h-l,b.y1+l))):(e=Math.min(m.point.y,d)-h/2,e>g-h-l&&("bubble"===p||"scatter"===p)&&(e=Math.min(m.point.y+l,b.y2-h-l))),e=Math.min(e,g-h))}else 0<=p.indexOf("line")||0<=p.indexOf("area")||0<=p.indexOf("scatter")?(u="auto",f=4):0<=p.indexOf("stacked")?"auto"===u&&(u="inside"):"bubble"===p&&(u="inside"),e=m.point.y-h/2,"inside"!==u?(l=b.x1,g=
|
||||
b.x2,0>w?(n=m.point.x-k-f-d,n<l&&(n="auto"===u?Math.max(m.point.x,l)+f+d:l+f+d,A=n+k>m.point.x)):(n=m.point.x+f+d,n>g-k-f-d&&(n="auto"===u?Math.min(m.point.x,g)-k-f-d:g-k-f-d,A=n<m.point.x))):(l=Math.max(m.bounds.x1,b.x1),Math.min(m.bounds.x2,b.x2),d=0<=p.indexOf("range")?0>w?Math.max(m.bounds.x1,b.x1)+k/2+f:Math.min(m.bounds.x2,b.x2)-k/2-f:(Math.max(m.bounds.x1,b.x1)+Math.min(m.bounds.x2,b.x2))/2,n=0>w?Math.max(m.point.x,d)-k/2:Math.min(m.point.x,d)-k/2,n=Math.max(n,l));"vertical"===v&&(e+=h);q.x=
|
||||
n;q.y=e;q.render(!0);x&&("inside"!==u&&(0>p.indexOf("bar")&&m.point.x>b.x1&&m.point.x<b.x2||!A)&&(0>p.indexOf("column")&&m.point.y>b.y1&&m.point.y<b.y2||!A))&&(c.lineWidth=x,c.strokeStyle=s?s:"gray",c.setLineDash&&c.setLineDash(F(r,x)),c.beginPath(),c.moveTo(m.point.x,m.point.y),0<=p.indexOf("bar")?c.lineTo(n+(0<m.direction?0:k),e+("horizontal"===v?h:-h)/2):0<=p.indexOf("column")?c.lineTo(n+k/2,e+((0<m.direction?h:-h)+("horizontal"===v?h:-h))/2):c.lineTo(n+k/2,e+((e<m.point.y?h:-h)+("horizontal"===
|
||||
v?h:-h))/2),c.stroke())}}c={source:c,dest:this.plotArea.ctx,animationCallback:E.fadeInAnimation,easingFunction:E.easing.easeInQuad,animationBase:0,startTimePercent:0.7};for(a=0;a<this._indexLabels.length;a++)m=this._indexLabels[a],q=K("indexLabelBackgroundColor",m.dataPoint,m.dataSeries),m.dataSeries.indexLabelBackgroundColor=y(q)?t?"transparent":null:q;return c};A.prototype.renderLine=function(a){var c=a.targetCanvasCtx||this.plotArea.ctx;if(!(0>=a.dataSeriesIndexes.length)){var b=this._eventManager.ghostCtx;
|
||||
c.save();var d=this.plotArea;c.beginPath();c.rect(d.x1,d.y1,d.width,d.height);c.clip();for(var d=[],f,g=0;g<a.dataSeriesIndexes.length;g++){var l=a.dataSeriesIndexes[g],k=this.data[l];c.lineWidth=k.lineThickness;var h=k.dataPoints,m="solid";if(c.setLineDash){var p=F(k.nullDataLineDashType,k.lineThickness),m=k.lineDashType,n=F(m,k.lineThickness);c.setLineDash(n)}var e=k.id;this._eventManager.objectMap[e]={objectType:"dataSeries",dataSeriesIndex:l};e=D(e);b.strokeStyle=e;b.lineWidth=0<k.lineThickness?
|
||||
Math.max(k.lineThickness,4):0;var e=k._colorSet,q=e=k.lineColor=k.options.lineColor?k.options.lineColor:e[0];c.strokeStyle=e;var r=!0,s=0,x,u;c.beginPath();if(0<h.length){for(var v=!1,s=0;s<h.length;s++)if(x=h[s].x.getTime?h[s].x.getTime():h[s].x,!(x<a.axisX.dataInfo.viewPortMin||x>a.axisX.dataInfo.viewPortMax&&(!k.connectNullData||!v)))if("number"!==typeof h[s].y)0<s&&!(k.connectNullData||v||r)&&(c.stroke(),t&&b.stroke()),v=!0;else{x=a.axisX.convertValueToPixel(x);u=a.axisY.convertValueToPixel(h[s].y);
|
||||
var z=k.dataPointIds[s];this._eventManager.objectMap[z]={id:z,objectType:"dataPoint",dataSeriesIndex:l,dataPointIndex:s,x1:x,y1:u};r||v?(!r&&k.connectNullData?(c.setLineDash&&(k.options.nullDataLineDashType||m===k.lineDashType&&k.lineDashType!==k.nullDataLineDashType)&&(c.stroke(),c.beginPath(),c.moveTo(f.x,f.y),m=k.nullDataLineDashType,c.setLineDash(p)),c.lineTo(x,u),t&&b.lineTo(x,u)):(c.beginPath(),c.moveTo(x,u),t&&(b.beginPath(),b.moveTo(x,u))),v=r=!1):(c.lineTo(x,u),t&&b.lineTo(x,u),0==s%500&&
|
||||
(c.stroke(),c.beginPath(),c.moveTo(x,u),t&&(b.stroke(),b.beginPath(),b.moveTo(x,u))));f={x:x,y:u};s<h.length-1&&(q!==(h[s].lineColor||e)||m!==(h[s].lineDashType||k.lineDashType))&&(c.stroke(),c.beginPath(),c.moveTo(x,u),q=h[s].lineColor||e,c.strokeStyle=q,c.setLineDash&&(h[s].lineDashType?(m=h[s].lineDashType,c.setLineDash(F(m,k.lineThickness))):(m=k.lineDashType,c.setLineDash(n))));if(0<h[s].markerSize||0<k.markerSize){var w=k.getMarkerProperties(s,x,u,c);d.push(w);z=D(z);t&&d.push({x:x,y:u,ctx:b,
|
||||
type:w.type,size:w.size,color:z,borderColor:z,borderThickness:w.borderThickness})}(h[s].indexLabel||k.indexLabel||h[s].indexLabelFormatter||k.indexLabelFormatter)&&this._indexLabels.push({chartType:"line",dataPoint:h[s],dataSeries:k,point:{x:x,y:u},direction:0>h[s].y===a.axisY.reversed?1:-1,color:e})}c.stroke();t&&b.stroke()}}O.drawMarkers(d);c.restore();c.beginPath();t&&b.beginPath();return{source:c,dest:this.plotArea.ctx,animationCallback:E.xClipAnimation,easingFunction:E.easing.linear,animationBase:0}}};
|
||||
A.prototype.renderStepLine=function(a){var c=a.targetCanvasCtx||this.plotArea.ctx;if(!(0>=a.dataSeriesIndexes.length)){var b=this._eventManager.ghostCtx;c.save();var d=this.plotArea;c.beginPath();c.rect(d.x1,d.y1,d.width,d.height);c.clip();for(var d=[],f,g=0;g<a.dataSeriesIndexes.length;g++){var l=a.dataSeriesIndexes[g],k=this.data[l];c.lineWidth=k.lineThickness;var h=k.dataPoints,m="solid";if(c.setLineDash){var p=F(k.nullDataLineDashType,k.lineThickness),m=k.lineDashType,n=F(m,k.lineThickness);c.setLineDash(n)}var e=
|
||||
k.id;this._eventManager.objectMap[e]={objectType:"dataSeries",dataSeriesIndex:l};e=D(e);b.strokeStyle=e;b.lineWidth=0<k.lineThickness?Math.max(k.lineThickness,4):0;var e=k._colorSet,q=e=k.lineColor=k.options.lineColor?k.options.lineColor:e[0];c.strokeStyle=e;var r=!0,s=0,x,u;c.beginPath();if(0<h.length){for(var v=!1,s=0;s<h.length;s++)if(x=h[s].getTime?h[s].x.getTime():h[s].x,!(x<a.axisX.dataInfo.viewPortMin||x>a.axisX.dataInfo.viewPortMax&&(!k.connectNullData||!v)))if("number"!==typeof h[s].y)0<
|
||||
s&&!(k.connectNullData||v||r)&&(c.stroke(),t&&b.stroke()),v=!0;else{var z=u;x=a.axisX.convertValueToPixel(x);u=a.axisY.convertValueToPixel(h[s].y);var w=k.dataPointIds[s];this._eventManager.objectMap[w]={id:w,objectType:"dataPoint",dataSeriesIndex:l,dataPointIndex:s,x1:x,y1:u};r||v?(!r&&k.connectNullData?(c.setLineDash&&(k.options.nullDataLineDashType||m===k.lineDashType&&k.lineDashType!==k.nullDataLineDashType)&&(c.stroke(),c.beginPath(),c.moveTo(f.x,f.y),m=k.nullDataLineDashType,c.setLineDash(p)),
|
||||
c.lineTo(x,z),c.lineTo(x,u),t&&(b.lineTo(x,z),b.lineTo(x,u))):(c.beginPath(),c.moveTo(x,u),t&&(b.beginPath(),b.moveTo(x,u))),v=r=!1):(c.lineTo(x,z),t&&b.lineTo(x,z),c.lineTo(x,u),t&&b.lineTo(x,u),0==s%500&&(c.stroke(),c.beginPath(),c.moveTo(x,u),t&&(b.stroke(),b.beginPath(),b.moveTo(x,u))));f={x:x,y:u};s<h.length-1&&(q!==(h[s].lineColor||e)||m!==(h[s].lineDashType||k.lineDashType))&&(c.stroke(),c.beginPath(),c.moveTo(x,u),q=h[s].lineColor||e,c.strokeStyle=q,c.setLineDash&&(h[s].lineDashType?(m=h[s].lineDashType,
|
||||
c.setLineDash(F(m,k.lineThickness))):(m=k.lineDashType,c.setLineDash(n))));if(0<h[s].markerSize||0<k.markerSize)z=k.getMarkerProperties(s,x,u,c),d.push(z),w=D(w),t&&d.push({x:x,y:u,ctx:b,type:z.type,size:z.size,color:w,borderColor:w,borderThickness:z.borderThickness});(h[s].indexLabel||k.indexLabel||h[s].indexLabelFormatter||k.indexLabelFormatter)&&this._indexLabels.push({chartType:"stepLine",dataPoint:h[s],dataSeries:k,point:{x:x,y:u},direction:0>h[s].y===a.axisY.reversed?1:-1,color:e})}c.stroke();
|
||||
t&&b.stroke()}}O.drawMarkers(d);c.restore();c.beginPath();t&&b.beginPath();return{source:c,dest:this.plotArea.ctx,animationCallback:E.xClipAnimation,easingFunction:E.easing.linear,animationBase:0}}};A.prototype.renderSpline=function(a){function c(a){a=wa(a,2);if(0<a.length){b.beginPath();t&&d.beginPath();b.moveTo(a[0].x,a[0].y);a[0].newStrokeStyle&&(b.strokeStyle=a[0].newStrokeStyle);a[0].newLineDashArray&&b.setLineDash(a[0].newLineDashArray);t&&d.moveTo(a[0].x,a[0].y);for(var c=0;c<a.length-3;c+=
|
||||
3)if(b.bezierCurveTo(a[c+1].x,a[c+1].y,a[c+2].x,a[c+2].y,a[c+3].x,a[c+3].y),t&&d.bezierCurveTo(a[c+1].x,a[c+1].y,a[c+2].x,a[c+2].y,a[c+3].x,a[c+3].y),0<c&&0===c%3E3||a[c+3].newStrokeStyle||a[c+3].newLineDashArray)b.stroke(),b.beginPath(),b.moveTo(a[c+3].x,a[c+3].y),a[c+3].newStrokeStyle&&(b.strokeStyle=a[c+3].newStrokeStyle),a[c+3].newLineDashArray&&b.setLineDash(a[c+3].newLineDashArray),t&&(d.stroke(),d.beginPath(),d.moveTo(a[c+3].x,a[c+3].y));b.stroke();t&&d.stroke()}}var b=a.targetCanvasCtx||this.plotArea.ctx;
|
||||
if(!(0>=a.dataSeriesIndexes.length)){var d=this._eventManager.ghostCtx;b.save();var f=this.plotArea;b.beginPath();b.rect(f.x1,f.y1,f.width,f.height);b.clip();for(var f=[],g=0;g<a.dataSeriesIndexes.length;g++){var l=a.dataSeriesIndexes[g],k=this.data[l];b.lineWidth=k.lineThickness;var h=k.dataPoints,m="solid";if(b.setLineDash){var p=F(k.nullDataLineDashType,k.lineThickness),m=k.lineDashType,n=F(m,k.lineThickness);b.setLineDash(n)}var e=k.id;this._eventManager.objectMap[e]={objectType:"dataSeries",
|
||||
dataSeriesIndex:l};e=D(e);d.strokeStyle=e;d.lineWidth=0<k.lineThickness?Math.max(k.lineThickness,4):0;var e=k._colorSet,q=e=k.lineColor=k.options.lineColor?k.options.lineColor:e[0];b.strokeStyle=e;var r=0,s,x,u=[];b.beginPath();if(0<h.length)for(x=!1,r=0;r<h.length;r++)if(s=h[r].getTime?h[r].x.getTime():h[r].x,!(s<a.axisX.dataInfo.viewPortMin||s>a.axisX.dataInfo.viewPortMax&&(!k.connectNullData||!x)))if("number"!==typeof h[r].y)0<r&&!x&&(k.connectNullData?b.setLineDash&&(0<u.length&&(k.options.nullDataLineDashType||
|
||||
!h[r-1].lineDashType))&&(u[u.length-1].newLineDashArray=p,m=k.nullDataLineDashType):(c(u),u=[])),x=!0;else{s=a.axisX.convertValueToPixel(s);x=a.axisY.convertValueToPixel(h[r].y);var v=k.dataPointIds[r];this._eventManager.objectMap[v]={id:v,objectType:"dataPoint",dataSeriesIndex:l,dataPointIndex:r,x1:s,y1:x};u[u.length]={x:s,y:x};r<h.length-1&&(q!==(h[r].lineColor||e)||m!==(h[r].lineDashType||k.lineDashType))&&(q=h[r].lineColor||e,u[u.length-1].newStrokeStyle=q,b.setLineDash&&(h[r].lineDashType?(m=
|
||||
h[r].lineDashType,u[u.length-1].newLineDashArray=F(m,k.lineThickness)):(m=k.lineDashType,u[u.length-1].newLineDashArray=n)));if(0<h[r].markerSize||0<k.markerSize){var z=k.getMarkerProperties(r,s,x,b);f.push(z);v=D(v);t&&f.push({x:s,y:x,ctx:d,type:z.type,size:z.size,color:v,borderColor:v,borderThickness:z.borderThickness})}(h[r].indexLabel||k.indexLabel||h[r].indexLabelFormatter||k.indexLabelFormatter)&&this._indexLabels.push({chartType:"spline",dataPoint:h[r],dataSeries:k,point:{x:s,y:x},direction:0>
|
||||
h[r].y===a.axisY.reversed?1:-1,color:e});x=!1}c(u)}O.drawMarkers(f);b.restore();b.beginPath();t&&d.beginPath();return{source:b,dest:this.plotArea.ctx,animationCallback:E.xClipAnimation,easingFunction:E.easing.linear,animationBase:0}}};var N=function(a,c,b,d,f,g,l,k,h,m,p,n,e){"undefined"===typeof e&&(e=1);l=l||0;k=k||"black";var q=15<d-c&&15<f-b?8:0.35*Math.min(d-c,f-b);a.beginPath();a.moveTo(c,b);a.save();a.fillStyle=g;a.globalAlpha=e;a.fillRect(c,b,d-c,f-b);a.globalAlpha=1;0<l&&(e=0===l%2?0:0.5,
|
||||
a.beginPath(),a.lineWidth=l,a.strokeStyle=k,a.moveTo(c,b),a.rect(c-e,b-e,d-c+2*e,f-b+2*e),a.stroke());a.restore();!0===h&&(a.save(),a.beginPath(),a.moveTo(c,b),a.lineTo(c+q,b+q),a.lineTo(d-q,b+q),a.lineTo(d,b),a.closePath(),l=a.createLinearGradient((d+c)/2,b+q,(d+c)/2,b),l.addColorStop(0,g),l.addColorStop(1,"rgba(255, 255, 255, .4)"),a.fillStyle=l,a.fill(),a.restore());!0===m&&(a.save(),a.beginPath(),a.moveTo(c,f),a.lineTo(c+q,f-q),a.lineTo(d-q,f-q),a.lineTo(d,f),a.closePath(),l=a.createLinearGradient((d+
|
||||
c)/2,f-q,(d+c)/2,f),l.addColorStop(0,g),l.addColorStop(1,"rgba(255, 255, 255, .4)"),a.fillStyle=l,a.fill(),a.restore());!0===p&&(a.save(),a.beginPath(),a.moveTo(c,b),a.lineTo(c+q,b+q),a.lineTo(c+q,f-q),a.lineTo(c,f),a.closePath(),l=a.createLinearGradient(c+q,(f+b)/2,c,(f+b)/2),l.addColorStop(0,g),l.addColorStop(1,"rgba(255, 255, 255, 0.1)"),a.fillStyle=l,a.fill(),a.restore());!0===n&&(a.save(),a.beginPath(),a.moveTo(d,b),a.lineTo(d-q,b+q),a.lineTo(d-q,f-q),a.lineTo(d,f),l=a.createLinearGradient(d-
|
||||
q,(f+b)/2,d,(f+b)/2),l.addColorStop(0,g),l.addColorStop(1,"rgba(255, 255, 255, 0.1)"),a.fillStyle=l,l.addColorStop(0,g),l.addColorStop(1,"rgba(255, 255, 255, 0.1)"),a.fillStyle=l,a.fill(),a.closePath(),a.restore())};A.prototype.renderColumn=function(a){var c=a.targetCanvasCtx||this.plotArea.ctx;if(!(0>=a.dataSeriesIndexes.length)){var b=null,d=this.plotArea,f=0,g,l,k,h=a.axisY.convertValueToPixel(a.axisY.logarithmic?a.axisY.viewportMinimum:0),f=this.dataPointMinWidth=this.dataPointMinWidth?this.dataPointMinWidth:
|
||||
this.dataPointWidth?this.dataPointWidth:1,m=this.dataPointMaxWidth=this.dataPointMaxWidth?this.dataPointMaxWidth:this.dataPointWidth?this.dataPointWidth:Math.min(0.15*this.width,0.9*(this.plotArea.width/a.plotType.totalDataSeries))<<0,p=a.axisX.dataInfo.minDiff;isFinite(p)||(p=0.3*Math.abs(a.axisX.range));p=this.dataPointWidth=this.dataPointWidth?this.dataPointWidth:0.9*(d.width*(a.axisX.logarithmic?Math.log(p)/Math.log(a.axisX.range):Math.abs(p)/Math.abs(a.axisX.range))/a.plotType.totalDataSeries)<<
|
||||
0;this.dataPointMaxWidth&&f>m&&(f=Math.min(this.dataPointWidth?this.dataPointWidth:Infinity,m));!this.dataPointMaxWidth&&(this.dataPointMinWidth&&m<f)&&(m=Math.max(this.dataPointWidth?this.dataPointWidth:-Infinity,f));p<f&&(p=f);p>m&&(p=m);c.save();t&&this._eventManager.ghostCtx.save();c.beginPath();c.rect(d.x1,d.y1,d.width,d.height);c.clip();t&&(this._eventManager.ghostCtx.beginPath(),this._eventManager.ghostCtx.rect(d.x1,d.y1,d.width,d.height),this._eventManager.ghostCtx.clip());for(d=0;d<a.dataSeriesIndexes.length;d++){var m=
|
||||
a.dataSeriesIndexes[d],n=this.data[m],e=n.dataPoints;if(0<e.length)for(var q=5<p&&n.bevelEnabled?!0:!1,f=0;f<e.length;f++)if(e[f].getTime?k=e[f].x.getTime():k=e[f].x,!(k<a.axisX.dataInfo.viewPortMin||k>a.axisX.dataInfo.viewPortMax)&&"number"===typeof e[f].y){g=a.axisX.convertValueToPixel(k);l=a.axisY.convertValueToPixel(e[f].y);g=a.axisX.reversed?g+a.plotType.totalDataSeries*p/2-(a.previousDataSeriesCount+d)*p<<0:g-a.plotType.totalDataSeries*p/2+(a.previousDataSeriesCount+d)*p<<0;var r=a.axisX.reversed?
|
||||
g-p<<0:g+p<<0,s;0<=e[f].y?s=h:(s=l,l=h);l>s&&(b=l,l=s,s=b);b=e[f].color?e[f].color:n._colorSet[f%n._colorSet.length];N(c,g,l,r,s,b,0,null,q&&0<=e[f].y,0>e[f].y&&q,!1,!1,n.fillOpacity);b=n.dataPointIds[f];this._eventManager.objectMap[b]={id:b,objectType:"dataPoint",dataSeriesIndex:m,dataPointIndex:f,x1:g,y1:l,x2:r,y2:s};b=D(b);t&&N(this._eventManager.ghostCtx,g,l,r,s,b,0,null,!1,!1,!1,!1);(e[f].indexLabel||n.indexLabel||e[f].indexLabelFormatter||n.indexLabelFormatter)&&this._indexLabels.push({chartType:"column",
|
||||
dataPoint:e[f],dataSeries:n,point:{x:g+(r-g)/2,y:0>e[f].y===a.axisY.reversed?l:s},direction:0>e[f].y===a.axisY.reversed?1:-1,bounds:{x1:g,y1:Math.min(l,s),x2:r,y2:Math.max(l,s)},color:b})}}c.restore();t&&this._eventManager.ghostCtx.restore();return{source:c,dest:this.plotArea.ctx,animationCallback:E.yScaleAnimation,easingFunction:E.easing.easeOutQuart,animationBase:h<a.axisY.bounds.y1?a.axisY.bounds.y1:h>a.axisY.bounds.y2?a.axisY.bounds.y2:h}}};A.prototype.renderStackedColumn=function(a){var c=a.targetCanvasCtx||
|
||||
this.plotArea.ctx;if(!(0>=a.dataSeriesIndexes.length)){var b=null,d=this.plotArea,f=[],g=[],l=[],k=0,h,m=a.axisY.convertValueToPixel(a.axisY.logarithmic?a.axisY.viewportMinimum:0),k=this.dataPointMinWidth?this.dataPointMinWidth:this.dataPointWidth?this.dataPointWidth:1,p=this.dataPointMaxWidth?this.dataPointMaxWidth:this.dataPointWidth?this.dataPointWidth:0.15*this.width<<0,n=a.axisX.dataInfo.minDiff;isFinite(n)||(n=0.3*Math.abs(a.axisX.range));n=this.dataPointWidth?this.dataPointWidth:0.9*(d.width*
|
||||
(a.axisX.logarithmic?Math.log(n)/Math.log(a.axisX.range):Math.abs(n)/Math.abs(a.axisX.range))/a.plotType.plotUnits.length)<<0;this.dataPointMaxWidth&&k>p&&(k=Math.min(this.dataPointWidth?this.dataPointWidth:Infinity,p));!this.dataPointMaxWidth&&(this.dataPointMinWidth&&p<k)&&(p=Math.max(this.dataPointWidth?this.dataPointWidth:-Infinity,k));n<k&&(n=k);n>p&&(n=p);c.save();t&&this._eventManager.ghostCtx.save();c.beginPath();c.rect(d.x1,d.y1,d.width,d.height);c.clip();t&&(this._eventManager.ghostCtx.beginPath(),
|
||||
this._eventManager.ghostCtx.rect(d.x1,d.y1,d.width,d.height),this._eventManager.ghostCtx.clip());for(p=0;p<a.dataSeriesIndexes.length;p++){var e=a.dataSeriesIndexes[p],q=this.data[e],r=q.dataPoints;if(0<r.length){var s=5<n&&q.bevelEnabled?!0:!1;c.strokeStyle="#4572A7 ";for(k=0;k<r.length;k++)if(b=r[k].x.getTime?r[k].x.getTime():r[k].x,!(b<a.axisX.dataInfo.viewPortMin||b>a.axisX.dataInfo.viewPortMax)&&"number"===typeof r[k].y){var d=a.axisX.convertValueToPixel(b),x=d-a.plotType.plotUnits.length*n/
|
||||
2+a.index*n<<0,u=x+n<<0,v;if(a.axisY.logarithmic)l[b]=r[k].y+(l[b]?l[b]:0),0<l[b]&&(h=a.axisY.convertValueToPixel(l[b]),v=f[b]?f[b]:m,f[b]=h);else if(h=a.axisY.convertValueToPixel(r[k].y),0<=r[k].y){var z=f[b]?f[b]:0;h-=z;v=m-z;f[b]=z+(v-h)}else z=g[b]?g[b]:0,v=h+z,h=m+z,g[b]=z+(v-h);b=r[k].color?r[k].color:q._colorSet[k%q._colorSet.length];N(c,x,h,u,v,b,0,null,s&&0<=r[k].y,0>r[k].y&&s,!1,!1,q.fillOpacity);b=q.dataPointIds[k];this._eventManager.objectMap[b]={id:b,objectType:"dataPoint",dataSeriesIndex:e,
|
||||
dataPointIndex:k,x1:x,y1:h,x2:u,y2:v};b=D(b);t&&N(this._eventManager.ghostCtx,x,h,u,v,b,0,null,!1,!1,!1,!1);(r[k].indexLabel||q.indexLabel||r[k].indexLabelFormatter||q.indexLabelFormatter)&&this._indexLabels.push({chartType:"stackedColumn",dataPoint:r[k],dataSeries:q,point:{x:d,y:0<=r[k].y?h:v},direction:0>r[k].y===a.axisY.reversed?1:-1,bounds:{x1:x,y1:Math.min(h,v),x2:u,y2:Math.max(h,v)},color:b})}}}c.restore();t&&this._eventManager.ghostCtx.restore();return{source:c,dest:this.plotArea.ctx,animationCallback:E.yScaleAnimation,
|
||||
easingFunction:E.easing.easeOutQuart,animationBase:m<a.axisY.bounds.y1?a.axisY.bounds.y1:m>a.axisY.bounds.y2?a.axisY.bounds.y2:m}}};A.prototype.renderStackedColumn100=function(a){var c=a.targetCanvasCtx||this.plotArea.ctx;if(!(0>=a.dataSeriesIndexes.length)){var b=null,d=this.plotArea,f=[],g=[],l=[],k=0,h,m=a.axisY.convertValueToPixel(a.axisY.logarithmic?a.axisY.viewportMinimum:0),k=this.dataPointMinWidth?this.dataPointMinWidth:this.dataPointWidth?this.dataPointWidth:1,p=this.dataPointMaxWidth?this.dataPointMaxWidth:
|
||||
this.dataPointWidth?this.dataPointWidth:0.15*this.width<<0,n=a.axisX.dataInfo.minDiff;isFinite(n)||(n=0.3*Math.abs(a.axisX.range));n=this.dataPointWidth?this.dataPointWidth:0.9*(d.width*(a.axisX.logarithmic?Math.log(n)/Math.log(a.axisX.range):Math.abs(n)/Math.abs(a.axisX.range))/a.plotType.plotUnits.length)<<0;this.dataPointMaxWidth&&k>p&&(k=Math.min(this.dataPointWidth?this.dataPointWidth:Infinity,p));!this.dataPointMaxWidth&&(this.dataPointMinWidth&&p<k)&&(p=Math.max(this.dataPointWidth?this.dataPointWidth:
|
||||
-Infinity,k));n<k&&(n=k);n>p&&(n=p);c.save();t&&this._eventManager.ghostCtx.save();c.beginPath();c.rect(d.x1,d.y1,d.width,d.height);c.clip();t&&(this._eventManager.ghostCtx.beginPath(),this._eventManager.ghostCtx.rect(d.x1,d.y1,d.width,d.height),this._eventManager.ghostCtx.clip());for(p=0;p<a.dataSeriesIndexes.length;p++){var e=a.dataSeriesIndexes[p],q=this.data[e],r=q.dataPoints;if(0<r.length)for(var s=5<n&&q.bevelEnabled?!0:!1,k=0;k<r.length;k++)if(b=r[k].x.getTime?r[k].x.getTime():r[k].x,!(b<a.axisX.dataInfo.viewPortMin||
|
||||
b>a.axisX.dataInfo.viewPortMax)&&"number"===typeof r[k].y){d=a.axisX.convertValueToPixel(b);h=0!==a.dataPointYSums[b]?100*(r[k].y/a.dataPointYSums[b]):0;var x=d-a.plotType.plotUnits.length*n/2+a.index*n<<0,u=x+n<<0,v;if(a.axisY.logarithmic){l[b]=h+(l[b]?l[b]:0);if(0>=l[b])continue;h=a.axisY.convertValueToPixel(l[b]);v=f[b]?f[b]:m;f[b]=h}else if(h=a.axisY.convertValueToPixel(h),0<=r[k].y){var z=f[b]?f[b]:0;h-=z;v=m-z;f[b]=z+(v-h)}else z=g[b]?g[b]:0,v=h+z,h=m+z,g[b]=z+(v-h);b=r[k].color?r[k].color:
|
||||
q._colorSet[k%q._colorSet.length];N(c,x,h,u,v,b,0,null,s&&0<=r[k].y,0>r[k].y&&s,!1,!1,q.fillOpacity);b=q.dataPointIds[k];this._eventManager.objectMap[b]={id:b,objectType:"dataPoint",dataSeriesIndex:e,dataPointIndex:k,x1:x,y1:h,x2:u,y2:v};b=D(b);t&&N(this._eventManager.ghostCtx,x,h,u,v,b,0,null,!1,!1,!1,!1);(r[k].indexLabel||q.indexLabel||r[k].indexLabelFormatter||q.indexLabelFormatter)&&this._indexLabels.push({chartType:"stackedColumn100",dataPoint:r[k],dataSeries:q,point:{x:d,y:0<=r[k].y?h:v},direction:0>
|
||||
r[k].y===a.axisY.reversed?1:-1,bounds:{x1:x,y1:Math.min(h,v),x2:u,y2:Math.max(h,v)},color:b})}}c.restore();t&&this._eventManager.ghostCtx.restore();return{source:c,dest:this.plotArea.ctx,animationCallback:E.yScaleAnimation,easingFunction:E.easing.easeOutQuart,animationBase:m<a.axisY.bounds.y1?a.axisY.bounds.y1:m>a.axisY.bounds.y2?a.axisY.bounds.y2:m}}};A.prototype.renderBar=function(a){var c=a.targetCanvasCtx||this.plotArea.ctx;if(!(0>=a.dataSeriesIndexes.length)){var b=null,d=this.plotArea,f=0,g,
|
||||
l,k,h=a.axisY.convertValueToPixel(a.axisY.logarithmic?a.axisY.viewportMinimum:0),f=this.dataPointMinWidth?this.dataPointMinWidth:this.dataPointWidth?this.dataPointWidth:1,m=this.dataPointMaxWidth?this.dataPointMaxWidth:this.dataPointWidth?this.dataPointWidth:Math.min(0.15*this.height,0.9*(this.plotArea.height/a.plotType.totalDataSeries))<<0,p=a.axisX.dataInfo.minDiff;isFinite(p)||(p=0.3*Math.abs(a.axisX.range));p=this.dataPointWidth?this.dataPointWidth:0.9*(d.height*(a.axisX.logarithmic?Math.log(p)/
|
||||
Math.log(a.axisX.range):Math.abs(p)/Math.abs(a.axisX.range))/a.plotType.totalDataSeries)<<0;this.dataPointMaxWidth&&f>m&&(f=Math.min(this.dataPointWidth?this.dataPointWidth:Infinity,m));!this.dataPointMaxWidth&&(this.dataPointMinWidth&&m<f)&&(m=Math.max(this.dataPointWidth?this.dataPointWidth:-Infinity,f));p<f&&(p=f);p>m&&(p=m);c.save();t&&this._eventManager.ghostCtx.save();c.beginPath();c.rect(d.x1,d.y1,d.width,d.height);c.clip();t&&(this._eventManager.ghostCtx.beginPath(),this._eventManager.ghostCtx.rect(d.x1,
|
||||
d.y1,d.width,d.height),this._eventManager.ghostCtx.clip());for(d=0;d<a.dataSeriesIndexes.length;d++){var m=a.dataSeriesIndexes[d],n=this.data[m],e=n.dataPoints;if(0<e.length){var q=5<p&&n.bevelEnabled?!0:!1;c.strokeStyle="#4572A7 ";for(f=0;f<e.length;f++)if(e[f].getTime?k=e[f].x.getTime():k=e[f].x,!(k<a.axisX.dataInfo.viewPortMin||k>a.axisX.dataInfo.viewPortMax)&&"number"===typeof e[f].y){l=a.axisX.convertValueToPixel(k);g=a.axisY.convertValueToPixel(e[f].y);l=a.axisX.reversed?l+a.plotType.totalDataSeries*
|
||||
p/2-(a.previousDataSeriesCount+d)*p<<0:l-a.plotType.totalDataSeries*p/2+(a.previousDataSeriesCount+d)*p<<0;var r=a.axisX.reversed?l-p<<0:l+p<<0,s;0<=e[f].y?s=h:(s=g,g=h);b=e[f].color?e[f].color:n._colorSet[f%n._colorSet.length];N(c,s,l,g,r,b,0,null,q,!1,!1,!1,n.fillOpacity);b=n.dataPointIds[f];this._eventManager.objectMap[b]={id:b,objectType:"dataPoint",dataSeriesIndex:m,dataPointIndex:f,x1:s,y1:l,x2:g,y2:r};b=D(b);t&&N(this._eventManager.ghostCtx,s,l,g,r,b,0,null,!1,!1,!1,!1);(e[f].indexLabel||n.indexLabel||
|
||||
e[f].indexLabelFormatter||n.indexLabelFormatter)&&this._indexLabels.push({chartType:"bar",dataPoint:e[f],dataSeries:n,point:{x:0<=e[f].y?g:s,y:l+(r-l)/2},direction:0>e[f].y===a.axisY.reversed?1:-1,bounds:{x1:Math.min(s,g),y1:l,x2:Math.max(s,g),y2:r},color:b})}}}c.restore();t&&this._eventManager.ghostCtx.restore();return{source:c,dest:this.plotArea.ctx,animationCallback:E.xScaleAnimation,easingFunction:E.easing.easeOutQuart,animationBase:h<a.axisY.bounds.x1?a.axisY.bounds.x1:h>a.axisY.bounds.x2?a.axisY.bounds.x2:
|
||||
h}}};A.prototype.renderStackedBar=function(a){var c=a.targetCanvasCtx||this.plotArea.ctx;if(!(0>=a.dataSeriesIndexes.length)){var b=null,d=this.plotArea,f=[],g=[],l=[],k=0,h,m=a.axisY.convertValueToPixel(a.axisY.logarithmic?a.axisY.viewportMinimum:0),k=this.dataPointMinWidth?this.dataPointMinWidth:this.dataPointWidth?this.dataPointWidth:1,p=this.dataPointMaxWidth?this.dataPointMaxWidth:this.dataPointWidth?this.dataPointWidth:0.15*this.height<<0,n=a.axisX.dataInfo.minDiff;isFinite(n)||(n=0.3*Math.abs(a.axisX.range));
|
||||
n=this.dataPointWidth?this.dataPointWidth:0.9*(d.height*(a.axisX.logarithmic?Math.log(n)/Math.log(a.axisX.range):Math.abs(n)/Math.abs(a.axisX.range))/a.plotType.plotUnits.length)<<0;this.dataPointMaxWidth&&k>p&&(k=Math.min(this.dataPointWidth?this.dataPointWidth:Infinity,p));!this.dataPointMaxWidth&&(this.dataPointMinWidth&&p<k)&&(p=Math.max(this.dataPointWidth?this.dataPointWidth:-Infinity,k));n<k&&(n=k);n>p&&(n=p);c.save();t&&this._eventManager.ghostCtx.save();c.beginPath();c.rect(d.x1,d.y1,d.width,
|
||||
d.height);c.clip();t&&(this._eventManager.ghostCtx.beginPath(),this._eventManager.ghostCtx.rect(d.x1,d.y1,d.width,d.height),this._eventManager.ghostCtx.clip());for(p=0;p<a.dataSeriesIndexes.length;p++){var e=a.dataSeriesIndexes[p],q=this.data[e],r=q.dataPoints;if(0<r.length){var s=5<n&&q.bevelEnabled?!0:!1;c.strokeStyle="#4572A7 ";for(k=0;k<r.length;k++)if(b=r[k].x.getTime?r[k].x.getTime():r[k].x,!(b<a.axisX.dataInfo.viewPortMin||b>a.axisX.dataInfo.viewPortMax)&&"number"===typeof r[k].y){var d=a.axisX.convertValueToPixel(b),
|
||||
x=d-a.plotType.plotUnits.length*n/2+a.index*n<<0,u=x+n<<0,v;if(a.axisY.logarithmic)l[b]=r[k].y+(l[b]?l[b]:0),0<l[b]&&(v=f[b]?f[b]:m,f[b]=h=a.axisY.convertValueToPixel(l[b]));else if(h=a.axisY.convertValueToPixel(r[k].y),0<=r[k].y){var z=f[b]?f[b]:0;v=m+z;h+=z;f[b]=z+(h-v)}else z=g[b]?g[b]:0,v=h-z,h=m-z,g[b]=z+(h-v);b=r[k].color?r[k].color:q._colorSet[k%q._colorSet.length];N(c,v,x,h,u,b,0,null,s,!1,!1,!1,q.fillOpacity);b=q.dataPointIds[k];this._eventManager.objectMap[b]={id:b,objectType:"dataPoint",
|
||||
dataSeriesIndex:e,dataPointIndex:k,x1:v,y1:x,x2:h,y2:u};b=D(b);t&&N(this._eventManager.ghostCtx,v,x,h,u,b,0,null,!1,!1,!1,!1);(r[k].indexLabel||q.indexLabel||r[k].indexLabelFormatter||q.indexLabelFormatter)&&this._indexLabels.push({chartType:"stackedBar",dataPoint:r[k],dataSeries:q,point:{x:0<=r[k].y?h:v,y:d},direction:0>r[k].y===a.axisY.reversed?1:-1,bounds:{x1:Math.min(v,h),y1:x,x2:Math.max(v,h),y2:u},color:b})}}}c.restore();t&&this._eventManager.ghostCtx.restore();return{source:c,dest:this.plotArea.ctx,
|
||||
animationCallback:E.xScaleAnimation,easingFunction:E.easing.easeOutQuart,animationBase:m<a.axisY.bounds.x1?a.axisY.bounds.x1:m>a.axisY.bounds.x2?a.axisY.bounds.x2:m}}};A.prototype.renderStackedBar100=function(a){var c=a.targetCanvasCtx||this.plotArea.ctx;if(!(0>=a.dataSeriesIndexes.length)){var b=null,d=this.plotArea,f=[],g=[],l=[],k=0,h,m=a.axisY.convertValueToPixel(a.axisY.logarithmic?a.axisY.viewportMinimum:0),k=this.dataPointMinWidth?this.dataPointMinWidth:this.dataPointWidth?this.dataPointWidth:
|
||||
1,p=this.dataPointMaxWidth?this.dataPointMaxWidth:this.dataPointWidth?this.dataPointWidth:0.15*this.height<<0,n=a.axisX.dataInfo.minDiff;isFinite(n)||(n=0.3*Math.abs(a.axisX.range));n=this.dataPointWidth?this.dataPointWidth:0.9*(d.height*(a.axisX.logarithmic?Math.log(n)/Math.log(a.axisX.range):Math.abs(n)/Math.abs(a.axisX.range))/a.plotType.plotUnits.length)<<0;this.dataPointMaxWidth&&k>p&&(k=Math.min(this.dataPointWidth?this.dataPointWidth:Infinity,p));!this.dataPointMaxWidth&&(this.dataPointMinWidth&&
|
||||
p<k)&&(p=Math.max(this.dataPointWidth?this.dataPointWidth:-Infinity,k));n<k&&(n=k);n>p&&(n=p);c.save();t&&this._eventManager.ghostCtx.save();c.beginPath();c.rect(d.x1,d.y1,d.width,d.height);c.clip();t&&(this._eventManager.ghostCtx.beginPath(),this._eventManager.ghostCtx.rect(d.x1,d.y1,d.width,d.height),this._eventManager.ghostCtx.clip());for(p=0;p<a.dataSeriesIndexes.length;p++){var e=a.dataSeriesIndexes[p],q=this.data[e],r=q.dataPoints;if(0<r.length){var s=5<n&&q.bevelEnabled?!0:!1;c.strokeStyle=
|
||||
"#4572A7 ";for(k=0;k<r.length;k++)if(b=r[k].x.getTime?r[k].x.getTime():r[k].x,!(b<a.axisX.dataInfo.viewPortMin||b>a.axisX.dataInfo.viewPortMax)&&"number"===typeof r[k].y){var d=a.axisX.convertValueToPixel(b),x;x=0!==a.dataPointYSums[b]?100*(r[k].y/a.dataPointYSums[b]):0;var u=d-a.plotType.plotUnits.length*n/2+a.index*n<<0,v=u+n<<0;if(a.axisY.logarithmic){l[b]=x+(l[b]?l[b]:0);if(0>=l[b])continue;x=f[b]?f[b]:m;f[b]=h=a.axisY.convertValueToPixel(l[b])}else if(h=a.axisY.convertValueToPixel(x),0<=r[k].y){var z=
|
||||
f[b]?f[b]:0;x=m+z;h+=z;f[b]=z+(h-x)}else z=g[b]?g[b]:0,x=h-z,h=m-z,g[b]=z+(h-x);b=r[k].color?r[k].color:q._colorSet[k%q._colorSet.length];N(c,x,u,h,v,b,0,null,s,!1,!1,!1,q.fillOpacity);b=q.dataPointIds[k];this._eventManager.objectMap[b]={id:b,objectType:"dataPoint",dataSeriesIndex:e,dataPointIndex:k,x1:x,y1:u,x2:h,y2:v};b=D(b);t&&N(this._eventManager.ghostCtx,x,u,h,v,b,0,null,!1,!1,!1,!1);(r[k].indexLabel||q.indexLabel||r[k].indexLabelFormatter||q.indexLabelFormatter)&&this._indexLabels.push({chartType:"stackedBar100",
|
||||
dataPoint:r[k],dataSeries:q,point:{x:0<=r[k].y?h:x,y:d},direction:0>r[k].y===a.axisY.reversed?1:-1,bounds:{x1:Math.min(x,h),y1:u,x2:Math.max(x,h),y2:v},color:b})}}}c.restore();t&&this._eventManager.ghostCtx.restore();return{source:c,dest:this.plotArea.ctx,animationCallback:E.xScaleAnimation,easingFunction:E.easing.easeOutQuart,animationBase:m<a.axisY.bounds.x1?a.axisY.bounds.x1:m>a.axisY.bounds.x2?a.axisY.bounds.x2:m}}};A.prototype.renderArea=function(a){var c,b;function d(){w&&(0<e.lineThickness&&
|
||||
f.stroke(),a.axisY.logarithmic||0>=a.axisY.viewportMinimum&&0<=a.axisY.viewportMaximum?z=v:0>a.axisY.viewportMaximum?z=k.y1:0<a.axisY.viewportMinimum&&(z=l.y2),f.lineTo(s,z),f.lineTo(w.x,z),f.closePath(),f.globalAlpha=e.fillOpacity,f.fill(),f.globalAlpha=1,t&&(g.lineTo(s,z),g.lineTo(w.x,z),g.closePath(),g.fill()),f.beginPath(),f.moveTo(s,x),g.beginPath(),g.moveTo(s,x),w={x:s,y:x})}var f=a.targetCanvasCtx||this.plotArea.ctx;if(!(0>=a.dataSeriesIndexes.length)){var g=this._eventManager.ghostCtx,l=a.axisX.lineCoordinates,
|
||||
k=a.axisY.lineCoordinates,h=[],m=this.plotArea,p;f.save();t&&g.save();f.beginPath();f.rect(m.x1,m.y1,m.width,m.height);f.clip();t&&(g.beginPath(),g.rect(m.x1,m.y1,m.width,m.height),g.clip());for(m=0;m<a.dataSeriesIndexes.length;m++){var n=a.dataSeriesIndexes[m],e=this.data[n],q=e.dataPoints,h=e.id;this._eventManager.objectMap[h]={objectType:"dataSeries",dataSeriesIndex:n};h=D(h);g.fillStyle=h;h=[];c=!0;var r=0,s,x,u,v=a.axisY.convertValueToPixel(a.axisY.logarithmic?a.axisY.viewportMinimum:0),z,w=
|
||||
null;if(0<q.length){var y=e._colorSet[r%e._colorSet.length],ba=e.lineColor=e.options.lineColor||y,A=ba;f.fillStyle=y;f.strokeStyle=ba;f.lineWidth=e.lineThickness;b="solid";if(f.setLineDash){var B=F(e.nullDataLineDashType,e.lineThickness);b=e.lineDashType;var W=F(b,e.lineThickness);f.setLineDash(W)}for(var X=!0;r<q.length;r++)if(u=q[r].x.getTime?q[r].x.getTime():q[r].x,!(u<a.axisX.dataInfo.viewPortMin||u>a.axisX.dataInfo.viewPortMax&&(!e.connectNullData||!X)))if("number"!==typeof q[r].y)e.connectNullData||
|
||||
(X||c)||d(),X=!0;else{s=a.axisX.convertValueToPixel(u);x=a.axisY.convertValueToPixel(q[r].y);c||X?(!c&&e.connectNullData?(f.setLineDash&&(e.options.nullDataLineDashType||b===e.lineDashType&&e.lineDashType!==e.nullDataLineDashType)&&(c=s,b=x,s=p.x,x=p.y,d(),f.moveTo(p.x,p.y),s=c,x=b,w=p,b=e.nullDataLineDashType,f.setLineDash(B)),f.lineTo(s,x),t&&g.lineTo(s,x)):(f.beginPath(),f.moveTo(s,x),t&&(g.beginPath(),g.moveTo(s,x)),w={x:s,y:x}),X=c=!1):(f.lineTo(s,x),t&&g.lineTo(s,x),0==r%250&&d());p={x:s,y:x};
|
||||
r<q.length-1&&(A!==(q[r].lineColor||ba)||b!==(q[r].lineDashType||e.lineDashType))&&(d(),A=q[r].lineColor||ba,f.strokeStyle=A,f.setLineDash&&(q[r].lineDashType?(b=q[r].lineDashType,f.setLineDash(F(b,e.lineThickness))):(b=e.lineDashType,f.setLineDash(W))));var H=e.dataPointIds[r];this._eventManager.objectMap[H]={id:H,objectType:"dataPoint",dataSeriesIndex:n,dataPointIndex:r,x1:s,y1:x};0!==q[r].markerSize&&(0<q[r].markerSize||0<e.markerSize)&&(u=e.getMarkerProperties(r,s,x,f),h.push(u),H=D(H),t&&h.push({x:s,
|
||||
y:x,ctx:g,type:u.type,size:u.size,color:H,borderColor:H,borderThickness:u.borderThickness}));(q[r].indexLabel||e.indexLabel||q[r].indexLabelFormatter||e.indexLabelFormatter)&&this._indexLabels.push({chartType:"area",dataPoint:q[r],dataSeries:e,point:{x:s,y:x},direction:0>q[r].y===a.axisY.reversed?1:-1,color:y})}d();O.drawMarkers(h)}}f.restore();t&&this._eventManager.ghostCtx.restore();return{source:f,dest:this.plotArea.ctx,animationCallback:E.xClipAnimation,easingFunction:E.easing.linear,animationBase:0}}};
|
||||
A.prototype.renderSplineArea=function(a){function c(){var c=wa(u,2);if(0<c.length){if(0<m.lineThickness){b.beginPath();b.moveTo(c[0].x,c[0].y);c[0].newStrokeStyle&&(b.strokeStyle=c[0].newStrokeStyle);c[0].newLineDashArray&&b.setLineDash(c[0].newLineDashArray);for(var e=0;e<c.length-3;e+=3)if(b.bezierCurveTo(c[e+1].x,c[e+1].y,c[e+2].x,c[e+2].y,c[e+3].x,c[e+3].y),t&&d.bezierCurveTo(c[e+1].x,c[e+1].y,c[e+2].x,c[e+2].y,c[e+3].x,c[e+3].y),c[e+3].newStrokeStyle||c[e+3].newLineDashArray)b.stroke(),b.beginPath(),
|
||||
b.moveTo(c[e+3].x,c[e+3].y),c[e+3].newStrokeStyle&&(b.strokeStyle=c[e+3].newStrokeStyle),c[e+3].newLineDashArray&&b.setLineDash(c[e+3].newLineDashArray);b.stroke()}b.beginPath();b.moveTo(c[0].x,c[0].y);t&&(d.beginPath(),d.moveTo(c[0].x,c[0].y));for(e=0;e<c.length-3;e+=3)b.bezierCurveTo(c[e+1].x,c[e+1].y,c[e+2].x,c[e+2].y,c[e+3].x,c[e+3].y),t&&d.bezierCurveTo(c[e+1].x,c[e+1].y,c[e+2].x,c[e+2].y,c[e+3].x,c[e+3].y);a.axisY.logarithmic||0>=a.axisY.viewportMinimum&&0<=a.axisY.viewportMaximum?s=r:0>a.axisY.viewportMaximum?
|
||||
s=g.y1:0<a.axisY.viewportMinimum&&(s=f.y2);x={x:c[0].x,y:c[0].y};b.lineTo(c[c.length-1].x,s);b.lineTo(x.x,s);b.closePath();b.globalAlpha=m.fillOpacity;b.fill();b.globalAlpha=1;t&&(d.lineTo(c[c.length-1].x,s),d.lineTo(x.x,s),d.closePath(),d.fill())}}var b=a.targetCanvasCtx||this.plotArea.ctx;if(!(0>=a.dataSeriesIndexes.length)){var d=this._eventManager.ghostCtx,f=a.axisX.lineCoordinates,g=a.axisY.lineCoordinates,l=[],k=this.plotArea;b.save();t&&d.save();b.beginPath();b.rect(k.x1,k.y1,k.width,k.height);
|
||||
b.clip();t&&(d.beginPath(),d.rect(k.x1,k.y1,k.width,k.height),d.clip());for(k=0;k<a.dataSeriesIndexes.length;k++){var h=a.dataSeriesIndexes[k],m=this.data[h],p=m.dataPoints,l=m.id;this._eventManager.objectMap[l]={objectType:"dataSeries",dataSeriesIndex:h};l=D(l);d.fillStyle=l;var l=[],n=0,e,q,r=a.axisY.convertValueToPixel(a.axisY.logarithmic?a.axisY.viewportMinimum:0),s,x=null,u=[];if(0<p.length){var v=m._colorSet[n%m._colorSet.length],z=m.lineColor=m.options.lineColor||v,w=z;b.fillStyle=v;b.strokeStyle=
|
||||
z;b.lineWidth=m.lineThickness;var y="solid";if(b.setLineDash){var A=F(m.nullDataLineDashType,m.lineThickness),y=m.lineDashType,B=F(y,m.lineThickness);b.setLineDash(B)}for(q=!1;n<p.length;n++)if(e=p[n].x.getTime?p[n].x.getTime():p[n].x,!(e<a.axisX.dataInfo.viewPortMin||e>a.axisX.dataInfo.viewPortMax&&(!m.connectNullData||!q)))if("number"!==typeof p[n].y)0<n&&!q&&(m.connectNullData?b.setLineDash&&(0<u.length&&(m.options.nullDataLineDashType||!p[n-1].lineDashType))&&(u[u.length-1].newLineDashArray=A,
|
||||
y=m.nullDataLineDashType):(c(),u=[])),q=!0;else{e=a.axisX.convertValueToPixel(e);q=a.axisY.convertValueToPixel(p[n].y);var M=m.dataPointIds[n];this._eventManager.objectMap[M]={id:M,objectType:"dataPoint",dataSeriesIndex:h,dataPointIndex:n,x1:e,y1:q};u[u.length]={x:e,y:q};n<p.length-1&&(w!==(p[n].lineColor||z)||y!==(p[n].lineDashType||m.lineDashType))&&(w=p[n].lineColor||z,u[u.length-1].newStrokeStyle=w,b.setLineDash&&(p[n].lineDashType?(y=p[n].lineDashType,u[u.length-1].newLineDashArray=F(y,m.lineThickness)):
|
||||
(y=m.lineDashType,u[u.length-1].newLineDashArray=B)));if(0!==p[n].markerSize&&(0<p[n].markerSize||0<m.markerSize)){var W=m.getMarkerProperties(n,e,q,b);l.push(W);M=D(M);t&&l.push({x:e,y:q,ctx:d,type:W.type,size:W.size,color:M,borderColor:M,borderThickness:W.borderThickness})}(p[n].indexLabel||m.indexLabel||p[n].indexLabelFormatter||m.indexLabelFormatter)&&this._indexLabels.push({chartType:"splineArea",dataPoint:p[n],dataSeries:m,point:{x:e,y:q},direction:0>p[n].y===a.axisY.reversed?1:-1,color:v});
|
||||
q=!1}c();O.drawMarkers(l)}}b.restore();t&&this._eventManager.ghostCtx.restore();return{source:b,dest:this.plotArea.ctx,animationCallback:E.xClipAnimation,easingFunction:E.easing.linear,animationBase:0}}};A.prototype.renderStepArea=function(a){var c,b;function d(){w&&(0<e.lineThickness&&f.stroke(),a.axisY.logarithmic||0>=a.axisY.viewportMinimum&&0<=a.axisY.viewportMaximum?z=v:0>a.axisY.viewportMaximum?z=k.y1:0<a.axisY.viewportMinimum&&(z=l.y2),f.lineTo(s,z),f.lineTo(w.x,z),f.closePath(),f.globalAlpha=
|
||||
e.fillOpacity,f.fill(),f.globalAlpha=1,t&&(g.lineTo(s,z),g.lineTo(w.x,z),g.closePath(),g.fill()),f.beginPath(),f.moveTo(s,x),g.beginPath(),g.moveTo(s,x),w={x:s,y:x})}var f=a.targetCanvasCtx||this.plotArea.ctx;if(!(0>=a.dataSeriesIndexes.length)){var g=this._eventManager.ghostCtx,l=a.axisX.lineCoordinates,k=a.axisY.lineCoordinates,h=[],m=this.plotArea,p;f.save();t&&g.save();f.beginPath();f.rect(m.x1,m.y1,m.width,m.height);f.clip();t&&(g.beginPath(),g.rect(m.x1,m.y1,m.width,m.height),g.clip());for(m=
|
||||
0;m<a.dataSeriesIndexes.length;m++){var n=a.dataSeriesIndexes[m],e=this.data[n],q=e.dataPoints,h=e.id;this._eventManager.objectMap[h]={objectType:"dataSeries",dataSeriesIndex:n};h=D(h);g.fillStyle=h;h=[];c=!0;var r=0,s,x,u,v=a.axisY.convertValueToPixel(a.axisY.logarithmic?a.axisY.viewportMinimum:0),z,w=null;b=!1;if(0<q.length){var y=e._colorSet[r%e._colorSet.length],A=e.lineColor=e.options.lineColor||y,B=A;f.fillStyle=y;f.strokeStyle=A;f.lineWidth=e.lineThickness;var M="solid";if(f.setLineDash){var W=
|
||||
F(e.nullDataLineDashType,e.lineThickness),M=e.lineDashType,X=F(M,e.lineThickness);f.setLineDash(X)}for(;r<q.length;r++)if(u=q[r].x.getTime?q[r].x.getTime():q[r].x,!(u<a.axisX.dataInfo.viewPortMin||u>a.axisX.dataInfo.viewPortMax&&(!e.connectNullData||!b))){var H=x;"number"!==typeof q[r].y?(e.connectNullData||(b||c)||d(),b=!0):(s=a.axisX.convertValueToPixel(u),x=a.axisY.convertValueToPixel(q[r].y),c||b?(!c&&e.connectNullData?(f.setLineDash&&(e.options.nullDataLineDashType||M===e.lineDashType&&e.lineDashType!==
|
||||
e.nullDataLineDashType)&&(c=s,b=x,s=p.x,x=p.y,d(),f.moveTo(p.x,p.y),s=c,x=b,w=p,M=e.nullDataLineDashType,f.setLineDash(W)),f.lineTo(s,H),f.lineTo(s,x),t&&(g.lineTo(s,H),g.lineTo(s,x))):(f.beginPath(),f.moveTo(s,x),t&&(g.beginPath(),g.moveTo(s,x)),w={x:s,y:x}),b=c=!1):(f.lineTo(s,H),t&&g.lineTo(s,H),f.lineTo(s,x),t&&g.lineTo(s,x),0==r%250&&d()),p={x:s,y:x},r<q.length-1&&(B!==(q[r].lineColor||A)||M!==(q[r].lineDashType||e.lineDashType))&&(d(),B=q[r].lineColor||A,f.strokeStyle=B,f.setLineDash&&(q[r].lineDashType?
|
||||
(M=q[r].lineDashType,f.setLineDash(F(M,e.lineThickness))):(M=e.lineDashType,f.setLineDash(X)))),u=e.dataPointIds[r],this._eventManager.objectMap[u]={id:u,objectType:"dataPoint",dataSeriesIndex:n,dataPointIndex:r,x1:s,y1:x},0!==q[r].markerSize&&(0<q[r].markerSize||0<e.markerSize)&&(H=e.getMarkerProperties(r,s,x,f),h.push(H),u=D(u),t&&h.push({x:s,y:x,ctx:g,type:H.type,size:H.size,color:u,borderColor:u,borderThickness:H.borderThickness})),(q[r].indexLabel||e.indexLabel||q[r].indexLabelFormatter||e.indexLabelFormatter)&&
|
||||
this._indexLabels.push({chartType:"stepArea",dataPoint:q[r],dataSeries:e,point:{x:s,y:x},direction:0>q[r].y===a.axisY.reversed?1:-1,color:y}))}d();O.drawMarkers(h)}}f.restore();t&&this._eventManager.ghostCtx.restore();return{source:f,dest:this.plotArea.ctx,animationCallback:E.xClipAnimation,easingFunction:E.easing.linear,animationBase:0}}};A.prototype.renderStackedArea=function(a){function c(){if(!(1>k.length)){for(0<w.lineThickness&&b.stroke();0<k.length;){var a=k.pop();b.lineTo(a.x,a.y);t&&s.lineTo(a.x,
|
||||
a.y)}b.closePath();b.globalAlpha=w.fillOpacity;b.fill();b.globalAlpha=1;b.beginPath();t&&(s.closePath(),s.fill(),s.beginPath());k=[]}}var b=a.targetCanvasCtx||this.plotArea.ctx;if(!(0>=a.dataSeriesIndexes.length)){var d=null,f=[],g=this.plotArea,l=[],k=[],h=[],m=[],p=0,n,e,q,r=a.axisY.convertValueToPixel(a.axisY.logarithmic?a.axisY.viewportMinimum:0),s=this._eventManager.ghostCtx,x,u,v;t&&s.beginPath();b.save();t&&s.save();b.beginPath();b.rect(g.x1,g.y1,g.width,g.height);b.clip();t&&(s.beginPath(),
|
||||
s.rect(g.x1,g.y1,g.width,g.height),s.clip());d=[];for(g=0;g<a.dataSeriesIndexes.length;g++){var z=a.dataSeriesIndexes[g],w=this.data[z],y=w.dataPoints;w.dataPointIndexes=[];for(p=0;p<y.length;p++)z=y[p].x.getTime?y[p].x.getTime():y[p].x,w.dataPointIndexes[z]=p,d[z]||(h.push(z),d[z]=!0);h.sort(Aa)}for(g=0;g<a.dataSeriesIndexes.length;g++){z=a.dataSeriesIndexes[g];w=this.data[z];y=w.dataPoints;u=!0;k=[];p=w.id;this._eventManager.objectMap[p]={objectType:"dataSeries",dataSeriesIndex:z};p=D(p);s.fillStyle=
|
||||
p;if(0<h.length){var d=w._colorSet[0],A=w.lineColor=w.options.lineColor||d,B=A;b.fillStyle=d;b.strokeStyle=A;b.lineWidth=w.lineThickness;v="solid";if(b.setLineDash){var M=F(w.nullDataLineDashType,w.lineThickness);v=w.lineDashType;var W=F(v,w.lineThickness);b.setLineDash(W)}for(var X=!0,p=0;p<h.length;p++){q=h[p];var H=null,H=0<=w.dataPointIndexes[q]?y[w.dataPointIndexes[q]]:{x:q,y:null};if(!(q<a.axisX.dataInfo.viewPortMin||q>a.axisX.dataInfo.viewPortMax&&(!w.connectNullData||!X)))if("number"!==typeof H.y)w.connectNullData||
|
||||
(X||u)||c(),X=!0;else{n=a.axisX.convertValueToPixel(q);var ga=l[q]?l[q]:0;if(a.axisY.logarithmic){m[q]=H.y+(m[q]?m[q]:0);if(0>=m[q])continue;e=a.axisY.convertValueToPixel(m[q])}else e=a.axisY.convertValueToPixel(H.y),e-=ga;k.push({x:n,y:r-ga});l[q]=r-e;u||X?(!u&&w.connectNullData?(b.setLineDash&&(w.options.nullDataLineDashType||v===w.lineDashType&&w.lineDashType!==w.nullDataLineDashType)&&(u=k.pop(),v=k[k.length-1],c(),b.moveTo(x.x,x.y),k.push(v),k.push(u),v=w.nullDataLineDashType,b.setLineDash(M)),
|
||||
b.lineTo(n,e),t&&s.lineTo(n,e)):(b.beginPath(),b.moveTo(n,e),t&&(s.beginPath(),s.moveTo(n,e))),X=u=!1):(b.lineTo(n,e),t&&s.lineTo(n,e),0==p%250&&(c(),b.moveTo(n,e),t&&s.moveTo(n,e),k.push({x:n,y:r-ga})));x={x:n,y:e};p<y.length-1&&(B!==(y[p].lineColor||A)||v!==(y[p].lineDashType||w.lineDashType))&&(c(),b.beginPath(),b.moveTo(n,e),k.push({x:n,y:r-ga}),B=y[p].lineColor||A,b.strokeStyle=B,b.setLineDash&&(y[p].lineDashType?(v=y[p].lineDashType,b.setLineDash(F(v,w.lineThickness))):(v=w.lineDashType,b.setLineDash(W))));
|
||||
if(0<=w.dataPointIndexes[q]){var ha=w.dataPointIds[w.dataPointIndexes[q]];this._eventManager.objectMap[ha]={id:ha,objectType:"dataPoint",dataSeriesIndex:z,dataPointIndex:w.dataPointIndexes[q],x1:n,y1:e}}0<=w.dataPointIndexes[q]&&0!==H.markerSize&&(0<H.markerSize||0<w.markerSize)&&(q=w.getMarkerProperties(w.dataPointIndexes[q],n,e,b),f.push(q),markerColor=D(ha),t&&f.push({x:n,y:e,ctx:s,type:q.type,size:q.size,color:markerColor,borderColor:markerColor,borderThickness:q.borderThickness}));(H.indexLabel||
|
||||
w.indexLabel||H.indexLabelFormatter||w.indexLabelFormatter)&&this._indexLabels.push({chartType:"stackedArea",dataPoint:H,dataSeries:w,point:{x:n,y:e},direction:0>y[p].y===a.axisY.reversed?1:-1,color:d})}}c();b.moveTo(n,e);t&&s.moveTo(n,e)}delete w.dataPointIndexes}O.drawMarkers(f);b.restore();t&&s.restore();return{source:b,dest:this.plotArea.ctx,animationCallback:E.xClipAnimation,easingFunction:E.easing.linear,animationBase:0}}};A.prototype.renderStackedArea100=function(a){function c(){for(0<w.lineThickness&&
|
||||
b.stroke();0<k.length;){var a=k.pop();b.lineTo(a.x,a.y);t&&v.lineTo(a.x,a.y)}b.closePath();b.globalAlpha=w.fillOpacity;b.fill();b.globalAlpha=1;b.beginPath();t&&(v.closePath(),v.fill(),v.beginPath());k=[]}var b=a.targetCanvasCtx||this.plotArea.ctx;if(!(0>=a.dataSeriesIndexes.length)){var d=null,f=this.plotArea,g=[],l=[],k=[],h=[],m=[],p=0,n,e,q,r,s,x,u=a.axisY.convertValueToPixel(a.axisY.logarithmic?a.axisY.viewportMinimum:0),v=this._eventManager.ghostCtx;b.save();t&&v.save();b.beginPath();b.rect(f.x1,
|
||||
f.y1,f.width,f.height);b.clip();t&&(v.beginPath(),v.rect(f.x1,f.y1,f.width,f.height),v.clip());d=[];for(f=0;f<a.dataSeriesIndexes.length;f++){var z=a.dataSeriesIndexes[f],w=this.data[z],y=w.dataPoints;w.dataPointIndexes=[];for(p=0;p<y.length;p++)z=y[p].x.getTime?y[p].x.getTime():y[p].x,w.dataPointIndexes[z]=p,d[z]||(h.push(z),d[z]=!0);h.sort(Aa)}for(f=0;f<a.dataSeriesIndexes.length;f++){z=a.dataSeriesIndexes[f];w=this.data[z];y=w.dataPoints;s=!0;d=w.id;this._eventManager.objectMap[d]={objectType:"dataSeries",
|
||||
dataSeriesIndex:z};d=D(d);v.fillStyle=d;k=[];if(0<h.length){var d=w._colorSet[p%w._colorSet.length],A=w.lineColor=w.options.lineColor||d,B=A;b.fillStyle=d;b.strokeStyle=A;b.lineWidth=w.lineThickness;x="solid";if(b.setLineDash){var M=F(w.nullDataLineDashType,w.lineThickness);x=w.lineDashType;var W=F(x,w.lineThickness);b.setLineDash(W)}for(var X=!0,p=0;p<h.length;p++){q=h[p];var H=null,H=0<=w.dataPointIndexes[q]?y[w.dataPointIndexes[q]]:{x:q,y:null};if(!(q<a.axisX.dataInfo.viewPortMin||q>a.axisX.dataInfo.viewPortMax&&
|
||||
(!w.connectNullData||!X)))if("number"!==typeof H.y)w.connectNullData||(X||s)||c(),X=!0;else{var ga;ga=0!==a.dataPointYSums[q]?100*(H.y/a.dataPointYSums[q]):0;n=a.axisX.convertValueToPixel(q);var ha=l[q]?l[q]:0;if(a.axisY.logarithmic){m[q]=ga+(m[q]?m[q]:0);if(0>=m[q])continue;e=a.axisY.convertValueToPixel(m[q])}else e=a.axisY.convertValueToPixel(ga),e-=ha;k.push({x:n,y:u-ha});l[q]=u-e;s||X?(!s&&w.connectNullData?(b.setLineDash&&(w.options.nullDataLineDashType||x===w.lineDashType&&w.lineDashType!==
|
||||
w.nullDataLineDashType)&&(s=k.pop(),x=k[k.length-1],c(),b.moveTo(r.x,r.y),k.push(x),k.push(s),x=w.nullDataLineDashType,b.setLineDash(M)),b.lineTo(n,e),t&&v.lineTo(n,e)):(b.beginPath(),b.moveTo(n,e),t&&(v.beginPath(),v.moveTo(n,e))),X=s=!1):(b.lineTo(n,e),t&&v.lineTo(n,e),0==p%250&&(c(),b.moveTo(n,e),t&&v.moveTo(n,e),k.push({x:n,y:u-ha})));r={x:n,y:e};p<y.length-1&&(B!==(y[p].lineColor||A)||x!==(y[p].lineDashType||w.lineDashType))&&(c(),b.beginPath(),b.moveTo(n,e),k.push({x:n,y:u-ha}),B=y[p].lineColor||
|
||||
A,b.strokeStyle=B,b.setLineDash&&(y[p].lineDashType?(x=y[p].lineDashType,b.setLineDash(F(x,w.lineThickness))):(x=w.lineDashType,b.setLineDash(W))));if(0<=w.dataPointIndexes[q]){var Ga=w.dataPointIds[w.dataPointIndexes[q]];this._eventManager.objectMap[Ga]={id:Ga,objectType:"dataPoint",dataSeriesIndex:z,dataPointIndex:w.dataPointIndexes[q],x1:n,y1:e}}0<=w.dataPointIndexes[q]&&0!==H.markerSize&&(0<H.markerSize||0<w.markerSize)&&(q=w.getMarkerProperties(p,n,e,b),g.push(q),markerColor=D(Ga),t&&g.push({x:n,
|
||||
y:e,ctx:v,type:q.type,size:q.size,color:markerColor,borderColor:markerColor,borderThickness:q.borderThickness}));(H.indexLabel||w.indexLabel||H.indexLabelFormatter||w.indexLabelFormatter)&&this._indexLabels.push({chartType:"stackedArea100",dataPoint:H,dataSeries:w,point:{x:n,y:e},direction:0>y[p].y===a.axisY.reversed?1:-1,color:d})}}c();b.moveTo(n,e);t&&v.moveTo(n,e)}delete w.dataPointIndexes}O.drawMarkers(g);b.restore();t&&v.restore();return{source:b,dest:this.plotArea.ctx,animationCallback:E.xClipAnimation,
|
||||
easingFunction:E.easing.linear,animationBase:0}}};A.prototype.renderBubble=function(a){var c=a.targetCanvasCtx||this.plotArea.ctx;if(!(0>=a.dataSeriesIndexes.length)){var b=this.plotArea,d=0,f,g;c.save();t&&this._eventManager.ghostCtx.save();c.beginPath();c.rect(b.x1,b.y1,b.width,b.height);c.clip();t&&(this._eventManager.ghostCtx.beginPath(),this._eventManager.ghostCtx.rect(b.x1,b.y1,b.width,b.height),this._eventManager.ghostCtx.clip());for(var l=-Infinity,k=Infinity,h=0;h<a.dataSeriesIndexes.length;h++)for(var m=
|
||||
a.dataSeriesIndexes[h],p=this.data[m],n=p.dataPoints,e=0,d=0;d<n.length;d++)f=n[d].getTime?f=n[d].x.getTime():f=n[d].x,f<a.axisX.dataInfo.viewPortMin||f>a.axisX.dataInfo.viewPortMax||"undefined"===typeof n[d].z||(e=n[d].z,e>l&&(l=e),e<k&&(k=e));for(var q=25*Math.PI,b=Math.max(Math.pow(0.25*Math.min(b.height,b.width)/2,2)*Math.PI,q),h=0;h<a.dataSeriesIndexes.length;h++)if(m=a.dataSeriesIndexes[h],p=this.data[m],n=p.dataPoints,0<n.length)for(c.strokeStyle="#4572A7 ",d=0;d<n.length;d++)if(f=n[d].getTime?
|
||||
f=n[d].x.getTime():f=n[d].x,!(f<a.axisX.dataInfo.viewPortMin||f>a.axisX.dataInfo.viewPortMax)&&"number"===typeof n[d].y){f=a.axisX.convertValueToPixel(f);g=a.axisY.convertValueToPixel(n[d].y);var e=n[d].z,r=2*Math.max(Math.sqrt((l===k?b/2:q+(b-q)/(l-k)*(e-k))/Math.PI)<<0,1),e=p.getMarkerProperties(d,c);e.size=r;c.globalAlpha=p.fillOpacity;O.drawMarker(f,g,c,e.type,e.size,e.color,e.borderColor,e.borderThickness);c.globalAlpha=1;var s=p.dataPointIds[d];this._eventManager.objectMap[s]={id:s,objectType:"dataPoint",
|
||||
dataSeriesIndex:m,dataPointIndex:d,x1:f,y1:g,size:r};r=D(s);t&&O.drawMarker(f,g,this._eventManager.ghostCtx,e.type,e.size,r,r,e.borderThickness);(n[d].indexLabel||p.indexLabel||n[d].indexLabelFormatter||p.indexLabelFormatter)&&this._indexLabels.push({chartType:"bubble",dataPoint:n[d],dataSeries:p,point:{x:f,y:g},direction:1,bounds:{x1:f-e.size/2,y1:g-e.size/2,x2:f+e.size/2,y2:g+e.size/2},color:null})}c.restore();t&&this._eventManager.ghostCtx.restore();return{source:c,dest:this.plotArea.ctx,animationCallback:E.fadeInAnimation,
|
||||
easingFunction:E.easing.easeInQuad,animationBase:0}}};A.prototype.renderScatter=function(a){var c=a.targetCanvasCtx||this.plotArea.ctx;if(!(0>=a.dataSeriesIndexes.length)){var b=this.plotArea,d=0,f,g;c.save();t&&this._eventManager.ghostCtx.save();c.beginPath();c.rect(b.x1,b.y1,b.width,b.height);c.clip();t&&(this._eventManager.ghostCtx.beginPath(),this._eventManager.ghostCtx.rect(b.x1,b.y1,b.width,b.height),this._eventManager.ghostCtx.clip());for(var l=0;l<a.dataSeriesIndexes.length;l++){var k=a.dataSeriesIndexes[l],
|
||||
h=this.data[k],m=h.dataPoints;if(0<m.length){c.strokeStyle="#4572A7 ";Math.pow(0.3*Math.min(b.height,b.width)/2,2);for(var p=0,n=0,d=0;d<m.length;d++)if(f=m[d].getTime?f=m[d].x.getTime():f=m[d].x,!(f<a.axisX.dataInfo.viewPortMin||f>a.axisX.dataInfo.viewPortMax)&&"number"===typeof m[d].y){f=a.axisX.convertValueToPixel(f);g=a.axisY.convertValueToPixel(m[d].y);var e=h.getMarkerProperties(d,f,g,c);c.globalAlpha=h.fillOpacity;O.drawMarker(e.x,e.y,e.ctx,e.type,e.size,e.color,e.borderColor,e.borderThickness);
|
||||
c.globalAlpha=1;Math.sqrt((p-f)*(p-f)+(n-g)*(n-g))<Math.min(e.size,5)&&m.length>Math.min(this.plotArea.width,this.plotArea.height)||(p=h.dataPointIds[d],this._eventManager.objectMap[p]={id:p,objectType:"dataPoint",dataSeriesIndex:k,dataPointIndex:d,x1:f,y1:g},p=D(p),t&&O.drawMarker(e.x,e.y,this._eventManager.ghostCtx,e.type,e.size,p,p,e.borderThickness),(m[d].indexLabel||h.indexLabel||m[d].indexLabelFormatter||h.indexLabelFormatter)&&this._indexLabels.push({chartType:"scatter",dataPoint:m[d],dataSeries:h,
|
||||
point:{x:f,y:g},direction:1,bounds:{x1:f-e.size/2,y1:g-e.size/2,x2:f+e.size/2,y2:g+e.size/2},color:null}),p=f,n=g)}}}c.restore();t&&this._eventManager.ghostCtx.restore();return{source:c,dest:this.plotArea.ctx,animationCallback:E.fadeInAnimation,easingFunction:E.easing.easeInQuad,animationBase:0}}};A.prototype.renderCandlestick=function(a){var c=a.targetCanvasCtx||this.plotArea.ctx,b=this._eventManager.ghostCtx;if(!(0>=a.dataSeriesIndexes.length)){var d=null,d=this.plotArea,f=0,g,l,k,h,m,p,f=this.dataPointMinWidth?
|
||||
this.dataPointMinWidth:this.dataPointWidth?this.dataPointWidth:1;g=this.dataPointMaxWidth?this.dataPointMaxWidth:this.dataPointWidth?this.dataPointWidth:0.015*this.width;var n=a.axisX.dataInfo.minDiff;isFinite(n)||(n=0.3*Math.abs(a.axisX.range));n=this.dataPointWidth?this.dataPointWidth:0.7*d.width*(a.axisX.logarithmic?Math.log(n)/Math.log(a.axisX.range):Math.abs(n)/Math.abs(a.axisX.range))<<0;this.dataPointMaxWidth&&f>g&&(f=Math.min(this.dataPointWidth?this.dataPointWidth:Infinity,g));!this.dataPointMaxWidth&&
|
||||
(this.dataPointMinWidth&&g<f)&&(g=Math.max(this.dataPointWidth?this.dataPointWidth:-Infinity,f));n<f&&(n=f);n>g&&(n=g);c.save();t&&b.save();c.beginPath();c.rect(d.x1,d.y1,d.width,d.height);c.clip();t&&(b.beginPath(),b.rect(d.x1,d.y1,d.width,d.height),b.clip());for(var e=0;e<a.dataSeriesIndexes.length;e++){var q=a.dataSeriesIndexes[e],r=this.data[q],s=r.dataPoints;if(0<s.length)for(var x=5<n&&r.bevelEnabled?!0:!1,f=0;f<s.length;f++)if(s[f].getTime?p=s[f].x.getTime():p=s[f].x,!(p<a.axisX.dataInfo.viewPortMin||
|
||||
p>a.axisX.dataInfo.viewPortMax)&&null!==s[f].y&&s[f].y.length&&"number"===typeof s[f].y[0]&&"number"===typeof s[f].y[1]&&"number"===typeof s[f].y[2]&&"number"===typeof s[f].y[3]){g=a.axisX.convertValueToPixel(p);l=a.axisY.convertValueToPixel(s[f].y[0]);k=a.axisY.convertValueToPixel(s[f].y[1]);h=a.axisY.convertValueToPixel(s[f].y[2]);m=a.axisY.convertValueToPixel(s[f].y[3]);var u=g-n/2<<0,v=u+n<<0,d=s[f].color?s[f].color:r._colorSet[0],z=Math.round(Math.max(1,0.15*n)),w=0===z%2?0:0.5,y=r.dataPointIds[f];
|
||||
this._eventManager.objectMap[y]={id:y,objectType:"dataPoint",dataSeriesIndex:q,dataPointIndex:f,x1:u,y1:l,x2:v,y2:k,x3:g,y3:h,x4:g,y4:m,borderThickness:z,color:d};c.strokeStyle=d;c.beginPath();c.lineWidth=z;b.lineWidth=Math.max(z,4);"candlestick"===r.type?(c.moveTo(g-w,k),c.lineTo(g-w,Math.min(l,m)),c.stroke(),c.moveTo(g-w,Math.max(l,m)),c.lineTo(g-w,h),c.stroke(),N(c,u,Math.min(l,m),v,Math.max(l,m),s[f].y[0]<=s[f].y[3]?r.risingColor:d,z,d,x,x,!1,!1,r.fillOpacity),t&&(d=D(y),b.strokeStyle=d,b.moveTo(g-
|
||||
w,k),b.lineTo(g-w,Math.min(l,m)),b.stroke(),b.moveTo(g-w,Math.max(l,m)),b.lineTo(g-w,h),b.stroke(),N(b,u,Math.min(l,m),v,Math.max(l,m),d,0,null,!1,!1,!1,!1))):"ohlc"===r.type&&(c.moveTo(g-w,k),c.lineTo(g-w,h),c.stroke(),c.beginPath(),c.moveTo(g,l),c.lineTo(u,l),c.stroke(),c.beginPath(),c.moveTo(g,m),c.lineTo(v,m),c.stroke(),t&&(d=D(y),b.strokeStyle=d,b.moveTo(g-w,k),b.lineTo(g-w,h),b.stroke(),b.beginPath(),b.moveTo(g,l),b.lineTo(u,l),b.stroke(),b.beginPath(),b.moveTo(g,m),b.lineTo(v,m),b.stroke()));
|
||||
(s[f].indexLabel||r.indexLabel||s[f].indexLabelFormatter||r.indexLabelFormatter)&&this._indexLabels.push({chartType:r.type,dataPoint:s[f],dataSeries:r,point:{x:u+(v-u)/2,y:a.axisY.reversed?h:k},direction:1,bounds:{x1:u,y1:Math.min(k,h),x2:v,y2:Math.max(k,h)},color:d})}}c.restore();t&&b.restore();return{source:c,dest:this.plotArea.ctx,animationCallback:E.fadeInAnimation,easingFunction:E.easing.easeInQuad,animationBase:0}}};A.prototype.renderRangeColumn=function(a){var c=a.targetCanvasCtx||this.plotArea.ctx;
|
||||
if(!(0>=a.dataSeriesIndexes.length)){var b=null,d=this.plotArea,f=0,g,l,f=this.dataPointMinWidth?this.dataPointMinWidth:this.dataPointWidth?this.dataPointWidth:1;g=this.dataPointMaxWidth?this.dataPointMaxWidth:this.dataPointWidth?this.dataPointWidth:0.03*this.width;var k=a.axisX.dataInfo.minDiff;isFinite(k)||(k=0.3*Math.abs(a.axisX.range));k=this.dataPointWidth?this.dataPointWidth:0.9*(d.width*(a.axisX.logarithmic?Math.log(k)/Math.log(a.axisX.range):Math.abs(k)/Math.abs(a.axisX.range))/a.plotType.totalDataSeries)<<
|
||||
0;this.dataPointMaxWidth&&f>g&&(f=Math.min(this.dataPointWidth?this.dataPointWidth:Infinity,g));!this.dataPointMaxWidth&&(this.dataPointMinWidth&&g<f)&&(g=Math.max(this.dataPointWidth?this.dataPointWidth:-Infinity,f));k<f&&(k=f);k>g&&(k=g);c.save();t&&this._eventManager.ghostCtx.save();c.beginPath();c.rect(d.x1,d.y1,d.width,d.height);c.clip();t&&(this._eventManager.ghostCtx.beginPath(),this._eventManager.ghostCtx.rect(d.x1,d.y1,d.width,d.height),this._eventManager.ghostCtx.clip());for(var h=0;h<a.dataSeriesIndexes.length;h++){var m=
|
||||
a.dataSeriesIndexes[h],p=this.data[m],n=p.dataPoints;if(0<n.length)for(var e=5<k&&p.bevelEnabled?!0:!1,f=0;f<n.length;f++)if(n[f].getTime?l=n[f].x.getTime():l=n[f].x,!(l<a.axisX.dataInfo.viewPortMin||l>a.axisX.dataInfo.viewPortMax)&&null!==n[f].y&&n[f].y.length&&"number"===typeof n[f].y[0]&&"number"===typeof n[f].y[1]){b=a.axisX.convertValueToPixel(l);d=a.axisY.convertValueToPixel(n[f].y[0]);g=a.axisY.convertValueToPixel(n[f].y[1]);var q=a.axisX.reversed?b+a.plotType.totalDataSeries*k/2-(a.previousDataSeriesCount+
|
||||
h)*k<<0:b-a.plotType.totalDataSeries*k/2+(a.previousDataSeriesCount+h)*k<<0,r=a.axisX.reversed?q-k<<0:q+k<<0,b=n[f].color?n[f].color:p._colorSet[f%p._colorSet.length];if(d>g){var s=d,d=g;g=s}s=p.dataPointIds[f];this._eventManager.objectMap[s]={id:s,objectType:"dataPoint",dataSeriesIndex:m,dataPointIndex:f,x1:q,y1:d,x2:r,y2:g};N(c,q,d,r,g,b,0,b,e,e,!1,!1,p.fillOpacity);b=D(s);t&&N(this._eventManager.ghostCtx,q,d,r,g,b,0,null,!1,!1,!1,!1);if(n[f].indexLabel||p.indexLabel||n[f].indexLabelFormatter||
|
||||
p.indexLabelFormatter)this._indexLabels.push({chartType:"rangeColumn",dataPoint:n[f],dataSeries:p,indexKeyword:0,point:{x:q+(r-q)/2,y:n[f].y[1]>=n[f].y[0]?g:d},direction:n[f].y[1]>=n[f].y[0]?-1:1,bounds:{x1:q,y1:Math.min(d,g),x2:r,y2:Math.max(d,g)},color:b}),this._indexLabels.push({chartType:"rangeColumn",dataPoint:n[f],dataSeries:p,indexKeyword:1,point:{x:q+(r-q)/2,y:n[f].y[1]>=n[f].y[0]?d:g},direction:n[f].y[1]>=n[f].y[0]?1:-1,bounds:{x1:q,y1:Math.min(d,g),x2:r,y2:Math.max(d,g)},color:b})}}c.restore();
|
||||
t&&this._eventManager.ghostCtx.restore();return{source:c,dest:this.plotArea.ctx,animationCallback:E.fadeInAnimation,easingFunction:E.easing.easeInQuad,animationBase:0}}};A.prototype.renderRangeBar=function(a){var c=a.targetCanvasCtx||this.plotArea.ctx;if(!(0>=a.dataSeriesIndexes.length)){var b=null,d=this.plotArea,f=0,g,l,k,f=this.dataPointMinWidth?this.dataPointMinWidth:this.dataPointWidth?this.dataPointWidth:1;g=this.dataPointMaxWidth?this.dataPointMaxWidth:this.dataPointWidth?this.dataPointWidth:
|
||||
Math.min(0.15*this.height,0.9*(this.plotArea.height/a.plotType.totalDataSeries))<<0;var h=a.axisX.dataInfo.minDiff;isFinite(h)||(h=0.3*Math.abs(a.axisX.range));h=this.dataPointWidth?this.dataPointWidth:0.9*(d.height*(a.axisX.logarithmic?Math.log(h)/Math.log(a.axisX.range):Math.abs(h)/Math.abs(a.axisX.range))/a.plotType.totalDataSeries)<<0;this.dataPointMaxWidth&&f>g&&(f=Math.min(this.dataPointWidth?this.dataPointWidth:Infinity,g));!this.dataPointMaxWidth&&(this.dataPointMinWidth&&g<f)&&(g=Math.max(this.dataPointWidth?
|
||||
this.dataPointWidth:-Infinity,f));h<f&&(h=f);h>g&&(h=g);c.save();t&&this._eventManager.ghostCtx.save();c.beginPath();c.rect(d.x1,d.y1,d.width,d.height);c.clip();t&&(this._eventManager.ghostCtx.beginPath(),this._eventManager.ghostCtx.rect(d.x1,d.y1,d.width,d.height),this._eventManager.ghostCtx.clip());for(var m=0;m<a.dataSeriesIndexes.length;m++){var p=a.dataSeriesIndexes[m],n=this.data[p],e=n.dataPoints;if(0<e.length){var q=5<h&&n.bevelEnabled?!0:!1;c.strokeStyle="#4572A7 ";for(f=0;f<e.length;f++)if(e[f].getTime?
|
||||
k=e[f].x.getTime():k=e[f].x,!(k<a.axisX.dataInfo.viewPortMin||k>a.axisX.dataInfo.viewPortMax)&&null!==e[f].y&&e[f].y.length&&"number"===typeof e[f].y[0]&&"number"===typeof e[f].y[1]){d=a.axisY.convertValueToPixel(e[f].y[0]);g=a.axisY.convertValueToPixel(e[f].y[1]);l=a.axisX.convertValueToPixel(k);l=a.axisX.reversed?l+a.plotType.totalDataSeries*h/2-(a.previousDataSeriesCount+m)*h<<0:l-a.plotType.totalDataSeries*h/2+(a.previousDataSeriesCount+m)*h<<0;var r=a.axisX.reversed?l-h<<0:l+h<<0;d>g&&(b=d,d=
|
||||
g,g=b);b=e[f].color?e[f].color:n._colorSet[f%n._colorSet.length];N(c,d,l,g,r,b,0,null,q,!1,!1,!1,n.fillOpacity);b=n.dataPointIds[f];this._eventManager.objectMap[b]={id:b,objectType:"dataPoint",dataSeriesIndex:p,dataPointIndex:f,x1:d,y1:l,x2:g,y2:r};b=D(b);t&&N(this._eventManager.ghostCtx,d,l,g,r,b,0,null,!1,!1,!1,!1);if(e[f].indexLabel||n.indexLabel||e[f].indexLabelFormatter||n.indexLabelFormatter)this._indexLabels.push({chartType:"rangeBar",dataPoint:e[f],dataSeries:n,indexKeyword:0,point:{x:e[f].y[1]>=
|
||||
e[f].y[0]?d:g,y:l+(r-l)/2},direction:e[f].y[1]>=e[f].y[0]?-1:1,bounds:{x1:Math.min(d,g),y1:l,x2:Math.max(d,g),y2:r},color:b}),this._indexLabels.push({chartType:"rangeBar",dataPoint:e[f],dataSeries:n,indexKeyword:1,point:{x:e[f].y[1]>=e[f].y[0]?g:d,y:l+(r-l)/2},direction:e[f].y[1]>=e[f].y[0]?1:-1,bounds:{x1:Math.min(d,g),y1:l,x2:Math.max(d,g),y2:r},color:b})}}}c.restore();t&&this._eventManager.ghostCtx.restore();return{source:c,dest:this.plotArea.ctx,animationCallback:E.fadeInAnimation,easingFunction:E.easing.easeInQuad,
|
||||
animationBase:0}}};A.prototype.renderRangeArea=function(a){function c(){if(x){var a=null;0<h.lineThickness&&b.stroke();for(var c=l.length-1;0<=c;c--)a=l[c],b.lineTo(a.x,a.y),d.lineTo(a.x,a.y);b.closePath();b.globalAlpha=h.fillOpacity;b.fill();b.globalAlpha=1;d.fill();if(0<h.lineThickness){b.beginPath();b.moveTo(a.x,a.y);for(c=0;c<l.length;c++)a=l[c],b.lineTo(a.x,a.y);b.stroke()}b.beginPath();b.moveTo(e,q);d.beginPath();d.moveTo(e,q);x={x:e,y:q};l=[];l.push({x:e,y:r})}}var b=a.targetCanvasCtx||this.plotArea.ctx;
|
||||
if(!(0>=a.dataSeriesIndexes.length)){var d=this._eventManager.ghostCtx,f=[],g=this.plotArea;b.save();t&&d.save();b.beginPath();b.rect(g.x1,g.y1,g.width,g.height);b.clip();t&&(d.beginPath(),d.rect(g.x1,g.y1,g.width,g.height),d.clip());for(g=0;g<a.dataSeriesIndexes.length;g++){var l=[],k=a.dataSeriesIndexes[g],h=this.data[k],m=h.dataPoints,f=h.id;this._eventManager.objectMap[f]={objectType:"dataSeries",dataSeriesIndex:k};f=D(f);d.fillStyle=f;var f=[],p=!0,n=0,e,q,r,s,x=null;if(0<m.length){var u=h._colorSet[n%
|
||||
h._colorSet.length],v=h.lineColor=h.options.lineColor||u,z=v;b.fillStyle=u;b.strokeStyle=v;b.lineWidth=h.lineThickness;var w="solid";if(b.setLineDash){var y=F(h.nullDataLineDashType,h.lineThickness),w=h.lineDashType,A=F(w,h.lineThickness);b.setLineDash(A)}for(var B=!0;n<m.length;n++)if(s=m[n].x.getTime?m[n].x.getTime():m[n].x,!(s<a.axisX.dataInfo.viewPortMin||s>a.axisX.dataInfo.viewPortMax&&(!h.connectNullData||!B)))if(null!==m[n].y&&m[n].y.length&&"number"===typeof m[n].y[0]&&"number"===typeof m[n].y[1]){e=
|
||||
a.axisX.convertValueToPixel(s);q=a.axisY.convertValueToPixel(m[n].y[0]);r=a.axisY.convertValueToPixel(m[n].y[1]);p||B?(h.connectNullData&&!p?(b.setLineDash&&(h.options.nullDataLineDashType||w===h.lineDashType&&h.lineDashType!==h.nullDataLineDashType)&&(l[l.length-1].newLineDashArray=A,w=h.nullDataLineDashType,b.setLineDash(y)),b.lineTo(e,q),t&&d.lineTo(e,q),l.push({x:e,y:r})):(b.beginPath(),b.moveTo(e,q),x={x:e,y:q},l=[],l.push({x:e,y:r}),t&&(d.beginPath(),d.moveTo(e,q))),B=p=!1):(b.lineTo(e,q),l.push({x:e,
|
||||
y:r}),t&&d.lineTo(e,q),0==n%250&&c());s=h.dataPointIds[n];this._eventManager.objectMap[s]={id:s,objectType:"dataPoint",dataSeriesIndex:k,dataPointIndex:n,x1:e,y1:q,y2:r};n<m.length-1&&(z!==(m[n].lineColor||v)||w!==(m[n].lineDashType||h.lineDashType))&&(c(),z=m[n].lineColor||v,l[l.length-1].newStrokeStyle=z,b.strokeStyle=z,b.setLineDash&&(m[n].lineDashType?(w=m[n].lineDashType,l[l.length-1].newLineDashArray=F(w,h.lineThickness),b.setLineDash(l[l.length-1].newLineDashArray)):(w=h.lineDashType,l[l.length-
|
||||
1].newLineDashArray=A,b.setLineDash(A))));if(0!==m[n].markerSize&&(0<m[n].markerSize||0<h.markerSize)){var M=h.getMarkerProperties(n,e,r,b);f.push(M);var W=D(s);t&&f.push({x:e,y:r,ctx:d,type:M.type,size:M.size,color:W,borderColor:W,borderThickness:M.borderThickness});M=h.getMarkerProperties(n,e,q,b);f.push(M);W=D(s);t&&f.push({x:e,y:q,ctx:d,type:M.type,size:M.size,color:W,borderColor:W,borderThickness:M.borderThickness})}if(m[n].indexLabel||h.indexLabel||m[n].indexLabelFormatter||h.indexLabelFormatter)this._indexLabels.push({chartType:"rangeArea",
|
||||
dataPoint:m[n],dataSeries:h,indexKeyword:0,point:{x:e,y:q},direction:m[n].y[0]>m[n].y[1]===a.axisY.reversed?-1:1,color:u}),this._indexLabels.push({chartType:"rangeArea",dataPoint:m[n],dataSeries:h,indexKeyword:1,point:{x:e,y:r},direction:m[n].y[0]>m[n].y[1]===a.axisY.reversed?1:-1,color:u})}else B||p||c(),B=!0;c();O.drawMarkers(f)}}b.restore();t&&this._eventManager.ghostCtx.restore();return{source:b,dest:this.plotArea.ctx,animationCallback:E.xClipAnimation,easingFunction:E.easing.linear,animationBase:0}}};
|
||||
A.prototype.renderRangeSplineArea=function(a){function c(a,c){var e=wa(q,2);if(0<e.length){if(0<k.lineThickness){b.strokeStyle=c;b.setLineDash&&b.setLineDash(a);b.beginPath();b.moveTo(e[0].x,e[0].y);for(var f=0;f<e.length-3;f+=3){if(e[f].newStrokeStyle||e[f].newLineDashArray)b.stroke(),b.beginPath(),b.moveTo(e[f].x,e[f].y),e[f].newStrokeStyle&&(b.strokeStyle=e[f].newStrokeStyle),e[f].newLineDashArray&&b.setLineDash(e[f].newLineDashArray);b.bezierCurveTo(e[f+1].x,e[f+1].y,e[f+2].x,e[f+2].y,e[f+3].x,
|
||||
e[f+3].y)}b.stroke()}b.beginPath();b.moveTo(e[0].x,e[0].y);t&&(d.beginPath(),d.moveTo(e[0].x,e[0].y));for(f=0;f<e.length-3;f+=3)b.bezierCurveTo(e[f+1].x,e[f+1].y,e[f+2].x,e[f+2].y,e[f+3].x,e[f+3].y),t&&d.bezierCurveTo(e[f+1].x,e[f+1].y,e[f+2].x,e[f+2].y,e[f+3].x,e[f+3].y);e=wa(r,2);b.lineTo(r[r.length-1].x,r[r.length-1].y);for(f=e.length-1;2<f;f-=3)b.bezierCurveTo(e[f-1].x,e[f-1].y,e[f-2].x,e[f-2].y,e[f-3].x,e[f-3].y),t&&d.bezierCurveTo(e[f-1].x,e[f-1].y,e[f-2].x,e[f-2].y,e[f-3].x,e[f-3].y);b.closePath();
|
||||
b.globalAlpha=k.fillOpacity;b.fill();t&&(d.closePath(),d.fill());b.globalAlpha=1;if(0<k.lineThickness){b.strokeStyle=c;b.setLineDash&&b.setLineDash(a);b.beginPath();b.moveTo(e[0].x,e[0].y);for(var g=f=0;f<e.length-3;f+=3,g++){if(q[g].newStrokeStyle||q[g].newLineDashArray)b.stroke(),b.beginPath(),b.moveTo(e[f].x,e[f].y),q[g].newStrokeStyle&&(b.strokeStyle=q[g].newStrokeStyle),q[g].newLineDashArray&&b.setLineDash(q[g].newLineDashArray);b.bezierCurveTo(e[f+1].x,e[f+1].y,e[f+2].x,e[f+2].y,e[f+3].x,e[f+
|
||||
3].y)}b.stroke()}b.beginPath()}}var b=a.targetCanvasCtx||this.plotArea.ctx;if(!(0>=a.dataSeriesIndexes.length)){var d=this._eventManager.ghostCtx,f=[],g=this.plotArea;b.save();t&&d.save();b.beginPath();b.rect(g.x1,g.y1,g.width,g.height);b.clip();t&&(d.beginPath(),d.rect(g.x1,g.y1,g.width,g.height),d.clip());for(g=0;g<a.dataSeriesIndexes.length;g++){var l=a.dataSeriesIndexes[g],k=this.data[l],h=k.dataPoints,f=k.id;this._eventManager.objectMap[f]={objectType:"dataSeries",dataSeriesIndex:l};f=D(f);d.fillStyle=
|
||||
f;var f=[],m=0,p,n,e,q=[],r=[];if(0<h.length){var s=k._colorSet[m%k._colorSet.length],x=k.lineColor=k.options.lineColor||s,u=x;b.fillStyle=s;b.lineWidth=k.lineThickness;var v="solid",z;if(b.setLineDash){var w=F(k.nullDataLineDashType,k.lineThickness),v=k.lineDashType;z=F(v,k.lineThickness)}for(n=!1;m<h.length;m++)if(p=h[m].x.getTime?h[m].x.getTime():h[m].x,!(p<a.axisX.dataInfo.viewPortMin||p>a.axisX.dataInfo.viewPortMax&&(!k.connectNullData||!n)))if(null!==h[m].y&&h[m].y.length&&"number"===typeof h[m].y[0]&&
|
||||
"number"===typeof h[m].y[1]){p=a.axisX.convertValueToPixel(p);n=a.axisY.convertValueToPixel(h[m].y[0]);e=a.axisY.convertValueToPixel(h[m].y[1]);var y=k.dataPointIds[m];this._eventManager.objectMap[y]={id:y,objectType:"dataPoint",dataSeriesIndex:l,dataPointIndex:m,x1:p,y1:n,y2:e};q[q.length]={x:p,y:n};r[r.length]={x:p,y:e};m<h.length-1&&(u!==(h[m].lineColor||x)||v!==(h[m].lineDashType||k.lineDashType))&&(u=h[m].lineColor||x,q[q.length-1].newStrokeStyle=u,b.setLineDash&&(h[m].lineDashType?(v=h[m].lineDashType,
|
||||
q[q.length-1].newLineDashArray=F(v,k.lineThickness)):(v=k.lineDashType,q[q.length-1].newLineDashArray=z)));if(0!==h[m].markerSize&&(0<h[m].markerSize||0<k.markerSize)){var A=k.getMarkerProperties(m,p,n,b);f.push(A);var B=D(y);t&&f.push({x:p,y:n,ctx:d,type:A.type,size:A.size,color:B,borderColor:B,borderThickness:A.borderThickness});A=k.getMarkerProperties(m,p,e,b);f.push(A);B=D(y);t&&f.push({x:p,y:e,ctx:d,type:A.type,size:A.size,color:B,borderColor:B,borderThickness:A.borderThickness})}if(h[m].indexLabel||
|
||||
k.indexLabel||h[m].indexLabelFormatter||k.indexLabelFormatter)this._indexLabels.push({chartType:"rangeSplineArea",dataPoint:h[m],dataSeries:k,indexKeyword:0,point:{x:p,y:n},direction:h[m].y[0]<=h[m].y[1]?-1:1,color:s}),this._indexLabels.push({chartType:"rangeSplineArea",dataPoint:h[m],dataSeries:k,indexKeyword:1,point:{x:p,y:e},direction:h[m].y[0]<=h[m].y[1]?1:-1,color:s});n=!1}else 0<m&&!n&&(k.connectNullData?b.setLineDash&&(0<q.length&&(k.options.nullDataLineDashType||!h[m-1].lineDashType))&&(q[q.length-
|
||||
1].newLineDashArray=w,v=k.nullDataLineDashType):(c(z,x),q=[],r=[])),n=!0;c(z,x);O.drawMarkers(f)}}b.restore();t&&this._eventManager.ghostCtx.restore();return{source:b,dest:this.plotArea.ctx,animationCallback:E.xClipAnimation,easingFunction:E.easing.linear,animationBase:0}}};var Ha=function(a,c,b,d,f,g,l,k,h){if(!(0>b)){"undefined"===typeof k&&(k=1);if(!t){var m=Number((l%(2*Math.PI)).toFixed(8));Number((g%(2*Math.PI)).toFixed(8))===m&&(l-=1E-4)}a.save();a.globalAlpha=k;"pie"===f?(a.beginPath(),a.moveTo(c.x,
|
||||
c.y),a.arc(c.x,c.y,b,g,l,!1),a.fillStyle=d,a.strokeStyle="white",a.lineWidth=2,a.closePath(),a.fill()):"doughnut"===f&&(a.beginPath(),a.arc(c.x,c.y,b,g,l,!1),0<=h&&a.arc(c.x,c.y,h*b,l,g,!0),a.closePath(),a.fillStyle=d,a.strokeStyle="white",a.lineWidth=2,a.fill());a.globalAlpha=1;a.restore()}};A.prototype.renderPie=function(a){function c(){if(m&&p){for(var a=0,b=0,c=0,d=0,f=0;f<p.length;f++){var g=p[f],k=m.dataPointIds[f],l={id:k,objectType:"dataPoint",dataPointIndex:f,dataSeriesIndex:0};q.push(l);
|
||||
var n={percent:null,total:null},r=null,n=h.getPercentAndTotal(m,g);if(m.indexLabelFormatter||g.indexLabelFormatter)r={chart:h.options,dataSeries:m,dataPoint:g,total:n.total,percent:n.percent};n=g.indexLabelFormatter?g.indexLabelFormatter(r):g.indexLabel?h.replaceKeywordsWithValue(g.indexLabel,g,m,f):m.indexLabelFormatter?m.indexLabelFormatter(r):m.indexLabel?h.replaceKeywordsWithValue(m.indexLabel,g,m,f):g.label?g.label:"";h._eventManager.objectMap[k]=l;l.center={x:z.x,y:z.y};l.y=g.y;l.radius=B;l.percentInnerRadius=
|
||||
M;l.indexLabelText=n;l.indexLabelPlacement=m.indexLabelPlacement;l.indexLabelLineColor=g.indexLabelLineColor?g.indexLabelLineColor:m.options.indexLabelLineColor?m.options.indexLabelLineColor:g.color?g.color:m._colorSet[f%m._colorSet.length];l.indexLabelLineThickness=y(g.indexLabelLineThickness)?m.indexLabelLineThickness:g.indexLabelLineThickness;l.indexLabelLineDashType=g.indexLabelLineDashType?g.indexLabelLineDashType:m.indexLabelLineDashType;l.indexLabelFontColor=g.indexLabelFontColor?g.indexLabelFontColor:
|
||||
m.indexLabelFontColor;l.indexLabelFontStyle=g.indexLabelFontStyle?g.indexLabelFontStyle:m.indexLabelFontStyle;l.indexLabelFontWeight=g.indexLabelFontWeight?g.indexLabelFontWeight:m.indexLabelFontWeight;l.indexLabelFontSize=y(g.indexLabelFontSize)?m.indexLabelFontSize:g.indexLabelFontSize;l.indexLabelFontFamily=g.indexLabelFontFamily?g.indexLabelFontFamily:m.indexLabelFontFamily;l.indexLabelBackgroundColor=g.indexLabelBackgroundColor?g.indexLabelBackgroundColor:m.options.indexLabelBackgroundColor?
|
||||
m.options.indexLabelBackgroundColor:m.indexLabelBackgroundColor;l.indexLabelMaxWidth=g.indexLabelMaxWidth?g.indexLabelMaxWidth:m.indexLabelMaxWidth?m.indexLabelMaxWidth:0.33*e.width;l.indexLabelWrap="undefined"!==typeof g.indexLabelWrap?g.indexLabelWrap:m.indexLabelWrap;l.startAngle=0===f?m.startAngle?m.startAngle/180*Math.PI:0:q[f-1].endAngle;l.startAngle=(l.startAngle+2*Math.PI)%(2*Math.PI);l.endAngle=l.startAngle+2*Math.PI/t*Math.abs(g.y);g=(l.endAngle+l.startAngle)/2;g=(g+2*Math.PI)%(2*Math.PI);
|
||||
l.midAngle=g;if(l.midAngle>Math.PI/2-u&&l.midAngle<Math.PI/2+u){if(0===a||q[c].midAngle>l.midAngle)c=f;a++}else if(l.midAngle>3*Math.PI/2-u&&l.midAngle<3*Math.PI/2+u){if(0===b||q[d].midAngle>l.midAngle)d=f;b++}l.hemisphere=g>Math.PI/2&&g<=3*Math.PI/2?"left":"right";l.indexLabelTextBlock=new V(h.plotArea.ctx,{fontSize:l.indexLabelFontSize,fontFamily:l.indexLabelFontFamily,fontColor:l.indexLabelFontColor,fontStyle:l.indexLabelFontStyle,fontWeight:l.indexLabelFontWeight,horizontalAlign:"left",backgroundColor:l.indexLabelBackgroundColor,
|
||||
maxWidth:l.indexLabelMaxWidth,maxHeight:l.indexLabelWrap?5*l.indexLabelFontSize:1.5*l.indexLabelFontSize,text:l.indexLabelText,padding:0,textBaseline:"top"});l.indexLabelTextBlock.measureText()}k=g=0;n=!1;for(f=0;f<p.length;f++)l=q[(c+f)%p.length],1<a&&(l.midAngle>Math.PI/2-u&&l.midAngle<Math.PI/2+u)&&(g<=a/2&&!n?(l.hemisphere="right",g++):(l.hemisphere="left",n=!0));n=!1;for(f=0;f<p.length;f++)l=q[(d+f)%p.length],1<b&&(l.midAngle>3*Math.PI/2-u&&l.midAngle<3*Math.PI/2+u)&&(k<=b/2&&!n?(l.hemisphere=
|
||||
"left",k++):(l.hemisphere="right",n=!0))}}function b(a){var b=h.plotArea.ctx;b.clearRect(e.x1,e.y1,e.width,e.height);b.fillStyle=h.backgroundColor;b.fillRect(e.x1,e.y1,e.width,e.height);for(b=0;b<p.length;b++){var c=q[b].startAngle,d=q[b].endAngle;if(d>c){var f=0.07*B*Math.cos(q[b].midAngle),g=0.07*B*Math.sin(q[b].midAngle),k=!1;if(p[b].exploded){if(1E-9<Math.abs(q[b].center.x-(z.x+f))||1E-9<Math.abs(q[b].center.y-(z.y+g)))q[b].center.x=z.x+f*a,q[b].center.y=z.y+g*a,k=!0}else if(0<Math.abs(q[b].center.x-
|
||||
z.x)||0<Math.abs(q[b].center.y-z.y))q[b].center.x=z.x+f*(1-a),q[b].center.y=z.y+g*(1-a),k=!0;k&&(f={},f.dataSeries=m,f.dataPoint=m.dataPoints[b],f.index=b,h.toolTip.highlightObjects([f]));Ha(h.plotArea.ctx,q[b].center,q[b].radius,p[b].color?p[b].color:m._colorSet[b%m._colorSet.length],m.type,c,d,m.fillOpacity,q[b].percentInnerRadius)}}a=h.plotArea.ctx;a.save();a.fillStyle="black";a.strokeStyle="grey";a.textBaseline="middle";a.lineJoin="round";for(b=b=0;b<p.length;b++)c=q[b],c.indexLabelText&&(c.indexLabelTextBlock.y-=
|
||||
c.indexLabelTextBlock.height/2,d=0,d="left"===c.hemisphere?"inside"!==m.indexLabelPlacement?-(c.indexLabelTextBlock.width+n):-c.indexLabelTextBlock.width/2:"inside"!==m.indexLabelPlacement?n:-c.indexLabelTextBlock.width/2,c.indexLabelTextBlock.x+=d,c.indexLabelTextBlock.render(!0),c.indexLabelTextBlock.x-=d,c.indexLabelTextBlock.y+=c.indexLabelTextBlock.height/2,"inside"!==c.indexLabelPlacement&&0<c.indexLabelLineThickness&&(d=c.center.x+B*Math.cos(c.midAngle),f=c.center.y+B*Math.sin(c.midAngle),
|
||||
a.strokeStyle=c.indexLabelLineColor,a.lineWidth=c.indexLabelLineThickness,a.setLineDash&&a.setLineDash(F(c.indexLabelLineDashType,c.indexLabelLineThickness)),a.beginPath(),a.moveTo(d,f),a.lineTo(c.indexLabelTextBlock.x,c.indexLabelTextBlock.y),a.lineTo(c.indexLabelTextBlock.x+("left"===c.hemisphere?-n:n),c.indexLabelTextBlock.y),a.stroke()),a.lineJoin="miter");a.save()}function d(a,b){var c=0,c=a.indexLabelTextBlock.y-a.indexLabelTextBlock.height/2,d=a.indexLabelTextBlock.y+a.indexLabelTextBlock.height/
|
||||
2,e=b.indexLabelTextBlock.y-b.indexLabelTextBlock.height/2,f=b.indexLabelTextBlock.y+b.indexLabelTextBlock.height/2;return c=b.indexLabelTextBlock.y>a.indexLabelTextBlock.y?e-d:c-f}function f(a){for(var b=null,c=1;c<p.length;c++)if(b=(a+c+q.length)%q.length,q[b].hemisphere!==q[a].hemisphere){b=null;break}else if(q[b].indexLabelText&&b!==a&&(0>d(q[b],q[a])||("right"===q[a].hemisphere?q[b].indexLabelTextBlock.y>=q[a].indexLabelTextBlock.y:q[b].indexLabelTextBlock.y<=q[a].indexLabelTextBlock.y)))break;
|
||||
else b=null;return b}function g(a,b,c){c=(c||0)+1;if(1E3<c)return 0;b=b||0;var e=0,h=z.y-1*s,m=z.y+1*s;if(0<=a&&a<p.length){var k=q[a];if(0>b&&k.indexLabelTextBlock.y<h||0<b&&k.indexLabelTextBlock.y>m)return 0;var l=0,n=0,n=l=l=0;0>b?k.indexLabelTextBlock.y-k.indexLabelTextBlock.height/2>h&&k.indexLabelTextBlock.y-k.indexLabelTextBlock.height/2+b<h&&(b=-(h-(k.indexLabelTextBlock.y-k.indexLabelTextBlock.height/2+b))):k.indexLabelTextBlock.y+k.indexLabelTextBlock.height/2<h&&k.indexLabelTextBlock.y+
|
||||
k.indexLabelTextBlock.height/2+b>m&&(b=k.indexLabelTextBlock.y+k.indexLabelTextBlock.height/2+b-m);b=k.indexLabelTextBlock.y+b;h=0;h="right"===k.hemisphere?z.x+Math.sqrt(Math.pow(s,2)-Math.pow(b-z.y,2)):z.x-Math.sqrt(Math.pow(s,2)-Math.pow(b-z.y,2));n=z.x+B*Math.cos(k.midAngle);l=z.y+B*Math.sin(k.midAngle);l=Math.sqrt(Math.pow(h-n,2)+Math.pow(b-l,2));n=Math.acos(B/s);l=Math.acos((s*s+B*B-l*l)/(2*B*s));b=l<n?b-k.indexLabelTextBlock.y:0;h=null;for(m=1;m<p.length;m++)if(h=(a-m+q.length)%q.length,q[h].hemisphere!==
|
||||
q[a].hemisphere){h=null;break}else if(q[h].indexLabelText&&q[h].hemisphere===q[a].hemisphere&&h!==a&&(0>d(q[h],q[a])||("right"===q[a].hemisphere?q[h].indexLabelTextBlock.y<=q[a].indexLabelTextBlock.y:q[h].indexLabelTextBlock.y>=q[a].indexLabelTextBlock.y)))break;else h=null;n=h;l=f(a);m=h=0;0>b?(m="right"===k.hemisphere?n:l,e=b,null!==m&&(n=-b,b=k.indexLabelTextBlock.y-k.indexLabelTextBlock.height/2-(q[m].indexLabelTextBlock.y+q[m].indexLabelTextBlock.height/2),b-n<r&&(h=-n,m=g(m,h,c+1),+m.toFixed(v)>
|
||||
+h.toFixed(v)&&(e=b>r?-(b-r):-(n-(m-h)))))):0<b&&(m="right"===k.hemisphere?l:n,e=b,null!==m&&(n=b,b=q[m].indexLabelTextBlock.y-q[m].indexLabelTextBlock.height/2-(k.indexLabelTextBlock.y+k.indexLabelTextBlock.height/2),b-n<r&&(h=n,m=g(m,h,c+1),+m.toFixed(v)<+h.toFixed(v)&&(e=b>r?b-r:n-(h-m)))));e&&(c=k.indexLabelTextBlock.y+e,b=0,b="right"===k.hemisphere?z.x+Math.sqrt(Math.pow(s,2)-Math.pow(c-z.y,2)):z.x-Math.sqrt(Math.pow(s,2)-Math.pow(c-z.y,2)),k.midAngle>Math.PI/2-u&&k.midAngle<Math.PI/2+u?(h=(a-
|
||||
1+q.length)%q.length,h=q[h],a=q[(a+1+q.length)%q.length],"left"===k.hemisphere&&"right"===h.hemisphere&&b>h.indexLabelTextBlock.x?b=h.indexLabelTextBlock.x-15:"right"===k.hemisphere&&("left"===a.hemisphere&&b<a.indexLabelTextBlock.x)&&(b=a.indexLabelTextBlock.x+15)):k.midAngle>3*Math.PI/2-u&&k.midAngle<3*Math.PI/2+u&&(h=(a-1+q.length)%q.length,h=q[h],a=q[(a+1+q.length)%q.length],"right"===k.hemisphere&&"left"===h.hemisphere&&b<h.indexLabelTextBlock.x?b=h.indexLabelTextBlock.x+15:"left"===k.hemisphere&&
|
||||
("right"===a.hemisphere&&b>a.indexLabelTextBlock.x)&&(b=a.indexLabelTextBlock.x-15)),k.indexLabelTextBlock.y=c,k.indexLabelTextBlock.x=b,k.indexLabelAngle=Math.atan2(k.indexLabelTextBlock.y-z.y,k.indexLabelTextBlock.x-z.x))}return e}function l(){var a=h.plotArea.ctx;a.fillStyle="grey";a.strokeStyle="grey";a.font="16px Arial";a.textBaseline="middle";for(var b=a=0,c=0,k=!0,b=0;10>b&&(1>b||0<c);b++){if(m.radius||!m.radius&&"undefined"!==typeof m.innerRadius&&null!==m.innerRadius&&B-c<=E)k=!1;k&&(B-=
|
||||
c);c=0;if("inside"!==m.indexLabelPlacement){s=B*x;for(a=0;a<p.length;a++){var l=q[a];l.indexLabelTextBlock.x=z.x+s*Math.cos(l.midAngle);l.indexLabelTextBlock.y=z.y+s*Math.sin(l.midAngle);l.indexLabelAngle=l.midAngle;l.radius=B;l.percentInnerRadius=M}for(var u,t,a=0;a<p.length;a++){var l=q[a],w=f(a);if(null!==w){u=q[a];t=q[w];var y=0,y=d(u,t)-r;if(0>y){for(var A=t=0,D=0;D<p.length;D++)D!==a&&q[D].hemisphere===l.hemisphere&&(q[D].indexLabelTextBlock.y<l.indexLabelTextBlock.y?t++:A++);t=y/(t+A||1)*A;
|
||||
var A=-1*(y-t),C=D=0;"right"===l.hemisphere?(D=g(a,t),A=-1*(y-D),C=g(w,A),+C.toFixed(v)<+A.toFixed(v)&&+D.toFixed(v)<=+t.toFixed(v)&&g(a,-(A-C))):(D=g(w,t),A=-1*(y-D),C=g(a,A),+C.toFixed(v)<+A.toFixed(v)&&+D.toFixed(v)<=+t.toFixed(v)&&g(w,-(A-C)))}}}}else for(a=0;a<p.length;a++)l=q[a],s="pie"===m.type?0.7*B:0.8*B,w=z.x+s*Math.cos(l.midAngle),t=z.y+s*Math.sin(l.midAngle),l.indexLabelTextBlock.x=w,l.indexLabelTextBlock.y=t;for(a=0;a<p.length;a++)if(l=q[a],w=l.indexLabelTextBlock.measureText(),0!==w.height&&
|
||||
0!==w.width)w=w=0,"right"===l.hemisphere?(w=e.x2-(l.indexLabelTextBlock.x+l.indexLabelTextBlock.width+n),w*=-1):w=e.x1-(l.indexLabelTextBlock.x-l.indexLabelTextBlock.width-n),0<w&&(!k&&l.indexLabelText&&(t="right"===l.hemisphere?e.x2-l.indexLabelTextBlock.x:l.indexLabelTextBlock.x-e.x1,0.3*l.indexLabelTextBlock.maxWidth>t?l.indexLabelText="":l.indexLabelTextBlock.maxWidth=0.85*t,0.3*l.indexLabelTextBlock.maxWidth<t&&(l.indexLabelTextBlock.x-="right"===l.hemisphere?2:-2)),Math.abs(l.indexLabelTextBlock.y-
|
||||
l.indexLabelTextBlock.height/2-z.y)<B||Math.abs(l.indexLabelTextBlock.y+l.indexLabelTextBlock.height/2-z.y)<B)&&(w/=Math.abs(Math.cos(l.indexLabelAngle)),9<w&&(w*=0.3),w>c&&(c=w)),w=w=0,0<l.indexLabelAngle&&l.indexLabelAngle<Math.PI?(w=e.y2-(l.indexLabelTextBlock.y+l.indexLabelTextBlock.height/2+5),w*=-1):w=e.y1-(l.indexLabelTextBlock.y-l.indexLabelTextBlock.height/2-5),0<w&&(!k&&l.indexLabelText&&(t=0<l.indexLabelAngle&&l.indexLabelAngle<Math.PI?-1:1,0===g(a,w*t)&&g(a,2*t)),Math.abs(l.indexLabelTextBlock.x-
|
||||
z.x)<B&&(w/=Math.abs(Math.sin(l.indexLabelAngle)),9<w&&(w*=0.3),w>c&&(c=w)));var F=function(a,b,c){for(var d=[],e=0;d.push(q[b]),b!==c;b=(b+1+p.length)%p.length);d.sort(function(a,b){return a.y-b.y});for(b=0;b<d.length;b++)if(c=d[b],e<0.7*a)e+=c.indexLabelTextBlock.height,c.indexLabelTextBlock.text="",c.indexLabelText="",c.indexLabelTextBlock.measureText();else break};(function(){for(var a=-1,b=-1,c=0,e=!1,g=0;g<p.length;g++)if(e=!1,u=q[g],u.indexLabelText){var h=f(g);if(null!==h){var k=q[h];y=0;
|
||||
y=d(u,k);var l;if(l=0>y){l=u.indexLabelTextBlock.x;var m=u.indexLabelTextBlock.y-u.indexLabelTextBlock.height/2,r=u.indexLabelTextBlock.y+u.indexLabelTextBlock.height/2,s=k.indexLabelTextBlock.y-k.indexLabelTextBlock.height/2,x=k.indexLabelTextBlock.x+k.indexLabelTextBlock.width,v=k.indexLabelTextBlock.y+k.indexLabelTextBlock.height/2;l=u.indexLabelTextBlock.x+u.indexLabelTextBlock.width<k.indexLabelTextBlock.x-n||l>x+n||m>v+n||r<s-n?!1:!0}l?(0>a&&(a=g),h!==a&&(b=h,c+=-y),0===g%Math.max(p.length/
|
||||
10,3)&&(e=!0)):e=!0;e&&(0<c&&0<=a&&0<=b)&&(F(c,a,b),b=a=-1,c=0)}}0<c&&F(c,a,b)})()}}function k(){h.plotArea.layoutManager.reset();h.title&&(h.title.dockInsidePlotArea||"center"===h.title.horizontalAlign&&"center"===h.title.verticalAlign)&&h.title.render();if(h.subtitles)for(var a=0;a<h.subtitles.length;a++){var b=h.subtitles[a];(b.dockInsidePlotArea||"center"===b.horizontalAlign&&"center"===b.verticalAlign)&&b.render()}h.legend&&(h.legend.dockInsidePlotArea||"center"===h.legend.horizontalAlign&&"center"===
|
||||
h.legend.verticalAlign)&&h.legend.render()}var h=this;if(!(0>=a.dataSeriesIndexes.length)){var m=this.data[a.dataSeriesIndexes[0]],p=m.dataPoints,n=10,e=this.plotArea,q=[],r=2,s,x=1.3,u=20/180*Math.PI,v=6,z={x:(e.x2+e.x1)/2,y:(e.y2+e.y1)/2},t=0;a=!1;for(var A=0;A<p.length;A++)t+=Math.abs(p[A].y),!a&&("undefined"!==typeof p[A].indexLabel&&null!==p[A].indexLabel&&0<p[A].indexLabel.toString().length)&&(a=!0),!a&&("undefined"!==typeof p[A].label&&null!==p[A].label&&0<p[A].label.toString().length)&&(a=
|
||||
!0);if(0!==t){a=a||"undefined"!==typeof m.indexLabel&&null!==m.indexLabel&&0<m.indexLabel.toString().length;var B="inside"!==m.indexLabelPlacement&&a?0.75*Math.min(e.width,e.height)/2:0.92*Math.min(e.width,e.height)/2;m.radius&&(B=Qa(m.radius,B));var E="undefined"!==typeof m.innerRadius&&null!==m.innerRadius?Qa(m.innerRadius,B):0.7*B;m.radius=B;"doughnut"===m.type&&(m.innerRadius=E);var M=Math.min(E/B,(B-1)/B);this.pieDoughnutClickHandler=function(a){h.isAnimating||!y(a.dataSeries.explodeOnClick)&&
|
||||
!a.dataSeries.explodeOnClick||(a=a.dataPoint,a.exploded=a.exploded?!1:!0,1<this.dataPoints.length&&h._animator.animate(0,500,function(a){b(a);k()}))};c();l();l();l();l();this.disableToolTip=!0;this._animator.animate(0,this.animatedRender?this.animationDuration:0,function(a){var b=h.plotArea.ctx;b.clearRect(e.x1,e.y1,e.width,e.height);b.fillStyle=h.backgroundColor;b.fillRect(e.x1,e.y1,e.width,e.height);a=q[0].startAngle+2*Math.PI*a;for(b=0;b<p.length;b++){var c=0===b?q[b].startAngle:d,d=c+(q[b].endAngle-
|
||||
q[b].startAngle),f=!1;d>a&&(d=a,f=!0);var g=p[b].color?p[b].color:m._colorSet[b%m._colorSet.length];d>c&&Ha(h.plotArea.ctx,q[b].center,q[b].radius,g,m.type,c,d,m.fillOpacity,q[b].percentInnerRadius);if(f)break}k()},function(){h.disableToolTip=!1;h._animator.animate(0,h.animatedRender?500:0,function(a){b(a);k()})})}}};A.prototype.animationRequestId=null;A.prototype.requestAnimFrame=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||
|
||||
window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(a){window.setTimeout(a,1E3/60)}}();A.prototype.cancelRequestAnimFrame=window.cancelAnimationFrame||window.webkitCancelRequestAnimationFrame||window.mozCancelRequestAnimationFrame||window.oCancelRequestAnimationFrame||window.msCancelRequestAnimationFrame||clearTimeout;A.prototype.set=function(a,c,b){b="undefined"===typeof b?!0:b;"options"===a?(this.options=c,b&&this.render()):A.base.set.call(this,a,c,b)};A.prototype.exportChart=
|
||||
function(a){a="undefined"===typeof a?{}:a;var c=a.format?a.format:"png",b=a.fileName?a.fileName:this.exportFileName;if(a.toDataURL)return this.canvas.toDataURL("image/"+c);Ca(this.canvas,c,b)};A.prototype.print=function(){var a=this.exportChart({toDataURL:!0}),c=document.createElement("iframe");c.setAttribute("class","canvasjs-chart-print-frame");c.setAttribute("style","position:absolute; width:100%; border: 0px; margin: 0px 0px 0px 0px; padding 0px 0px 0px 0px;");c.style.height=this.height+"px";
|
||||
this._canvasJSContainer.appendChild(c);var b=this,d=c.contentWindow||c.contentDocument.document||c.contentDocument;d.document.open();d.document.write('<!DOCTYPE HTML>\n<html><body style="margin: 0px 0px 0px 0px; padding: 0px 0px 0px 0px;"><img src="'+a+'"/><body/></html>');d.document.close();setTimeout(function(){d.focus();d.print();setTimeout(function(){b._canvasJSContainer.removeChild(c)},1E3)},500)};la.prototype.registerSpace=function(a,c){"top"===a?this._topOccupied+=c.height:"bottom"===a?this._bottomOccupied+=
|
||||
c.height:"left"===a?this._leftOccupied+=c.width:"right"===a&&(this._rightOccupied+=c.width)};la.prototype.unRegisterSpace=function(a,c){"top"===a?this._topOccupied-=c.height:"bottom"===a?this._bottomOccupied-=c.height:"left"===a?this._leftOccupied-=c.width:"right"===a&&(this._rightOccupied-=c.width)};la.prototype.getFreeSpace=function(){return{x1:this._x1+this._leftOccupied,y1:this._y1+this._topOccupied,x2:this._x2-this._rightOccupied,y2:this._y2-this._bottomOccupied,width:this._x2-this._x1-this._rightOccupied-
|
||||
this._leftOccupied,height:this._y2-this._y1-this._bottomOccupied-this._topOccupied}};la.prototype.reset=function(){this._rightOccupied=this._leftOccupied=this._bottomOccupied=this._topOccupied=this._padding};T(V,L);V.prototype.render=function(a){if(0!==this.fontSize){a&&this.ctx.save();var c=this.ctx.font;this.ctx.textBaseline=this.textBaseline;var b=0;this._isDirty&&this.measureText(this.ctx);this.ctx.translate(this.x,this.y+b);"middle"===this.textBaseline&&(b=-this._lineHeight/2);this.ctx.font=
|
||||
this._getFontString();this.ctx.rotate(Math.PI/180*this.angle);var d=0,f=this.padding,g=null;this.ctx.roundRect||Ja(this.ctx);(0<this.borderThickness&&this.borderColor||this.backgroundColor)&&this.ctx.roundRect(0,b,this.width,this.height,this.cornerRadius,this.borderThickness,this.backgroundColor,this.borderColor);this.ctx.fillStyle=this.fontColor;for(b=0;b<this._wrappedText.lines.length;b++)g=this._wrappedText.lines[b],"right"===this.horizontalAlign?d=this.width-g.width-this.padding:"left"===this.horizontalAlign?
|
||||
d=this.padding:"center"===this.horizontalAlign&&(d=(this.width-2*this.padding)/2-g.width/2+this.padding),this.ctx.fillText(g.text,d,f),f+=g.height;this.ctx.font=c;a&&this.ctx.restore()}};V.prototype.setText=function(a){this.text=a;this._isDirty=!0;this._wrappedText=null};V.prototype.measureText=function(){this._lineHeight=La(this.fontFamily,this.fontSize,this.fontWeight);if(null===this.maxWidth)throw"Please set maxWidth and height for TextBlock";this._wrapText(this.ctx);this._isDirty=!1;return{width:this.width,
|
||||
height:this.height}};V.prototype._getLineWithWidth=function(a,c,b){a=String(a);if(!a)return{text:"",width:0};var d=b=0,f=a.length-1,g=Infinity;for(this.ctx.font=this._getFontString();d<=f;){var g=Math.floor((d+f)/2),l=a.substr(0,g+1);b=this.ctx.measureText(l).width;if(b<c)d=g+1;else if(b>c)f=g-1;else break}b>c&&1<l.length&&(l=l.substr(0,l.length-1),b=this.ctx.measureText(l).width);c=!0;if(l.length===a.length||" "===a[l.length])c=!1;c&&(a=l.split(" "),1<a.length&&a.pop(),l=a.join(" "),b=this.ctx.measureText(l).width);
|
||||
return{text:l,width:b}};V.prototype._wrapText=function(){var a=new String(ma(String(this.text))),c=[],b=this.ctx.font,d=0,f=0;this.ctx.font=this._getFontString();if(0===this.frontSize)f=d=0;else for(;0<a.length;){var g=this.maxHeight-2*this.padding,l=this._getLineWithWidth(a,this.maxWidth-2*this.padding,!1);l.height=this._lineHeight;c.push(l);var k=f,f=Math.max(f,l.width),d=d+l.height,a=ma(a.slice(l.text.length,a.length));g&&d>g&&(l=c.pop(),d-=l.height,f=k)}this._wrappedText={lines:c,width:f,height:d};
|
||||
this.width=f+2*this.padding;this.height=d+2*this.padding;this.ctx.font=b};V.prototype._getFontString=function(){var a;a=""+(this.fontStyle?this.fontStyle+" ":"");a+=this.fontWeight?this.fontWeight+" ":"";a+=this.fontSize?this.fontSize+"px ":"";var c=this.fontFamily?this.fontFamily+"":"";!t&&c&&(c=c.split(",")[0],"'"!==c[0]&&'"'!==c[0]&&(c="'"+c+"'"));return a+=c};T(oa,L);oa.prototype.render=function(){if(this.text){var a=this.dockInsidePlotArea?this.chart.plotArea:this.chart,c=a.layoutManager.getFreeSpace(),
|
||||
b=c.x1,d=c.y1,f=0,g=0,l=this.chart._menuButton&&this.chart.exportEnabled&&"top"===this.verticalAlign?22:0,k,h;"top"===this.verticalAlign||"bottom"===this.verticalAlign?(null===this.maxWidth&&(this.maxWidth=c.width-4-l*("center"===this.horizontalAlign?2:1)),g=0.5*c.height-this.margin-2,f=0):"center"===this.verticalAlign&&("left"===this.horizontalAlign||"right"===this.horizontalAlign?(null===this.maxWidth&&(this.maxWidth=c.height-4),g=0.5*c.width-this.margin-2):"center"===this.horizontalAlign&&(null===
|
||||
this.maxWidth&&(this.maxWidth=c.width-4),g=0.5*c.height-4));this.wrap||(g=Math.min(g,Math.max(1.5*this.fontSize,this.fontSize+2.5*this.padding)));var g=new V(this.ctx,{fontSize:this.fontSize,fontFamily:this.fontFamily,fontColor:this.fontColor,fontStyle:this.fontStyle,fontWeight:this.fontWeight,horizontalAlign:this.horizontalAlign,verticalAlign:this.verticalAlign,borderColor:this.borderColor,borderThickness:this.borderThickness,backgroundColor:this.backgroundColor,maxWidth:this.maxWidth,maxHeight:g,
|
||||
cornerRadius:this.cornerRadius,text:this.text,padding:this.padding,textBaseline:"top"}),m=g.measureText();"top"===this.verticalAlign||"bottom"===this.verticalAlign?("top"===this.verticalAlign?(d=c.y1+2,h="top"):"bottom"===this.verticalAlign&&(d=c.y2-2-m.height,h="bottom"),"left"===this.horizontalAlign?b=c.x1+2:"center"===this.horizontalAlign?b=c.x1+c.width/2-m.width/2:"right"===this.horizontalAlign&&(b=c.x2-2-m.width-l),k=this.horizontalAlign,this.width=m.width,this.height=m.height):"center"===this.verticalAlign&&
|
||||
("left"===this.horizontalAlign?(b=c.x1+2,d=c.y2-2-(this.maxWidth/2-m.width/2),f=-90,h="left",this.width=m.height,this.height=m.width):"right"===this.horizontalAlign?(b=c.x2-2,d=c.y1+2+(this.maxWidth/2-m.width/2),f=90,h="right",this.width=m.height,this.height=m.width):"center"===this.horizontalAlign&&(d=a.y1+(a.height/2-m.height/2),b=a.x1+(a.width/2-m.width/2),h="center",this.width=m.width,this.height=m.height),k="center");g.x=b;g.y=d;g.angle=f;g.horizontalAlign=k;g.render(!0);a.layoutManager.registerSpace(h,
|
||||
{width:this.width+("left"===h||"right"===h?this.margin+2:0),height:this.height+("top"===h||"bottom"===h?this.margin+2:0)});this.bounds={x1:b,y1:d,x2:b+this.width,y2:d+this.height};this.ctx.textBaseline="top"}};T(xa,L);xa.prototype.render=oa.prototype.render;T(ya,L);ya.prototype.render=function(){var a=this.dockInsidePlotArea?this.chart.plotArea:this.chart,c=a.layoutManager.getFreeSpace(),b=null,d=0,f=0,g=0,l=0,k=this.markerMargin=this.chart.options.legend&&!y(this.chart.options.legend.markerMargin)?
|
||||
this.chart.options.legend.markerMargin:0.3*this.fontSize;this.height=0;var h=[],m=[];"top"===this.verticalAlign||"bottom"===this.verticalAlign?(this.orientation="horizontal",b=this.verticalAlign,g=this.maxWidth=null!==this.maxWidth?this.maxWidth:c.width,l=this.maxHeight=null!==this.maxHeight?this.maxHeight:0.5*c.height):"center"===this.verticalAlign&&(this.orientation="vertical",b=this.horizontalAlign,g=this.maxWidth=null!==this.maxWidth?this.maxWidth:0.5*c.width,l=this.maxHeight=null!==this.maxHeight?
|
||||
this.maxHeight:c.height);for(var p=0;p<this.dataSeries.length;p++){var n=this.dataSeries[p];if(n.dataPoints&&n.dataPoints.length)if("pie"!==n.type&&"doughnut"!==n.type&&"funnel"!==n.type){var e=n.legendMarkerType=n.legendMarkerType?n.legendMarkerType:"line"!==n.type&&"stepLine"!==n.type&&"spline"!==n.type&&"scatter"!==n.type&&"bubble"!==n.type||!n.markerType?ca.getDefaultLegendMarker(n.type):n.markerType,q=n.legendText?n.legendText:this.itemTextFormatter?this.itemTextFormatter({chart:this.chart,legend:this.options,
|
||||
dataSeries:n,dataPoint:null}):n.name,r=n.legendMarkerColor=n.legendMarkerColor?n.legendMarkerColor:n.markerColor?n.markerColor:n._colorSet[0],s=n.markerSize||"line"!==n.type&&"stepLine"!==n.type&&"spline"!==n.type?0.75*this.lineHeight:0,x=n.legendMarkerBorderColor?n.legendMarkerBorderColor:n.markerBorderColor,u=n.legendMarkerBorderThickness?n.legendMarkerBorderThickness:n.markerBorderThickness?Math.max(1,Math.round(0.2*s)):0,q=this.chart.replaceKeywordsWithValue(q,n.dataPoints[0],n,p),e={markerType:e,
|
||||
markerColor:r,text:q,textBlock:null,chartType:n.type,markerSize:s,lineColor:n._colorSet[0],dataSeriesIndex:n.index,dataPointIndex:null,markerBorderColor:x,markerBorderThickness:u};h.push(e)}else for(var v=0;v<n.dataPoints.length;v++){var t=n.dataPoints[v],e=t.legendMarkerType?t.legendMarkerType:n.legendMarkerType?n.legendMarkerType:ca.getDefaultLegendMarker(n.type),q=t.legendText?t.legendText:n.legendText?n.legendText:this.itemTextFormatter?this.itemTextFormatter({chart:this.chart,legend:this.options,
|
||||
dataSeries:n,dataPoint:t}):t.name?t.name:"DataPoint: "+(v+1),r=t.legendMarkerColor?t.legendMarkerColor:n.legendMarkerColor?n.legendMarkerColor:t.color?t.color:n.color?n.color:n._colorSet[v%n._colorSet.length],s=0.75*this.lineHeight,x=t.legendMarkerBorderColor?t.legendMarkerBorderColor:n.legendMarkerBorderColor?n.legendMarkerBorderColor:t.markerBorderColor?t.markerBorderColor:n.markerBorderColor,u=t.legendMarkerBorderThickness?t.legendMarkerBorderThickness:n.legendMarkerBorderThickness?n.legendMarkerBorderThickness:
|
||||
t.markerBorderThickness||n.markerBorderThickness?Math.max(1,Math.round(0.2*s)):0,q=this.chart.replaceKeywordsWithValue(q,t,n,v),e={markerType:e,markerColor:r,text:q,textBlock:null,chartType:n.type,markerSize:s,dataSeriesIndex:p,dataPointIndex:v,markerBorderColor:x,markerBorderThickness:u};(t.showInLegend||n.showInLegend&&!1!==t.showInLegend)&&h.push(e)}}!0===this.reversed&&h.reverse();if(0<h.length){n=null;r=v=q=t=0;q=null!==this.itemWidth?null!==this.itemMaxWidth?Math.min(this.itemWidth,this.itemMaxWidth,
|
||||
g):this.itemMaxWidth=Math.min(this.itemWidth,g):null!==this.itemMaxWidth?Math.min(this.itemMaxWidth,g):this.itemMaxWidth=g;s=0===s?0.75*this.lineHeight:s;q-=s+k;for(p=0;p<h.length;p++){e=h[p];if("line"===e.chartType||"spline"===e.chartType||"stepLine"===e.chartType)q-=2*0.1*this.lineHeight;if(!(0>=l||"undefined"===typeof l||0>=q||"undefined"===typeof q)){if("horizontal"===this.orientation){e.textBlock=new V(this.ctx,{x:0,y:0,maxWidth:q,maxHeight:this.itemWrap?l:this.lineHeight,angle:0,text:e.text,
|
||||
horizontalAlign:"left",fontSize:this.fontSize,fontFamily:this.fontFamily,fontWeight:this.fontWeight,fontColor:this.fontColor,fontStyle:this.fontStyle,textBaseline:"middle"});e.textBlock.measureText();null!==this.itemWidth&&(e.textBlock.width=this.itemWidth-(s+k+("line"===e.chartType||"spline"===e.chartType||"stepLine"===e.chartType?2*0.1*this.lineHeight:0)));if(!n||n.width+Math.round(e.textBlock.width+s+k+(0===n.width?0:this.horizontalSpacing)+("line"===e.chartType||"spline"===e.chartType||"stepLine"===
|
||||
e.chartType?2*0.1*this.lineHeight:0))>g)n={items:[],width:0},m.push(n),this.height+=v,v=0;v=Math.max(v,e.textBlock.height)}else e.textBlock=new V(this.ctx,{x:0,y:0,maxWidth:q,maxHeight:!0===this.itemWrap?l:1.5*this.fontSize,angle:0,text:e.text,horizontalAlign:"left",fontSize:this.fontSize,fontFamily:this.fontFamily,fontWeight:this.fontWeight,fontColor:this.fontColor,fontStyle:this.fontStyle,textBaseline:"middle"}),e.textBlock.measureText(),null!==this.itemWidth&&(e.textBlock.width=this.itemWidth-
|
||||
(s+k+("line"===e.chartType||"spline"===e.chartType||"stepLine"===e.chartType?2*0.1*this.lineHeight:0))),this.height<l-this.lineHeight?(n={items:[],width:0},m.push(n)):(n=m[t],t=(t+1)%m.length),this.height+=e.textBlock.height;e.textBlock.x=n.width;e.textBlock.y=0;n.width+=Math.round(e.textBlock.width+s+k+(0===n.width?0:this.horizontalSpacing)+("line"===e.chartType||"spline"===e.chartType||"stepLine"===e.chartType?2*0.1*this.lineHeight:0));n.items.push(e);this.width=Math.max(n.width,this.width);r=e.textBlock.width+
|
||||
(s+k+("line"===e.chartType||"spline"===e.chartType||"stepLine"===e.chartType?2*0.1*this.lineHeight:0))}}this.itemWidth=r;this.height=!1===this.itemWrap?m.length*this.lineHeight:this.height+v;this.height=Math.min(l,this.height);this.width=Math.min(g,this.width)}"top"===this.verticalAlign?(f="left"===this.horizontalAlign?c.x1:"right"===this.horizontalAlign?c.x2-this.width:c.x1+c.width/2-this.width/2,d=c.y1):"center"===this.verticalAlign?(f="left"===this.horizontalAlign?c.x1:"right"===this.horizontalAlign?
|
||||
c.x2-this.width:c.x1+c.width/2-this.width/2,d=c.y1+c.height/2-this.height/2):"bottom"===this.verticalAlign&&(f="left"===this.horizontalAlign?c.x1:"right"===this.horizontalAlign?c.x2-this.width:c.x1+c.width/2-this.width/2,d=c.y2-this.height);this.items=h;for(p=0;p<this.items.length;p++)e=h[p],e.id=++this.chart._eventManager.lastObjectId,this.chart._eventManager.objectMap[e.id]={id:e.id,objectType:"legendItem",legendItemIndex:p,dataSeriesIndex:e.dataSeriesIndex,dataPointIndex:e.dataPointIndex};(0<this.borderThickness&&
|
||||
this.borderColor||this.backgroundColor)&&this.ctx.roundRect(f,d,this.width,this.height,this.cornerRadius,this.borderThickness,this.backgroundColor,this.borderColor);for(p=c=0;p<m.length;p++){n=m[p];for(t=v=0;t<n.items.length;t++){e=n.items[t];r=e.textBlock.x+f+(0===t?0.2*s:this.horizontalSpacing);x=d+c;q=r;this.chart.data[e.dataSeriesIndex].visible||(this.ctx.globalAlpha=0.5);this.ctx.save();this.ctx.beginPath();this.ctx.rect(f,d,g,Math.max(l-l%this.lineHeight,0));this.ctx.clip();if("line"===e.chartType||
|
||||
"stepLine"===e.chartType||"spline"===e.chartType)this.ctx.strokeStyle=e.lineColor,this.ctx.lineWidth=Math.ceil(this.lineHeight/8),this.ctx.beginPath(),this.ctx.moveTo(r-0.1*this.lineHeight,x+this.lineHeight/2),this.ctx.lineTo(r+0.85*this.lineHeight,x+this.lineHeight/2),this.ctx.stroke(),q-=0.1*this.lineHeight;O.drawMarker(r+s/2,x+this.lineHeight/2,this.ctx,e.markerType,e.markerSize,e.markerColor,e.markerBorderColor,e.markerBorderThickness);e.textBlock.x=r+k+s;if("line"===e.chartType||"stepLine"===
|
||||
e.chartType||"spline"===e.chartType)e.textBlock.x+=0.1*this.lineHeight;e.textBlock.y=Math.round(x+this.lineHeight/2);e.textBlock.render(!0);this.ctx.restore();v=0<t?Math.max(v,e.textBlock.height):e.textBlock.height;this.chart.data[e.dataSeriesIndex].visible||(this.ctx.globalAlpha=1);r=D(e.id);this.ghostCtx.fillStyle=r;this.ghostCtx.beginPath();this.ghostCtx.fillRect(q,e.textBlock.y-this.lineHeight/2,e.textBlock.x+e.textBlock.width-q,e.textBlock.height);e.x1=this.chart._eventManager.objectMap[e.id].x1=
|
||||
q;e.y1=this.chart._eventManager.objectMap[e.id].y1=e.textBlock.y-this.lineHeight/2;e.x2=this.chart._eventManager.objectMap[e.id].x2=e.textBlock.x+e.textBlock.width;e.y2=this.chart._eventManager.objectMap[e.id].y2=e.textBlock.y+e.textBlock.height-this.lineHeight/2}c+=v}0<h.length&&a.layoutManager.registerSpace(b,{width:this.width+2+2,height:this.height+5+5});this.bounds={x1:f,y1:d,x2:f+this.width,y2:d+this.height}};T(Da,L);Da.prototype.render=function(){var a=this.chart.layoutManager.getFreeSpace();
|
||||
this.ctx.fillStyle="red";this.ctx.fillRect(a.x1,a.y1,a.x2,a.y2)};T(ca,L);ca.prototype.getDefaultAxisPlacement=function(){var a=this.type;if("column"===a||"line"===a||"stepLine"===a||"spline"===a||"area"===a||"stepArea"===a||"splineArea"===a||"stackedColumn"===a||"stackedLine"===a||"bubble"===a||"scatter"===a||"stackedArea"===a||"stackedColumn100"===a||"stackedLine100"===a||"stackedArea100"===a||"candlestick"===a||"ohlc"===a||"rangeColumn"===a||"rangeArea"===a||"rangeSplineArea"===a)return"normal";
|
||||
if("bar"===a||"stackedBar"===a||"stackedBar100"===a||"rangeBar"===a)return"xySwapped";if("pie"===a||"doughnut"===a||"funnel"===a)return"none";window.console.log("Unknown Chart Type: "+a);return null};ca.getDefaultLegendMarker=function(a){if("column"===a||"stackedColumn"===a||"stackedLine"===a||"bar"===a||"stackedBar"===a||"stackedBar100"===a||"bubble"===a||"scatter"===a||"stackedColumn100"===a||"stackedLine100"===a||"stepArea"===a||"candlestick"===a||"ohlc"===a||"rangeColumn"===a||"rangeBar"===a||
|
||||
"rangeArea"===a||"rangeSplineArea"===a)return"square";if("line"===a||"stepLine"===a||"spline"===a||"pie"===a||"doughnut"===a||"funnel"===a)return"circle";if("area"===a||"splineArea"===a||"stackedArea"===a||"stackedArea100"===a)return"triangle";window.console.log("Unknown Chart Type: "+a);return null};ca.prototype.getDataPointAtX=function(a,c){if(!this.dataPoints||0===this.dataPoints.length)return null;var b={dataPoint:null,distance:Infinity,index:NaN},d=null,f=0,g=0,l=1,k=Infinity,h=0,m=0,p=0;"none"!==
|
||||
this.chart.plotInfo.axisPlacement&&(this.axisX.logarithmic?(p=Math.log(this.dataPoints[this.dataPoints.length-1].x/this.dataPoints[0].x),p=1<p?Math.min(Math.max((this.dataPoints.length-1)/p*Math.log(a/this.dataPoints[0].x)>>0,0),this.dataPoints.length):0):(p=this.dataPoints[this.dataPoints.length-1].x-this.dataPoints[0].x,p=0<p?Math.min(Math.max((this.dataPoints.length-1)/p*(a-this.dataPoints[0].x)>>0,0),this.dataPoints.length):0));for(;;){g=0<l?p+f:p-f;if(0<=g&&g<this.dataPoints.length){var d=this.dataPoints[g],
|
||||
n=this.axisX.logarithmic?d.x>a?d.x/a:a/d.x:Math.abs(d.x-a);n<b.distance&&(b.dataPoint=d,b.distance=n,b.index=g);d=n;d<=k?k=d:0<l?h++:m++;if(1E3<h&&1E3<m)break}else if(0>p-f&&p+f>=this.dataPoints.length)break;-1===l?(f++,l=1):l=-1}return c||b.dataPoint.x!==a?c&&null!==b.dataPoint?b:null:b};ca.prototype.getDataPointAtXY=function(a,c,b){if(!this.dataPoints||0===this.dataPoints.length||a<this.chart.plotArea.x1||a>this.chart.plotArea.x2||c<this.chart.plotArea.y1||c>this.chart.plotArea.y2)return null;b=
|
||||
b||!1;var d=[],f=0,g=0,l=1,k=!1,h=Infinity,m=0,p=0,n=0;"none"!==this.chart.plotInfo.axisPlacement&&(n=(this.chart.axisX[0]?this.chart.axisX[0]:this.chart.axisX2[0]).getXValueAt({x:a,y:c}),this.axisX.logarithmic?(g=Math.log(this.dataPoints[this.dataPoints.length-1].x/this.dataPoints[0].x),n=1<g?Math.min(Math.max((this.dataPoints.length-1)/g*Math.log(n/this.dataPoints[0].x)>>0,0),this.dataPoints.length):0):(g=this.dataPoints[this.dataPoints.length-1].x-this.dataPoints[0].x,n=0<g?Math.min(Math.max((this.dataPoints.length-
|
||||
1)/g*(n-this.dataPoints[0].x)>>0,0),this.dataPoints.length):0));for(;;){g=0<l?n+f:n-f;if(0<=g&&g<this.dataPoints.length){var e=this.chart._eventManager.objectMap[this.dataPointIds[g]],q=this.dataPoints[g],r=null;if(e){switch(this.type){case "column":case "stackedColumn":case "stackedColumn100":case "bar":case "stackedBar":case "stackedBar100":case "rangeColumn":case "rangeBar":a>=e.x1&&(a<=e.x2&&c>=e.y1&&c<=e.y2)&&(d.push({dataPoint:q,dataPointIndex:g,dataSeries:this,distance:Math.min(Math.abs(e.x1-
|
||||
a),Math.abs(e.x2-a),Math.abs(e.y1-c),Math.abs(e.y2-c))}),k=!0);break;case "line":case "stepLine":case "spline":case "area":case "stepArea":case "stackedArea":case "stackedArea100":case "splineArea":case "scatter":var s=K("markerSize",q,this)||4,t=b?20:s,r=Math.sqrt(Math.pow(e.x1-a,2)+Math.pow(e.y1-c,2));r<=t&&d.push({dataPoint:q,dataPointIndex:g,dataSeries:this,distance:r});g=Math.abs(e.x1-a);g<=h?h=g:0<l?m++:p++;r<=s/2&&(k=!0);break;case "rangeArea":case "rangeSplineArea":s=K("markerSize",q,this)||
|
||||
4;t=b?20:s;r=Math.min(Math.sqrt(Math.pow(e.x1-a,2)+Math.pow(e.y1-c,2)),Math.sqrt(Math.pow(e.x1-a,2)+Math.pow(e.y2-c,2)));r<=t&&d.push({dataPoint:q,dataPointIndex:g,dataSeries:this,distance:r});g=Math.abs(e.x1-a);g<=h?h=g:0<l?m++:p++;r<=s/2&&(k=!0);break;case "bubble":s=e.size;r=Math.sqrt(Math.pow(e.x1-a,2)+Math.pow(e.y1-c,2));r<=s/2&&(d.push({dataPoint:q,dataPointIndex:g,dataSeries:this,distance:r}),k=!0);break;case "pie":case "doughnut":s=e.center;t="doughnut"===this.type?e.percentInnerRadius*e.radius:
|
||||
0;r=Math.sqrt(Math.pow(s.x-a,2)+Math.pow(s.y-c,2));r<e.radius&&r>t&&(r=Math.atan2(c-s.y,a-s.x),0>r&&(r+=2*Math.PI),r=Number(((180*(r/Math.PI)%360+360)%360).toFixed(12)),s=Number(((180*(e.startAngle/Math.PI)%360+360)%360).toFixed(12)),t=Number(((180*(e.endAngle/Math.PI)%360+360)%360).toFixed(12)),0===t&&1<e.endAngle&&(t=360),s>=t&&0!==q.y&&(t+=360,r<s&&(r+=360)),r>s&&r<t&&(d.push({dataPoint:q,dataPointIndex:g,dataSeries:this,distance:0}),k=!0));break;case "candlestick":if(a>=e.x1-e.borderThickness/
|
||||
2&&a<=e.x2+e.borderThickness/2&&c>=e.y2-e.borderThickness/2&&c<=e.y3+e.borderThickness/2||Math.abs(e.x2-a+e.x1-a)<e.borderThickness&&c>=e.y1&&c<=e.y4)d.push({dataPoint:q,dataPointIndex:g,dataSeries:this,distance:Math.min(Math.abs(e.x1-a),Math.abs(e.x2-a),Math.abs(e.y2-c),Math.abs(e.y3-c))}),k=!0;break;case "ohlc":if(Math.abs(e.x2-a+e.x1-a)<e.borderThickness&&c>=e.y2&&c<=e.y3||a>=e.x1&&a<=(e.x2+e.x1)/2&&c>=e.y1-e.borderThickness/2&&c<=e.y1+e.borderThickness/2||a>=(e.x1+e.x2)/2&&a<=e.x2&&c>=e.y4-e.borderThickness/
|
||||
2&&c<=e.y4+e.borderThickness/2)d.push({dataPoint:q,dataPointIndex:g,dataSeries:this,distance:Math.min(Math.abs(e.x1-a),Math.abs(e.x2-a),Math.abs(e.y2-c),Math.abs(e.y3-c))}),k=!0}if(k||1E3<m&&1E3<p)break}}else if(0>n-f&&n+f>=this.dataPoints.length)break;-1===l?(f++,l=1):l=-1}a=null;for(c=0;c<d.length;c++)a?d[c].distance<=a.distance&&(a=d[c]):a=d[c];return a};ca.prototype.getMarkerProperties=function(a,c,b,d){var f=this.dataPoints;return{x:c,y:b,ctx:d,type:f[a].markerType?f[a].markerType:this.markerType,
|
||||
size:f[a].markerSize?f[a].markerSize:this.markerSize,color:f[a].markerColor?f[a].markerColor:this.markerColor?this.markerColor:f[a].color?f[a].color:this.color?this.color:this._colorSet[a%this._colorSet.length],borderColor:f[a].markerBorderColor?f[a].markerBorderColor:this.markerBorderColor?this.markerBorderColor:null,borderThickness:f[a].markerBorderThickness?f[a].markerBorderThickness:this.markerBorderThickness?this.markerBorderThickness:null}};T(B,L);B.prototype.createExtraLabelsForLog=function(a){a=
|
||||
(a||0)+1;if(!(5<a)){var c=this.logLabelValues[0]||this.intervalStartPosition;if(Math.log(this.range)/Math.log(c/this.viewportMinimum)<this.noTicks-1){for(var b=B.getNiceNumber((c-this.viewportMinimum)/Math.min(Math.max(2,this.noTicks-this.logLabelValues.length),3),!0),d=Math.ceil(this.viewportMinimum/b)*b;d<c;d+=b)d<this.viewportMinimum||this.logLabelValues.push(d);this.logLabelValues.sort(Aa);this.createExtraLabelsForLog(a)}}};B.prototype.createLabels=function(){var a,c,b=0,d=0,f,g=0,l=0,d=0,k=this.interval,
|
||||
h=0,m,p=0.6*this.chart.height,b=!1;if(this.dataSeries&&0<this.dataSeries.length)for(d=0;d<this.dataSeries.length;d++)"dateTime"===this.dataSeries[d].xValueType&&(b=!0);if("axisX"===this.type&&b&&!this.logarithmic)for(this.intervalStartPosition=this.getLabelStartPoint(new Date(this.viewportMinimum),this.intervalType,this.interval),f=Ia(new Date(this.viewportMaximum),this.interval,this.intervalType),b=this.intervalStartPosition;b<f;Ia(b,k,this.intervalType))a=b.getTime(),a=this.labelFormatter?this.labelFormatter({chart:this.chart,
|
||||
axis:this.options,value:b,label:this.labels[b]?this.labels[b]:null}):"axisX"===this.type&&this.labels[a]?this.labels[a]:Fa(b,this.valueFormatString,this.chart._cultureInfo),a=new V(this.ctx,{x:0,y:0,maxWidth:g,backgroundColor:this.labelBackgroundColor,borderColor:this.labelBorderColor,borderThickness:this.labelBorderThickness,cornerRadius:this.labelCornerRadius,maxHeight:l,angle:this.labelAngle,text:this.prefix+a+this.suffix,horizontalAlign:"left",fontSize:this.labelFontSize,fontFamily:this.labelFontFamily,
|
||||
fontWeight:this.labelFontWeight,fontColor:this.labelFontColor,fontStyle:this.labelFontStyle,textBaseline:"middle"}),this._labels.push({position:b.getTime(),textBlock:a,effectiveHeight:null});else{f=this.viewportMaximum;if(this.labels){a=Math.ceil(k);for(var k=Math.ceil(this.intervalStartPosition),n=!1,b=k;b<this.viewportMaximum;b+=a)if(this.labels[b])n=!0;else{n=!1;break}n&&(this.interval=a,this.intervalStartPosition=k)}if(this.logarithmic&&!this.equidistantInterval){this.logLabelValues||(this.logLabelValues=
|
||||
[],this.createExtraLabelsForLog());for(var e=0;e<this.logLabelValues.length;e++)b=this.logLabelValues[e],b<this.viewportMinimum||(a=this.labelFormatter?this.labelFormatter({chart:this.chart,axis:this.options,value:b,label:this.labels[b]?this.labels[b]:null}):"axisX"===this.type&&this.labels[b]?this.labels[b]:fa(b,this.valueFormatString,this.chart._cultureInfo),a=new V(this.ctx,{x:0,y:0,maxWidth:g,maxHeight:l,angle:this.labelAngle,text:this.prefix+a+this.suffix,backgroundColor:this.labelBackgroundColor,
|
||||
borderColor:this.labelBorderColor,borderThickness:this.labelBorderThickness,cornerRadius:this.labelCornerRadius,horizontalAlign:"left",fontSize:this.labelFontSize,fontFamily:this.labelFontFamily,fontWeight:this.labelFontWeight,fontColor:this.labelFontColor,fontStyle:this.labelFontStyle,textBaseline:"middle"}),this._labels.push({position:b,textBlock:a,effectiveHeight:null}))}for(b=this.intervalStartPosition;b<=f;b=parseFloat((this.logarithmic&&this.equidistantInterval?b*Math.pow(this.logarithmBase,
|
||||
this.interval):b+this.interval).toFixed(12)))a=this.labelFormatter?this.labelFormatter({chart:this.chart,axis:this.options,value:b,label:this.labels[b]?this.labels[b]:null}):"axisX"===this.type&&this.labels[b]?this.labels[b]:fa(b,this.valueFormatString,this.chart._cultureInfo),a=new V(this.ctx,{x:0,y:0,maxWidth:g,maxHeight:l,angle:this.labelAngle,text:this.prefix+a+this.suffix,horizontalAlign:"left",backgroundColor:this.labelBackgroundColor,borderColor:this.labelBorderColor,borderThickness:this.labelBorderThickness,
|
||||
cornerRadius:this.labelCornerRadius,fontSize:this.labelFontSize,fontFamily:this.labelFontFamily,fontWeight:this.labelFontWeight,fontColor:this.labelFontColor,fontStyle:this.labelFontStyle,textBaseline:"middle"}),this._labels.push({position:b,textBlock:a,effectiveHeight:null})}if("bottom"===this._position||"top"===this._position)h=this.logarithmic&&!this.equidistantInterval&&2<=this._labels.length?this.lineCoordinates.width*Math.log(Math.min(this._labels[this._labels.length-1].position/this._labels[this._labels.length-
|
||||
2].position,this._labels[1].position/this._labels[0].position))/Math.log(this.range):this.lineCoordinates.width/(this.logarithmic&&this.equidistantInterval?Math.log(this.range)/Math.log(this.logarithmBase):Math.abs(this.range))*G[this.intervalType+"Duration"]*this.interval,g="undefined"===typeof this.options.labelMaxWidth?0.5*this.chart.width>>0:this.options.labelMaxWidth,this.chart.panEnabled||(l="undefined"===typeof this.options.labelWrap||this.labelWrap?0.8*this.chart.height>>0:1.5*this.labelFontSize);
|
||||
else if("left"===this._position||"right"===this._position)h=this.logarithmic&&!this.equidistantInterval&&2<=this._labels.length?this.lineCoordinates.height*Math.log(Math.min(this._labels[this._labels.length-1].position/this._labels[this._labels.length-2].position,this._labels[1].position/this._labels[0].position))/Math.log(this.range):this.lineCoordinates.height/(this.logarithmic&&this.equidistantInterval?Math.log(this.range)/Math.log(this.logarithmBase):Math.abs(this.range))*G[this.intervalType+
|
||||
"Duration"]*this.interval,this.chart.panEnabled||(g="undefined"===typeof this.options.labelMaxWidth?0.3*this.chart.width>>0:this.options.labelMaxWidth),l="undefined"===typeof this.options.labelWrap||this.labelWrap?0.3*this.chart.height>>0:1.5*this.labelFontSize;for(d=0;d<this._labels.length;d++){a=this._labels[d].textBlock;a.maxWidth=g;a.maxHeight=l;var q=a.measureText();m=q.height}f=[];n=k=0;if(this.labelAutoFit||this.options.labelAutoFit)if(y(this.labelAngle)||(this.labelAngle=(this.labelAngle%
|
||||
360+360)%360,90<this.labelAngle&&270>this.labelAngle?this.labelAngle-=180:270<=this.labelAngle&&360>=this.labelAngle&&(this.labelAngle-=360)),"bottom"===this._position||"top"===this._position)if(g=0.9*h>>0,n=0,!this.chart.panEnabled&&1<=this._labels.length){this.sessionVariables.labelFontSize=this.labelFontSize;this.sessionVariables.labelMaxWidth=g;this.sessionVariables.labelMaxHeight=l;this.sessionVariables.labelAngle=this.labelAngle;this.sessionVariables.labelWrap=this.labelWrap;for(b=0;b<this._labels.length;b++){a=
|
||||
this._labels[b].textBlock;for(var r,s=a.text.split(" "),d=0;d<s.length;d++)e=s[d],this.ctx.font=a.fontStyle+" "+a.fontWeight+" "+a.fontSize+"px "+a.fontFamily,e=this.ctx.measureText(e),e.width>n&&(r=b,n=e.width)}b=0;for(b=this.intervalStartPosition<this.viewportMinimum?1:0;b<this._labels.length;b++)if(a=this._labels[b].textBlock,q=a.measureText(),b<this._labels.length-1&&(e=b+1,c=this._labels[e].textBlock,c=c.measureText()),f.push(a.height),this.sessionVariables.labelMaxHeight=Math.max.apply(Math,
|
||||
f),Math.cos(Math.PI/180*Math.abs(this.labelAngle)),Math.sin(Math.PI/180*Math.abs(this.labelAngle)),d=g*Math.sin(Math.PI/180*Math.abs(this.labelAngle))+(l-a.fontSize/2)*Math.cos(Math.PI/180*Math.abs(this.labelAngle)),y(this.options.labelAngle)&&isNaN(this.options.labelAngle)&&0!==this.options.labelAngle)if(this.sessionVariables.labelMaxHeight=0===this.labelAngle?l:Math.min((d-g*Math.cos(Math.PI/180*Math.abs(this.labelAngle)))/Math.sin(Math.PI/180*Math.abs(this.labelAngle)),d),s=(p-(m+a.fontSize/2)*
|
||||
Math.cos(Math.PI/180*Math.abs(-25)))/Math.sin(Math.PI/180*Math.abs(-25)),!y(this.options.labelWrap))this.labelWrap?y(this.options.labelMaxWidth)?(this.sessionVariables.labelMaxWidth=Math.min(Math.max(g,n),s),this.sessionVariables.labelWrap=this.labelWrap,q.width+c.width>>0>2*g&&(this.sessionVariables.labelAngle=-25)):(this.sessionVariables.labelWrap=this.labelWrap,this.sessionVariables.labelMaxWidth=this.options.labelMaxWidth,this.sessionVariables.labelAngle=this.sessionVariables.labelMaxWidth>g?
|
||||
-25:this.sessionVariables.labelAngle):y(this.options.labelMaxWidth)?(this.sessionVariables.labelWrap=this.labelWrap,this.sessionVariables.labelMaxHeight=l,this.sessionVariables.labelMaxWidth=g,q.width+c.width>>0>2*g&&(this.sessionVariables.labelAngle=-25,this.sessionVariables.labelMaxWidth=s)):(this.sessionVariables.labelAngle=this.sessionVariables.labelMaxWidth>g?-25:this.sessionVariables.labelAngle,this.sessionVariables.labelMaxWidth=this.options.labelMaxWidth,this.sessionVariables.labelMaxHeight=
|
||||
l,this.sessionVariables.labelWrap=this.labelWrap);else{if(y(this.options.labelWrap))if(!y(this.options.labelMaxWidth))this.options.labelMaxWidth<g?(this.sessionVariables.labelMaxWidth=this.options.labelMaxWidth,this.sessionVariables.labelMaxHeight=d):(this.sessionVariables.labelAngle=-25,this.sessionVariables.labelMaxWidth=this.options.labelMaxWidth,this.sessionVariables.labelMaxHeight=l);else if(!y(c))if(d=q.width+c.width>>0,e=this.labelFontSize,n<g)d-2*g>k&&(k=d-2*g,d>=2*g&&d<2.2*g?(this.sessionVariables.labelMaxWidth=
|
||||
g,y(this.options.labelFontSize)&&12<e&&(e=Math.floor(12/13*e),a.measureText()),this.sessionVariables.labelFontSize=y(this.options.labelFontSize)?e:this.options.labelFontSize,this.sessionVariables.labelAngle=this.labelAngle):d>=2.2*g&&d<2.8*g?(this.sessionVariables.labelAngle=-25,this.sessionVariables.labelMaxWidth=s,this.sessionVariables.labelFontSize=e):d>=2.8*g&&d<3.2*g?(this.sessionVariables.labelMaxWidth=Math.max(g,n),this.sessionVariables.labelWrap=!0,y(this.options.labelFontSize)&&12<this.labelFontSize&&
|
||||
(this.labelFontSize=Math.floor(12/13*this.labelFontSize),a.measureText()),this.sessionVariables.labelFontSize=y(this.options.labelFontSize)?e:this.options.labelFontSize,this.sessionVariables.labelAngle=this.labelAngle):d>=3.2*g&&d<3.6*g?(this.sessionVariables.labelAngle=-25,this.sessionVariables.labelWrap=!0,this.sessionVariables.labelMaxWidth=s,this.sessionVariables.labelFontSize=this.labelFontSize):d>3.6*g&&d<5*g?(y(this.options.labelFontSize)&&12<e&&(e=Math.floor(12/13*e),a.measureText()),this.sessionVariables.labelFontSize=
|
||||
y(this.options.labelFontSize)?e:this.options.labelFontSize,this.sessionVariables.labelWrap=!0,this.sessionVariables.labelAngle=-25,this.sessionVariables.labelMaxWidth=s):d>5*g&&(this.sessionVariables.labelWrap=!0,this.sessionVariables.labelMaxWidth=g,this.sessionVariables.labelFontSize=e,this.sessionVariables.labelMaxHeight=l,this.sessionVariables.labelAngle=this.labelAngle));else if(r===b&&(0===r&&n+this._labels[r+1].textBlock.measureText().width-2*g>k||r===this._labels.length-1&&n+this._labels[r-
|
||||
1].textBlock.measureText().width-2*g>k||0<r&&r<this._labels.length-1&&n+this._labels[r+1].textBlock.measureText().width-2*g>k&&n+this._labels[r-1].textBlock.measureText().width-2*g>k))k=0===r?n+this._labels[r+1].textBlock.measureText().width-2*g:n+this._labels[r-1].textBlock.measureText().width-2*g,this.sessionVariables.labelFontSize=y(this.options.labelFontSize)?e:this.options.labelFontSize,this.sessionVariables.labelWrap=!0,this.sessionVariables.labelAngle=-25,this.sessionVariables.labelMaxWidth=
|
||||
s;else if(0===k)for(this.sessionVariables.labelFontSize=y(this.options.labelFontSize)?e:this.options.labelFontSize,this.sessionVariables.labelWrap=!0,d=0;d<this._labels.length;d++)a=this._labels[d].textBlock,a.maxWidth=this.sessionVariables.labelMaxWidth=Math.min(Math.max(g,n),s),q=a.measureText(),d<this._labels.length-1&&(e=d+1,c=this._labels[e].textBlock,c.maxWidth=this.sessionVariables.labelMaxWidth=Math.min(Math.max(g,n),s),c=c.measureText(),q.width+c.width>>0>2*g&&(this.sessionVariables.labelAngle=
|
||||
-25))}else(this.sessionVariables.labelAngle=this.labelAngle,this.sessionVariables.labelMaxHeight=0===this.labelAngle?l:Math.min((d-g*Math.cos(Math.PI/180*Math.abs(this.labelAngle)))/Math.sin(Math.PI/180*Math.abs(this.labelAngle)),d),s=0!=this.labelAngle?(p-(m+a.fontSize/2)*Math.cos(Math.PI/180*Math.abs(this.labelAngle)))/Math.sin(Math.PI/180*Math.abs(this.labelAngle)):g,this.sessionVariables.labelMaxHeight=l=this.labelWrap?(p-s*Math.sin(Math.PI/180*Math.abs(this.labelAngle)))/Math.cos(Math.PI/180*
|
||||
Math.abs(this.labelAngle)):1.5*this.labelFontSize,y(this.options.labelWrap))?y(this.options.labelWrap)&&(this.labelWrap&&!y(this.options.labelMaxWidth)?(this.sessionVariables.labelWrap=this.labelWrap,this.sessionVariables.labelMaxWidth=this.options.labelMaxWidth?this.options.labelMaxWidth:s,this.sessionVariables.labelMaxHeight=l):(this.sessionVariables.labelAngle=this.labelAngle,this.sessionVariables.labelMaxWidth=s,this.sessionVariables.labelMaxHeight=d<0.9*h?0.9*h:d,this.sessionVariables.labelWrap=
|
||||
this.labelWrap)):(this.options.labelWrap?(this.sessionVariables.labelWrap=this.labelWrap,this.sessionVariables.labelMaxWidth=this.options.labelMaxWidth?this.options.labelMaxWidth:s):(y(this.options.labelMaxWidth),this.sessionVariables.labelMaxWidth=this.options.labelMaxWidth?this.options.labelMaxWidth:s,this.sessionVariables.labelWrap=this.labelWrap),this.sessionVariables.labelMaxHeight=l);for(d=0;d<this._labels.length;d++)a=this._labels[d].textBlock,a.maxWidth=this.labelMaxWidth=this.sessionVariables.labelMaxWidth,
|
||||
a.fontSize=this.sessionVariables.labelFontSize,a.angle=this.labelAngle=this.sessionVariables.labelAngle,a.wrap=this.labelWrap=this.sessionVariables.labelWrap,a.maxHeight=this.sessionVariables.labelMaxHeight,a.measureText()}else for(b=0;b<this._labels.length;b++)a=this._labels[b].textBlock,a.maxWidth=this.labelMaxWidth=y(this.options.labelMaxWidth)?this.sessionVariables.labelMaxWidth:this.options.labelMaxWidth,a.fontSize=this.labelFontSize=y(this.options.labelFontSize)?this.sessionVariables.labelFontSize:
|
||||
this.options.labelFontSize,a.angle=this.labelAngle=y(this.options.labelAngle)?this.sessionVariables.labelAngle:this.labelAngle,a.wrap=this.labelWrap=y(this.options.labelWrap)?this.sessionVariables.labelWrap:this.options.labelWrap,a.maxHeight=this.sessionVariables.labelMaxHeight,a.measureText();else if("left"===this._position||"right"===this._position)if(g=y(this.options.labelMaxWidth)?0.3*this.chart.width>>0:this.options.labelMaxWidth,l="undefined"===typeof this.options.labelWrap||this.labelWrap?
|
||||
0.3*this.chart.height>>0:1.5*this.labelFontSize,!this.chart.panEnabled&&1<=this._labels.length){this.sessionVariables.labelFontSize=this.labelFontSize;this.sessionVariables.labelMaxWidth=g;this.sessionVariables.labelMaxHeight=l;this.sessionVariables.labelAngle=y(this.sessionVariables.labelAngle)?0:this.sessionVariables.labelAngle;this.sessionVariables.labelWrap=this.labelWrap;for(b=0;b<this._labels.length;b++)(a=this._labels[b].textBlock,q=a.measureText(),b<this._labels.length-1&&(e=b+1,c=this._labels[e].textBlock,
|
||||
c=c.measureText()),f.push(a.height),this.sessionVariables.labelMaxHeight=Math.max.apply(Math,f),d=g*Math.sin(Math.PI/180*Math.abs(this.labelAngle))+(l-a.fontSize/2)*Math.cos(Math.PI/180*Math.abs(this.labelAngle)),Math.cos(Math.PI/180*Math.abs(this.labelAngle)),Math.sin(Math.PI/180*Math.abs(this.labelAngle)),y(this.options.labelAngle)&&isNaN(this.options.labelAngle)&&0!==this.options.labelAngle)?y(this.options.labelWrap)?y(this.options.labelWrap)&&(y(this.options.labelMaxWidth)?y(c)||(h=q.height+c.height>>
|
||||
0,h-2*l>n&&(n=h-2*l,h>=2*l&&h<2.4*l?(y(this.options.labelFontSize)&&12<this.labelFontSize&&(this.labelFontSize=Math.floor(12/13*this.labelFontSize),a.measureText()),this.sessionVariables.labelMaxHeight=l,this.sessionVariables.labelFontSize=y(this.options.labelFontSize)?this.labelFontSize:this.options.labelFontSize):h>=2.4*l&&h<2.8*l?(this.sessionVariables.labelMaxHeight=d,this.sessionVariables.labelFontSize=this.labelFontSize,this.sessionVariables.labelWrap=!0):h>=2.8*l&&h<3.2*l?(this.sessionVariables.labelMaxHeight=
|
||||
l,this.sessionVariables.labelWrap=!0,y(this.options.labelFontSize)&&12<this.labelFontSize&&(this.labelFontSize=Math.floor(12/13*this.labelFontSize),a.measureText()),this.sessionVariables.labelFontSize=y(this.options.labelFontSize)?this.labelFontSize:this.options.labelFontSize,this.sessionVariables.labelAngle=y(this.sessionVariables.labelAngle)?0:this.sessionVariables.labelAngle):h>=3.2*l&&h<3.6*l?(this.sessionVariables.labelMaxHeight=d,this.sessionVariables.labelWrap=!0,this.sessionVariables.labelFontSize=
|
||||
this.labelFontSize):h>3.6*l&&h<10*l?(y(this.options.labelFontSize)&&12<this.labelFontSize&&(this.labelFontSize=Math.floor(12/13*this.labelFontSize),a.measureText()),this.sessionVariables.labelFontSize=y(this.options.labelFontSize)?this.labelFontSize:this.options.labelFontSize,this.sessionVariables.labelMaxWidth=g,this.sessionVariables.labelMaxHeight=l,this.sessionVariables.labelAngle=y(this.sessionVariables.labelAngle)?0:this.sessionVariables.labelAngle):h>10*l&&h<50*l&&(y(this.options.labelFontSize)&&
|
||||
12<this.labelFontSize&&(this.labelFontSize=Math.floor(12/13*this.labelFontSize),a.measureText()),this.sessionVariables.labelFontSize=y(this.options.labelFontSize)?this.labelFontSize:this.options.labelFontSize,this.sessionVariables.labelMaxHeight=l,this.sessionVariables.labelMaxWidth=g,this.sessionVariables.labelAngle=y(this.sessionVariables.labelAngle)?0:this.sessionVariables.labelAngle))):(this.sessionVariables.labelMaxHeight=l,this.sessionVariables.labelMaxWidth=this.options.labelMaxWidth?this.options.labelMaxWidth:
|
||||
this.sessionVariables.labelMaxWidth)):(this.sessionVariables.labelMaxWidth=this.labelWrap?this.options.labelMaxWidth?this.options.labelMaxWidth:this.sessionVariables.labelMaxWidth:this.labelMaxWidth?this.options.labelMaxWidth?this.options.labelMaxWidth:this.sessionVariables.labelMaxWidth:g,this.sessionVariables.labelMaxHeight=l):(this.sessionVariables.labelAngle=this.labelAngle,this.sessionVariables.labelMaxWidth=0===this.labelAngle?g:Math.min((d-l*Math.sin(Math.PI/180*Math.abs(this.labelAngle)))/
|
||||
Math.cos(Math.PI/180*Math.abs(this.labelAngle)),l),y(this.options.labelWrap))?y(this.options.labelWrap)&&(this.labelWrap&&!y(this.options.labelMaxWidth)?(this.sessionVariables.labelMaxWidth=this.options.labelMaxWidth?this.options.labelMaxWidth>this.options.labelMaxWidth:this.sessionVariables.labelMaxWidth,this.sessionVariables.labelWrap=this.labelWrap,this.sessionVariables.labelMaxHeight=d):(this.sessionVariables.labelMaxWidth=this.options.labelMaxWidth?this.options.labelMaxWidth:g,this.sessionVariables.labelMaxHeight=
|
||||
0===this.labelAngle?l:d,y(this.options.labelMaxWidth)&&(this.sessionVariables.labelAngle=this.labelAngle))):this.options.labelWrap?(this.sessionVariables.labelMaxHeight=0===this.labelAngle?l:d,this.sessionVariables.labelWrap=this.labelWrap,this.sessionVariables.labelMaxWidth=g):(this.sessionVariables.labelMaxHeight=l,y(this.options.labelMaxWidth),this.sessionVariables.labelMaxWidth=this.options.labelMaxWidth?this.options.labelMaxWidth:this.sessionVariables.labelMaxWidth,this.sessionVariables.labelWrap=
|
||||
this.labelWrap);for(d=0;d<this._labels.length;d++)a=this._labels[d].textBlock,a.maxWidth=this.labelMaxWidth=this.sessionVariables.labelMaxWidth,a.fontSize=this.labelFontSize=this.sessionVariables.labelFontSize,a.angle=this.labelAngle=this.sessionVariables.labelAngle,a.wrap=this.labelWrap=this.sessionVariables.labelWrap,a.maxHeight=this.sessionVariables.labelMaxHeight,a.measureText()}else for(b=0;b<this._labels.length;b++)a=this._labels[b].textBlock,a.maxWidth=this.labelMaxWidth=y(this.options.labelMaxWidth)?
|
||||
this.sessionVariables.labelMaxWidth:this.options.labelMaxWidth,a.fontSize=this.labelFontSize=y(this.options.labelFontSize)?this.sessionVariables.labelFontSize:this.options.labelFontSize,a.angle=this.labelAngle=y(this.options.labelAngle)?this.sessionVariables.labelAngle:this.labelAngle,a.wrap=this.labelWrap=y(this.options.labelWrap)?this.sessionVariables.labelWrap:this.options.labelWrap,a.maxHeight=this.sessionVariables.labelMaxHeight,a.measureText();for(b=0;b<this.stripLines.length;b++){var g=this.stripLines[b],
|
||||
x;if("outside"===g.labelPlacement){l=this.sessionVariables.labelMaxWidth;if("bottom"===this._position||"top"===this._position)x="undefined"===typeof g.options.labelWrap?this.sessionVariables.labelMaxHeight:g.labelWrap?0.8*this.chart.height>>0:1.5*this.labelFontSize;if("left"===this._position||"right"===this._position)x="undefined"===typeof g.options.labelWrap?this.sessionVariables.labelMaxHeight:g.labelWrap?0.8*this.chart.width>>0:1.5*this.labelFontSize;c=y(g.options.labelBackgroundColor)?"#EEEEEE":
|
||||
g.options.labelBackgroundColor}else l="bottom"===this._position||"top"===this._position?0.9*this.chart.width>>0:0.9*this.chart.height>>0,x="undefined"===typeof g.options.labelWrap||g.labelWrap?"bottom"===this._position||"top"===this._position?0.8*this.chart.width>>0:0.8*this.chart.height>>0:1.5*this.labelFontSize,c=y(g.options.labelBackgroundColor)?y(g.startValue)&&0!==g.startValue?t?"transparent":null:"#EEEEEE":g.options.labelBackgroundColor;a=new V(this.ctx,{x:0,y:0,backgroundColor:c,borderColor:g.labelBorderColor,
|
||||
borderThickness:g.labelBorderThickness,cornerRadius:g.labelCornerRadius,maxWidth:g.options.labelMaxWidth?g.options.labelMaxWidth:l,maxHeight:x,angle:this.labelAngle,text:g.labelFormatter?g.labelFormatter({chart:this.chart,axis:this,stripLine:g}):g.label,horizontalAlign:"left",fontSize:"outside"===g.labelPlacement?g.options.labelFontSize?g.options.labelFontSize:this.labelFontSize:g.labelFontSize,fontFamily:"outside"===g.labelPlacement?g.options.labelFontFamily?g.options.labelFontFamily:this.labelFontFamily:
|
||||
g.labelFontFamily,fontWeight:"outside"===g.labelPlacement?g.options.fontWeight?g.options.fontWeight:this.fontWeight:g.fontWeight,fontColor:g.options.labelFontColor||g.color,fontStyle:"outside"===g.labelPlacement?g.options.fontStyle?g.options.fontStyle:this.fontWeight:g.fontStyle,textBaseline:"middle"});this._stripLineLabels.push({position:g.value,textBlock:a,effectiveHeight:null,stripLine:g})}};B.prototype.createLabelsAndCalculateWidth=function(){var a=0,c=0;this._labels=[];this._stripLineLabels=
|
||||
[];if("left"===this._position||"right"===this._position){this.createLabels();for(c=0;c<this._labels.length;c++){var b=this._labels[c].textBlock,d=b.measureText(),f=0,f=0===this.labelAngle?d.width:d.width*Math.cos(Math.PI/180*Math.abs(this.labelAngle))+(d.height-b.fontSize/2)*Math.sin(Math.PI/180*Math.abs(this.labelAngle));a<f&&(a=f);this._labels[c].effectiveWidth=f}for(c=0;c<this._stripLineLabels.length;c++)"outside"===this._stripLineLabels[c].stripLine.labelPlacement&&(this._stripLineLabels[c].stripLine.value>
|
||||
this.viewportMinimum&&this._stripLineLabels[c].stripLine.value<this.viewportMaximum)&&(b=this._stripLineLabels[c].textBlock,d=b.measureText(),f=0===this.labelAngle?d.width:d.width*Math.cos(Math.PI/180*Math.abs(this.labelAngle))+(d.height-b.fontSize/2)*Math.sin(Math.PI/180*Math.abs(this.labelAngle)),a<f&&(a=f),this._stripLineLabels[c].effectiveWidth=f)}return(this.title?this._titleTextBlock.measureText().height+2:0)+a+this.tickLength+5};B.prototype.createLabelsAndCalculateHeight=function(){var a=0;
|
||||
this._labels=[];this._stripLineLabels=[];var c,b=0;this.createLabels();if("bottom"===this._position||"top"===this._position){for(b=0;b<this._labels.length;b++){c=this._labels[b].textBlock;var d=c.measureText(),f=0,f=0===this.labelAngle?d.height:d.width*Math.sin(Math.PI/180*Math.abs(this.labelAngle))+(d.height-c.fontSize/2)*Math.cos(Math.PI/180*Math.abs(this.labelAngle));a<f&&(a=f);this._labels[b].effectiveHeight=f}for(b=0;b<this._stripLineLabels.length;b++)"outside"===this._stripLineLabels[b].stripLine.labelPlacement&&
|
||||
(c=this._stripLineLabels[b].textBlock,d=c.measureText(),f=0===this.labelAngle?d.height:d.width*Math.sin(Math.PI/180*Math.abs(this.labelAngle))+(d.height-c.fontSize/2)*Math.cos(Math.PI/180*Math.abs(this.labelAngle)),a<f&&(a=f),this._stripLineLabels[b].effectiveHeight=f)}return(this.title?this._titleTextBlock.measureText().height+2:0)+a+this.tickLength+5};B.setLayoutAndRender=function(a,c,b,d,f,g){var l,k,h,m,p=a[0]?a[0].chart:c[0].chart,n=p.ctx;if(a&&0<a.length)for(var e=0;e<a.length;e++)a[e]&&a[e].calculateAxisParameters();
|
||||
if(c&&0<c.length)for(e=0;e<c.length;e++)c[e].calculateAxisParameters();if(b&&0<b.length)for(e=0;e<b.length;e++)b[e].calculateAxisParameters();if(d&&0<d.length)for(e=0;e<d.length;e++)d[e].calculateAxisParameters();var q=0,r=0,s=0,t=0,u=0,v=0,z=0,w,A,B=k=0,D,E,F,G;D=E=F=G=!1;if(a&&0<a.length)for(e=0;e<a.length;e++)a[e]&&a[e].title&&(a[e]._titleTextBlock=new V(a[e].ctx,{text:a[e].title,horizontalAlign:"center",fontSize:a[e].titleFontSize,fontFamily:a[e].titleFontFamily,fontWeight:a[e].titleFontWeight,
|
||||
fontColor:a[e].titleFontColor,fontStyle:a[e].titleFontStyle,borderColor:a[e].titleBorderColor,borderThickness:a[e].titleBorderThickness,backgroundColor:a[e].titleBackgroundColor,cornerRadius:a[e].titleCornerRadius,textBaseline:"top"}));if(c&&0<c.length)for(e=0;e<c.length;e++)c[e]&&c[e].title&&(c[e]._titleTextBlock=new V(c[e].ctx,{text:c[e].title,horizontalAlign:"center",fontSize:c[e].titleFontSize,fontFamily:c[e].titleFontFamily,fontWeight:c[e].titleFontWeight,fontColor:c[e].titleFontColor,fontStyle:c[e].titleFontStyle,
|
||||
borderColor:c[e].titleBorderColor,borderThickness:c[e].titleBorderThickness,backgroundColor:c[e].titleBackgroundColor,cornerRadius:c[e].titleCornerRadius,textBaseline:"top"}));if(b&&0<b.length)for(e=0;e<b.length;e++)b[e]&&b[e].title&&(b[e]._titleTextBlock=new V(b[e].ctx,{text:b[e].title,horizontalAlign:"center",fontSize:b[e].titleFontSize,fontFamily:b[e].titleFontFamily,fontWeight:b[e].titleFontWeight,fontColor:b[e].titleFontColor,fontStyle:b[e].titleFontStyle,borderColor:b[e].titleBorderColor,borderThickness:b[e].titleBorderThickness,
|
||||
backgroundColor:b[e].titleBackgroundColor,cornerRadius:b[e].titleCornerRadius,textBaseline:"top"}));if(d&&0<d.length)for(e=0;e<d.length;e++)d[e]&&d[e].title&&(d[e]._titleTextBlock=new V(d[e].ctx,{text:d[e].title,horizontalAlign:"center",fontSize:d[e].titleFontSize,fontFamily:d[e].titleFontFamily,fontWeight:d[e].titleFontWeight,fontColor:d[e].titleFontColor,fontStyle:d[e].titleFontStyle,borderColor:d[e].titleBorderColor,borderThickness:d[e].titleBorderThickness,backgroundColor:d[e].titleBackgroundColor,
|
||||
cornerRadius:d[e].titleCornerRadius,textBaseline:"top"}));if("normal"===f){var t=[],u=[],v=[],z=[],H=[],I=[],L=[],J=[];if(a&&0<a.length)for(e=0;e<a.length;e++)a[e]&&a[e].title&&(a[e]._titleTextBlock.maxWidth=a[e].titleMaxWidth||g.width,a[e]._titleTextBlock.maxHeight=a[e].titleWrap?0.8*g.height:1.5*a[e].titleFontSize,a[e]._titleTextBlock.angle=0);if(c&&0<c.length)for(e=0;e<c[e].length;e++)c[e]&&c[e].title&&(c[e]._titleTextBlock.maxWidth=c[e].titleMaxWidth||g.width,c[e]._titleTextBlock.maxHeight=c[e].titleWrap?
|
||||
0.8*g.height:1.5*c[e].titleFontSize,c[e]._titleTextBlock.angle=0);if(b&&0<b.length)for(e=0;e<b.length;e++)b[e]&&b[e].title&&(b[e]._titleTextBlock.maxWidth=b[e].titleMaxWidth||g.height,b[e]._titleTextBlock.maxHeight=b[e].titleWrap?0.8*g.width:1.5*b[e].titleFontSize,b[e]._titleTextBlock.angle=-90);if(d&&0<d.length)for(e=0;e<d.length;e++)d[e]&&d[e].title&&(d[e]._titleTextBlock.maxWidth=d[e].titleMaxWidth||g.height,d[e]._titleTextBlock.maxHeight=d[e].titleWrap?0.8*g.width:1.5*d[e].titleFontSize,d[e]._titleTextBlock.angle=
|
||||
90);for(;4>q;){var N=0,Q=0,O=0,P=0,K=f=0,C=0,R=0,Y=0,U=0,T=0,S=0;if(b&&0<b.length)for(v=[],e=T=0;e<b.length;e++)v.push(Math.ceil(b[e]?b[e].createLabelsAndCalculateWidth():0)),T+=v[e],C+=b[e]?b[e].margin:0;else v.push(Math.ceil(b[0]?b[0].createLabelsAndCalculateWidth():0));L.push(v);if(d&&0<d.length)for(z=[],e=S=0;e<d.length;e++)z.push(Math.ceil(d[e]?d[e].createLabelsAndCalculateWidth():0)),S+=z[e],R+=d[e]?d[e].margin:0;else z.push(Math.ceil(d[0]?d[0].createLabelsAndCalculateWidth():0));J.push(z);
|
||||
l=Math.round(g.x1+T+C);h=Math.round(g.x2-S-R>p.width-10?p.width-10:g.x2-S-R);if(a&&0<a.length)for(t=[],e=Y=0;e<a.length;e++)a[e]&&(a[e].lineCoordinates={}),a[e].lineCoordinates.width=Math.abs(h-l),a[e].title&&(a[e]._titleTextBlock.maxWidth=0<a[e].titleMaxWidth&&a[e].titleMaxWidth<a[e].lineCoordinates.width?a[e].titleMaxWidth:a[e].lineCoordinates.width),t.push(Math.ceil(a[e]?a[e].createLabelsAndCalculateHeight():0)),Y+=t[e],f+=a[e]?a[e].margin:0;else t.push(Math.ceil(a[0]?a[0].createLabelsAndCalculateHeight():
|
||||
0));H.push(t);if(c&&0<c.length)for(u=[],e=U=0;e<c.length;e++)c[e]&&(c[e].lineCoordinates={}),c[e].lineCoordinates.width=Math.abs(h-l),c[e].title&&(c[e]._titleTextBlock.maxWidth=0<c[e].titleMaxWidth&&c[e].titleMaxWidth<c[e].lineCoordinates.width?c[e].titleMaxWidth:c[e].lineCoordinates.width),u.push(Math.ceil(c[e]?c[e].createLabelsAndCalculateHeight():0)),U+=u[e],K+=c[e]?c[e].margin:0;else u.push(Math.ceil(c[0]?c[0].createLabelsAndCalculateHeight():0));I.push(u);if(a&&0<a.length)for(e=0;e<a.length;e++)a[e]&&
|
||||
(a[e].lineCoordinates.x1=l,h=Math.round(g.x2-S-R>p.width-10?p.width-10:g.x2-S-R),a[e]._labels&&1<a[e]._labels.length&&(k=m=0,m=a[e]._labels[1],k="dateTime"===a[e].chart.plotInfo.axisXValueType?a[e]._labels[a[e]._labels.length-2]:a[e]._labels[a[e]._labels.length-1],r=m.textBlock.width*Math.cos(Math.PI/180*Math.abs(m.textBlock.angle))+(m.textBlock.height-k.textBlock.fontSize/2)*Math.sin(Math.PI/180*Math.abs(m.textBlock.angle)),s=k.textBlock.width*Math.cos(Math.PI/180*Math.abs(k.textBlock.angle))+(k.textBlock.height-
|
||||
k.textBlock.fontSize/2)*Math.sin(Math.PI/180*Math.abs(k.textBlock.angle))),a[e]&&(a[e].labelAutoFit&&!y(w)&&!y(A))&&(k=0,0<a[e].labelAngle?A+s>h&&(k+=0<a[e].labelAngle?A+s-h-S:0):0>a[e].labelAngle?w-r<l&&w-r<a[e].viewportMinimum&&(B=l-(C+a[e].tickLength+v+w-r+a[e].labelFontSize/2)):0===a[e].labelAngle&&(A+s>h&&(k=A+s/2-h-S),w-r<l&&w-r<a[e].viewportMinimum&&(B=l-C-a[e].tickLength-v-w+r/2)),a[e].viewportMaximum===a[e].maximum&&a[e].viewportMinimum===a[e].minimum&&0<a[e].labelAngle&&0<k?h-=k:a[e].viewportMaximum===
|
||||
a[e].maximum&&a[e].viewportMinimum===a[e].minimum&&0>a[e].labelAngle&&0<B?l+=B:a[e].viewportMaximum===a[e].maximum&&a[e].viewportMinimum===a[e].minimum&&0===a[e].labelAngle&&(0<B&&(l+=B),0<k&&(h-=k))),p.panEnabled?Y=p.sessionVariables.axisX.height:p.sessionVariables.axisX.height=Y,k=Math.round(g.y2-Y-f+N),m=Math.round(g.y2),a[e].lineCoordinates.x2=h,a[e].lineCoordinates.width=h-l,a[e].lineCoordinates.y1=k,a[e].lineCoordinates.y2=k,a[e].bounds={x1:l,y1:k,x2:h,y2:m-(Y+f-t[e]-N),width:h-l,height:m-k}),
|
||||
N+=t[e]+a[e].margin;if(c&&0<c.length)for(e=0;e<c.length;e++)c[e].lineCoordinates.x1=Math.round(g.x1+T+C),c[e].lineCoordinates.x2=Math.round(g.x2-S-R>p.width-10?p.width-10:g.x2-S-R),c[e].lineCoordinates.width=Math.abs(h-l),c[e]._labels&&1<c[e]._labels.length&&(m=c[e]._labels[1],k="dateTime"===c[e].chart.plotInfo.axisXValueType?c[e]._labels[c[e]._labels.length-2]:c[e]._labels[c[e]._labels.length-1],r=m.textBlock.width*Math.cos(Math.PI/180*Math.abs(m.textBlock.angle))+(m.textBlock.height-k.textBlock.fontSize/
|
||||
2)*Math.sin(Math.PI/180*Math.abs(m.textBlock.angle)),s=k.textBlock.width*Math.cos(Math.PI/180*Math.abs(k.textBlock.angle))+(k.textBlock.height-k.textBlock.fontSize/2)*Math.sin(Math.PI/180*Math.abs(k.textBlock.angle))),p.panEnabled?U=p.sessionVariables.axisX2.height:p.sessionVariables.axisX2.height=U,k=Math.round(g.y1),m=Math.round(g.y2+c[e].margin),c[e].lineCoordinates.y1=k+U+K-Q,c[e].lineCoordinates.y2=k,c[e].bounds={x1:l,y1:k+(U+K-u[e]-Q),x2:h,y2:m,width:h-l,height:m-k},Q+=u[e]+c[e].margin;if(b&&
|
||||
0<b.length)for(e=0;e<b.length;e++)C=10,b[e]&&(l=Math.round(a[0]?a[0].lineCoordinates.x1:c[0].lineCoordinates.x1),C=b[e]._labels&&0<b[e]._labels.length?b[e]._labels[b[e]._labels.length-1].textBlock.height/2:10,k=Math.round(g.y1+U+K<Math.max(C,10)?Math.max(C,10):g.y1+U+K),h=Math.round(a[0]?a[0].lineCoordinates.x1:c[0].lineCoordinates.x1),C=0<a.length?0:b[e]._labels&&0<b[e]._labels.length?b[e]._labels[0].textBlock.height/2:10,m=Math.round(g.y2-Y-f-C),b[e].lineCoordinates={x1:h-O,y1:k,x2:h-O,y2:m,height:Math.abs(m-
|
||||
k)},b[e].bounds={x1:l-(v[e]+O),y1:k,x2:h,y2:m,width:h-l,height:m-k},b[e].title&&(b[e]._titleTextBlock.maxWidth=0<b[e].titleMaxWidth&&b[e].titleMaxWidth<b[e].lineCoordinates.height?b[e].titleMaxWidth:b[e].lineCoordinates.height),O+=v[e]+b[e].margin);if(d&&0<d.length)for(e=0;e<d.length;e++)d[e]&&(l=Math.round(a[0]?a[0].lineCoordinates.x2:c[0].lineCoordinates.x2),h=Math.round(l),C=d[e]._labels&&0<d[e]._labels.length?d[e]._labels[d[e]._labels.length-1].textBlock.height/2:0,k=Math.round(g.y1+U+K<Math.max(C,
|
||||
10)?Math.max(C,10):g.y1+U+K),C=0<a.length?0:d[e]._labels&&0<d[e]._labels.length?d[e]._labels[0].textBlock.height/2:0,m=Math.round(g.y2-(Y+f+C)),d[e].lineCoordinates={x1:l+P,y1:k,x2:l+P,y2:m,height:Math.abs(m-k)},d[e].bounds={x1:l,y1:k,x2:h+(z[e]+P),y2:m,width:h-l,height:m-k},d[e].title&&(d[e]._titleTextBlock.maxWidth=0<d[e].titleMaxWidth&&d[e].titleMaxWidth<d[e].lineCoordinates.height?d[e].titleMaxWidth:d[e].lineCoordinates.height),P+=z[e]+d[e].margin);if(a&&0<a.length)for(e=0;e<a.length;e++)a[e]&&
|
||||
(a[e].calculateValueToPixelConversionParameters(),a[e]._labels&&1<a[e]._labels.length&&(w=(a[e].logarithmic?Math.log(a[e]._labels[1].position/a[e].viewportMinimum)/a[e].conversionParameters.lnLogarithmBase:a[e]._labels[1].position-a[e].viewportMinimum)*Math.abs(a[e].conversionParameters.pixelPerUnit)+a[e].lineCoordinates.x1,A="dateTime"===a[e].chart.plotInfo.axisXValueType?(a[e].logarithmic?Math.log(a[e]._labels[a[e]._labels.length-2].position/a[e].viewportMinimum)/a[e].conversionParameters.lnLogarithmBase:
|
||||
a[e]._labels[a[e]._labels.length-2].position-a[e].viewportMinimum)*Math.abs(a[e].conversionParameters.pixelPerUnit)+a[e].lineCoordinates.x1:(a[e].logarithmic?Math.log(a[e]._labels[a[e]._labels.length-1].position/a[e].viewportMinimum)/a[e].conversionParameters.lnLogarithmBase:a[e]._labels[a[e]._labels.length-1].position-a[e].viewportMinimum)*Math.abs(a[e].conversionParameters.pixelPerUnit)+a[e].lineCoordinates.x1));if(c&&0<c.length)for(e=0;e<c.length;e++)c[e].calculateValueToPixelConversionParameters(),
|
||||
c[e]._labels&&1<c[e]._labels.length&&(w=(c[e].logarithmic?Math.log(c[e]._labels[1].position/c[e].viewportMinimum)/c[e].conversionParameters.lnLogarithmBase:c[e]._labels[1].position-c[e].viewportMinimum)*Math.abs(c[e].conversionParameters.pixelPerUnit)+c[e].lineCoordinates.x1,A="dateTime"===c[e].chart.plotInfo.axisXValueType?(c[e].logarithmic?Math.log(c[e]._labels[c[e]._labels.length-2].position/c[e].viewportMinimum)/c[e].conversionParameters.lnLogarithmBase:c[e]._labels[c[e]._labels.length-2].position-
|
||||
c[e].viewportMinimum)*Math.abs(c[e].conversionParameters.pixelPerUnit)+c[e].lineCoordinates.x1:(c[e].logarithmic?Math.log(c[e]._labels[c[e]._labels.length-1].position/c[e].viewportMinimum)/c[e].conversionParameters.lnLogarithmBase:c[e]._labels[c[e]._labels.length-1].position-c[e].viewportMinimum)*Math.abs(c[e].conversionParameters.pixelPerUnit)+c[e].lineCoordinates.x1);if(b&&0<b.length)for(e=0;e<b.length;e++)b[e].calculateValueToPixelConversionParameters();if(d&&0<d.length)for(e=0;e<d.length;e++)d[e].calculateValueToPixelConversionParameters();
|
||||
if(0<q){if(a&&0<a.length)for(e=0;e<a.length;e++)D=H[q-1][e]===H[q][e]?!0:!1;else D=!0;if(c&&0<c.length)for(e=0;e<c.length;e++)E=I[q-1][e]===I[q][e]?!0:!1;else E=!0;if(b&&0<b.length)for(e=0;e<b.length;e++)F=L[q-1][e]===L[q][e]?!0:!1;else F=!0;if(d&&0<d.length)for(e=0;e<d.length;e++)G=J[q-1][e]===J[q][e]?!0:!1;else G=!0}if(D&&E&&F&&G)break;q++}n.save();n.beginPath();a[0]&&n.rect(5,a[0].bounds.y1,a[0].chart.width-10,a[0].bounds.height);c[0]&&n.rect(5,c[c.length-1].bounds.y1,c[0].chart.width-10,c[0].bounds.height);
|
||||
n.clip();if(a&&0<a.length)for(e=0;e<a.length;e++)a[e].renderLabelsTicksAndTitle();if(c&&0<c.length)for(e=0;e<c.length;e++)c[e].renderLabelsTicksAndTitle();n.restore();if(b&&0<b.length)for(e=0;e<b.length;e++)b[e].renderLabelsTicksAndTitle();if(d&&0<d.length)for(e=0;e<d.length;e++)d[e].renderLabelsTicksAndTitle()}else{w=[];A=[];B=[];r=[];s=[];H=[];I=[];L=[];if(a&&0<a.length)for(e=0;e<a.length;e++)a[e]&&a[e].title&&(a[e]._titleTextBlock.maxWidth=a[e].titleMaxWidth||g.width,a[e]._titleTextBlock.maxHeight=
|
||||
a[e].titleWrap?0.8*g.height:1.5*a[e].titleFontSize,a[e]._titleTextBlock.angle=-90);if(c&&0<c.length)for(e=0;e<c.length;e++)c[e]&&c[e].title&&(c[e]._titleTextBlock.maxWidth=c[e].titleMaxWidth||g.width,c[e]._titleTextBlock.maxHeight=c[e].titleWrap?0.8*g.height:1.5*c[e].titleFontSize,c[e]._titleTextBlock.angle=90);if(b&&0<b.length)for(e=0;e<b.length;e++)b[e]&&b[e].title&&(b[e]._titleTextBlock.maxWidth=b[e].titleMaxWidth||g.width,b[e]._titleTextBlock.maxHeight=b[e].titleWrap?0.8*g.height:1.5*b[e].titleFontSize,
|
||||
b[e]._titleTextBlock.angle=0);if(d&&0<d.length)for(e=0;e<d.length;e++)d[e]&&d[e].title&&(d[e]._titleTextBlock.maxWidth=d[e].titleMaxWidth||g.width,d[e]._titleTextBlock.maxHeight=d[e].titleWrap?0.8*g.height:1.5*d[e].titleFontSize,d[e]._titleTextBlock.angle=0);for(;4>q;){U=Y=T=P=R=C=K=f=O=J=Q=N=0;if(a&&0<a.length)for(B=[],e=Y=0;e<a.length;e++)B.push(Math.ceil(a[e]?a[e].createLabelsAndCalculateWidth():0)),Y+=B[e],f+=a[e]?a[e].margin:0;else B.push(Math.ceil(a[0]?a[0].createLabelsAndCalculateWidth():0));
|
||||
I.push(B);if(c&&0<c.length)for(r=[],e=U=0;e<c.length;e++)r.push(Math.ceil(c[e]?c[e].createLabelsAndCalculateWidth():0)),U+=r[e],K+=c[e]?c[e].margin:0;else r.push(Math.ceil(c[0]?c[0].createLabelsAndCalculateWidth():0));L.push(r);if(b&&0<b.length)for(e=0;e<b.length;e++)b[e].lineCoordinates={},l=Math.round(g.x1+Y+f),h=Math.round(g.x2-U-K>p.width-10?p.width-10:g.x2-U-K),b[e].labelAutoFit&&!y(t)&&(0<!a.length&&(l=0>b[e].labelAngle?Math.max(l,t):0===b[e].labelAngle?Math.max(l,t/2):l),0<!c.length&&(h=0<
|
||||
b[e].labelAngle?h-u/2:0===b[e].labelAngle?h-u/2:h)),b[e].lineCoordinates.x1=l,b[e].lineCoordinates.x2=h,b[e].lineCoordinates.width=Math.abs(h-l),b[e].title&&(b[e]._titleTextBlock.maxWidth=0<b[e].titleMaxWidth&&b[e].titleMaxWidth<b[e].lineCoordinates.width?b[e].titleMaxWidth:b[e].lineCoordinates.width);if(d&&0<d.length)for(e=0;e<d.length;e++)d[e].lineCoordinates={},l=Math.round(g.x1+Y+f),h=Math.round(g.x2-U-K>d[e].chart.width-10?d[e].chart.width-10:g.x2-U-K),d[e]&&d[e].labelAutoFit&&!y(v)&&(0<!a.length&&
|
||||
(l=0<d[e].labelAngle?Math.max(l,v):0===d[e].labelAngle?Math.max(l,v/2):l),0<!c.length&&(h-=z/2)),d[e].lineCoordinates.x1=l,d[e].lineCoordinates.x2=h,d[e].lineCoordinates.width=Math.abs(h-l),d[e].title&&(d[e]._titleTextBlock.maxWidth=0<d[e].titleMaxWidth&&d[e].titleMaxWidth<d[e].lineCoordinates.width?d[e].titleMaxWidth:d[e].lineCoordinates.width);if(b&&0<b.length)for(w=[],e=P=0;e<b.length;e++)w.push(Math.ceil(b[e]?b[e].createLabelsAndCalculateHeight():0)),P+=w[e]+b[e].margin,C+=b[e].margin;else w.push(Math.ceil(b[0]?
|
||||
b[0].createLabelsAndCalculateHeight():0));s.push(w);if(d&&0<d.length)for(A=[],e=T=0;e<d.length;e++)A.push(Math.ceil(d[e]?d[e].createLabelsAndCalculateHeight():0)),T+=A[e],R+=d[e].margin;else A.push(Math.ceil(d[0]?d[0].createLabelsAndCalculateHeight():0));H.push(A);if(b&&0<b.length)for(e=0;e<b.length;e++)0<b[e]._labels.length&&(m=b[e]._labels[0],k=b[e]._labels[b[e]._labels.length-1],t=m.textBlock.width*Math.cos(Math.PI/180*Math.abs(m.textBlock.angle))+(m.textBlock.height-k.textBlock.fontSize/2)*Math.sin(Math.PI/
|
||||
180*Math.abs(m.textBlock.angle)),u=k.textBlock.width*Math.cos(Math.PI/180*Math.abs(k.textBlock.angle))+(k.textBlock.height-k.textBlock.fontSize/2)*Math.sin(Math.PI/180*Math.abs(k.textBlock.angle)));if(d&&0<d.length)for(e=0;e<d.length;e++)d[e]&&0<d[e]._labels.length&&(m=d[e]._labels[0],k=d[e]._labels[d[e]._labels.length-1],v=m.textBlock.width*Math.cos(Math.PI/180*Math.abs(m.textBlock.angle))+(m.textBlock.height-k.textBlock.fontSize/2)*Math.sin(Math.PI/180*Math.abs(m.textBlock.angle)),z=k.textBlock.width*
|
||||
Math.cos(Math.PI/180*Math.abs(k.textBlock.angle))+(k.textBlock.height-k.textBlock.fontSize/2)*Math.sin(Math.PI/180*Math.abs(k.textBlock.angle)));if(p.panEnabled)for(e=0;e<b.length;e++)w[e]=p.sessionVariables.axisY.height;else for(e=0;e<b.length;e++)p.sessionVariables.axisY.height=w[e];if(b&&0<b.length)for(e=b.length-1;0<=e;e--)k=Math.round(g.y2),m=Math.round(g.y2>b[e].chart.height-10?b[e].chart.height-10:g.y2),b[e].lineCoordinates.y1=k-(w[e]+b[e].margin+N),b[e].lineCoordinates.y2=k-(w[e]+b[e].margin+
|
||||
N),b[e].bounds={x1:l,y1:k-(w[e]+N+b[e].margin),x2:h,y2:m-(N+b[e].margin),width:h-l,height:w[e]},b[e].title&&(b[e]._titleTextBlock.maxWidth=0<b[e].titleMaxWidth&&b[e].titleMaxWidth<b[e].lineCoordinates.width?b[e].titleMaxWidth:b[e].lineCoordinates.width),N+=w[e]+b[e].margin;if(d&&0<d.length)for(e=d.length-1;0<=e;e--)d[e]&&(k=Math.round(g.y1),m=Math.round(g.y1+(A[e]+d[e].margin+Q)),d[e].lineCoordinates.y1=m,d[e].lineCoordinates.y2=m,d[e].bounds={x1:l,y1:k+(d[e].margin+Q),x2:h,y2:m,width:h-l,height:T},
|
||||
d[e].title&&(d[e]._titleTextBlock.maxWidth=0<d[e].titleMaxWidth&&d[e].titleMaxWidth<d[e].lineCoordinates.width?d[e].titleMaxWidth:d[e].lineCoordinates.width),Q+=A[e]+d[e].margin);if(a&&0<a.length)for(e=0;e<a.length;e++){C=a[e]._labels&&0<a[e]._labels.length?a[e]._labels[0].textBlock.fontSize/2:0;l=Math.round(g.x1+f);k=d&&0<d.length?Math.round(d[0]?d[0].lineCoordinates.y2:g.y1<Math.max(C,10)?Math.max(C,10):g.y1):g.y1<Math.max(C,10)?Math.max(C,10):g.y1;h=Math.round(g.x1+Y+f);m=b&&0<b.length?Math.round(b[0]?
|
||||
b[0].lineCoordinates.y1:g.y2-P>p.height-Math.max(C,10)?p.height-Math.max(C,10):g.y2-P):g.y2>p.height-Math.max(C,10)?p.height-Math.max(C,10):g.y2;if(b&&0<b.length)for(C=0;C<b.length;C++)b[C]&&b[C].labelAutoFit&&(h=0>b[C].labelAngle?Math.max(h,t):0===b[C].labelAngle?Math.max(h,t/2):h,l=0>b[C].labelAngle||0===b[C].labelAngle?h-Y:l);if(d&&0<d.length)for(C=0;C<d.length;C++)d[C]&&d[C].labelAutoFit&&(h=d[C].lineCoordinates.x1,l=h-Y);a[e].lineCoordinates={x1:h-J,y1:k,x2:h-J,y2:m,height:Math.abs(m-k)};a[e].bounds=
|
||||
{x1:h-(B[e]+J),y1:k,x2:h,y2:m,width:h-l,height:m-k};a[e].title&&(a[e]._titleTextBlock.maxWidth=0<a[e].titleMaxWidth&&a[e].titleMaxWidth<a[e].lineCoordinates.height?a[e].titleMaxWidth:a[e].lineCoordinates.height);a[e].calculateValueToPixelConversionParameters();J+=B[e]+a[e].margin}if(c&&0<c.length)for(e=0;e<c.length;e++){C=c[e]._labels&&0<c[e]._labels.length?c[e]._labels[0].textBlock.fontSize/2:0;l=Math.round(g.x1-f);k=d&&0<d.length?Math.round(d[0]?d[0].lineCoordinates.y2:g.y1<Math.max(C,10)?Math.max(C,
|
||||
10):g.y1):g.y1<Math.max(C,10)?Math.max(C,10):g.y1;h=Math.round(g.x2-U-K);m=b&&0<b.length?Math.round(b[0]?b[0].lineCoordinates.y1:g.y2-P>p.height-Math.max(C,10)?p.height-Math.max(C,10):g.y2-P):g.y2>p.height-Math.max(C,10)?p.height-Math.max(C,10):g.y2;if(b&&0<b.length)for(C=0;C<b.length;C++)b[C]&&b[C].labelAutoFit&&(h=0>b[C].labelAngle?Math.max(h,t):0===b[C].labelAngle?Math.max(h,t/2):h,l=0>b[C].labelAngle||0===b[C].labelAngle?h-U:l);if(d&&0<d.length)for(C=0;C<d.length;C++)d[C]&&d[C].labelAutoFit&&
|
||||
(h=d[C].lineCoordinates.x2,l=h-U);c[e].lineCoordinates={x1:h+O,y1:k,x2:h+O,y2:m,height:Math.abs(m-k)};c[e].bounds={x1:l,y1:k,x2:h+r[e]+O,y2:m,width:h-l,height:m-k};c[e].title&&(c[e]._titleTextBlock.maxWidth=0<c[e].titleMaxWidth&&c[e].titleMaxWidth<c[e].lineCoordinates.height?c[e].titleMaxWidth:c[e].lineCoordinates.height);c[e].calculateValueToPixelConversionParameters();O+=r[e]+c[e].margin}if(b&&0<b.length)for(e=0;e<b.length;e++)b[e].calculateValueToPixelConversionParameters();if(d&&0<d.length)for(e=
|
||||
0;e<d.length;e++)d[e].calculateValueToPixelConversionParameters();if(0<q){if(a&&0<a.length)for(e=0;e<a.length;e++)D=I[q-1][e]===I[q][e]?!0:!1;else D=!0;if(c&&0<c.length)for(e=0;e<c.length;e++)E=L[q-1][e]===L[q][e]?!0:!1;else E=!0;if(b&&0<b.length)for(e=0;e<b.length;e++)F=s[q-1][e]===s[q][e]?!0:!1;else F=!0;if(d&&0<d.length)for(e=0;e<d.length;e++)G=H[q-1][e]===H[q][e]?!0:!1;else G=!0}if(D&&E&&F&&G)break;q++}if(b&&0<b.length)for(e=0;e<b.length;e++)b[e].renderLabelsTicksAndTitle();if(d&&0<d.length)for(e=
|
||||
0;e<d.length;e++)d[e].renderLabelsTicksAndTitle();if(a&&0<a.length)for(e=0;e<a.length;e++)a[e].renderLabelsTicksAndTitle();if(c&&0<c.length)for(e=0;e<c.length;e++)c[e].renderLabelsTicksAndTitle()}p.preparePlotArea();g=p.plotArea;n.save();n.beginPath();n.rect(g.x1,g.y1,Math.abs(g.x2-g.x1),Math.abs(g.y2-g.y1));n.clip();if(a&&0<a.length)for(e=0;e<a.length;e++)a[e].renderStripLinesOfThicknessType("value");if(c&&0<c.length)for(e=0;e<c.length;e++)c[e].renderStripLinesOfThicknessType("value");if(b&&0<b.length)for(e=
|
||||
0;e<b.length;e++)b[e].renderStripLinesOfThicknessType("value");if(d&&0<d.length)for(e=0;e<d.length;e++)d[e].renderStripLinesOfThicknessType("value");if(a&&0<a.length)for(e=0;e<a.length;e++)a[e].renderInterlacedColors();if(c&&0<c.length)for(e=0;e<c.length;e++)c[e].renderInterlacedColors();if(b&&0<b.length)for(e=0;e<b.length;e++)b[e].renderInterlacedColors();if(d&&0<d.length)for(e=0;e<d.length;e++)d[e].renderInterlacedColors();n.restore();if(a&&0<a.length)for(e=0;e<a.length;e++)a[e].renderGrid();if(c&&
|
||||
0<c.length)for(e=0;e<c.length;e++)c[e].renderGrid();if(b&&0<b.length)for(e=0;e<b.length;e++)b[e].renderGrid();if(d&&0<d.length)for(e=0;e<d.length;e++)d[e].renderGrid();if(a&&0<a.length)for(e=0;e<a.length;e++)a[e].renderAxisLine();if(c&&0<c.length)for(e=0;e<c.length;e++)c[e].renderAxisLine();if(b&&0<b.length)for(e=0;e<b.length;e++)b[e].renderAxisLine();if(d&&0<d.length)for(e=0;e<d.length;e++)d[e].renderAxisLine();if(a&&0<a.length)for(e=0;e<a.length;e++)a[e].renderStripLinesOfThicknessType("pixel");
|
||||
if(c&&0<c.length)for(e=0;e<c.length;e++)c[e].renderStripLinesOfThicknessType("pixel");if(b&&0<b.length)for(e=0;e<b.length;e++)b[e].renderStripLinesOfThicknessType("pixel");if(d&&0<d.length)for(e=0;e<d.length;e++)d[e].renderStripLinesOfThicknessType("pixel")};B.prototype.renderLabelsTicksAndTitle=function(){var a=!1,c=0,b=0,d=1,f=0;0!==this.labelAngle&&360!==this.labelAngle&&(d=1.2);if("undefined"===typeof this.options.interval){if("bottom"===this._position||"top"===this._position)if(this.logarithmic&&
|
||||
!this.equidistantInterval&&this.labelAutoFit){for(var c=[],d=0!==this.labelAngle&&360!==this.labelAngle?1:1.2,g,l=this.viewportMaximum,k=this.lineCoordinates.width/Math.log(this.range),h=this._labels.length-1;0<=h;h--){p=this._labels[h];if(p.position<this.viewportMinimum)break;p.position>this.viewportMaximum||!(h===this._labels.length-1||g<Math.log(l/p.position)*k/d)||(c.push(p),l=p.position,g=p.textBlock.width*Math.abs(Math.cos(Math.PI/180*this.labelAngle))+p.textBlock.height*Math.abs(Math.sin(Math.PI/
|
||||
180*this.labelAngle)))}this._labels=c}else{for(h=0;h<this._labels.length;h++)p=this._labels[h],p.position<this.viewportMinimum||(p=p.textBlock.width*Math.abs(Math.cos(Math.PI/180*this.labelAngle))+p.textBlock.height*Math.abs(Math.sin(Math.PI/180*this.labelAngle)),c+=p);c>this.lineCoordinates.width*d&&this.labelAutoFit&&(a=!0)}if("left"===this._position||"right"===this._position)if(this.logarithmic&&!this.equidistantInterval&&this.labelAutoFit){for(var c=[],m,l=this.viewportMaximum,k=this.lineCoordinates.height/
|
||||
Math.log(this.range),h=this._labels.length-1;0<=h;h--){p=this._labels[h];if(p.position<this.viewportMinimum)break;p.position>this.viewportMaximum||!(h===this._labels.length-1||m<Math.log(l/p.position)*k)||(c.push(p),l=p.position,m=p.textBlock.height*Math.abs(Math.cos(Math.PI/180*this.labelAngle))+p.textBlock.width*Math.abs(Math.sin(Math.PI/180*this.labelAngle)))}this._labels=c}else{for(h=0;h<this._labels.length;h++)p=this._labels[h],p.position<this.viewportMinimum||(p=p.textBlock.height*Math.abs(Math.cos(Math.PI/
|
||||
180*this.labelAngle))+p.textBlock.width*Math.abs(Math.sin(Math.PI/180*this.labelAngle)),b+=p);b>this.lineCoordinates.height*d&&this.labelAutoFit&&(a=!0)}}if("bottom"===this._position){for(var p,h=0;h<this._labels.length;h++)p=this._labels[h],p.position<this.viewportMinimum||p.position>this.viewportMaximum||(b=this.getPixelCoordinatesOnAxis(p.position),a&&0!==f++%2&&this.labelAutoFit||(this.tickThickness&&(this.ctx.lineWidth=this.tickThickness,this.ctx.strokeStyle=this.tickColor,d=1===this.ctx.lineWidth%
|
||||
2?(b.x<<0)+0.5:b.x<<0,this.ctx.beginPath(),this.ctx.moveTo(d,b.y<<0),this.ctx.lineTo(d,b.y+this.tickLength<<0),this.ctx.stroke()),0===p.textBlock.angle?(b.x-=p.textBlock.width/2,b.y+=this.tickLength+p.textBlock.fontSize/2):(b.x-=0>this.labelAngle?p.textBlock.width*Math.cos(Math.PI/180*this.labelAngle):0,b.y+=this.tickLength+Math.abs(0>this.labelAngle?p.textBlock.width*Math.sin(Math.PI/180*this.labelAngle)-5:5)),p.textBlock.x=b.x,p.textBlock.y=b.y,p.textBlock.render(!0)));this.title&&(this._titleTextBlock.measureText(),
|
||||
this._titleTextBlock.x=this.lineCoordinates.x1+this.lineCoordinates.width/2-this._titleTextBlock.width/2,this._titleTextBlock.y=this.bounds.y2-this._titleTextBlock.height-3,this.titleMaxWidth=this._titleTextBlock.maxWidth,this._titleTextBlock.render(!0))}else if("top"===this._position){for(h=0;h<this._labels.length;h++)p=this._labels[h],p.position<this.viewportMinimum||p.position>this.viewportMaximum||(b=this.getPixelCoordinatesOnAxis(p.position),a&&0!==f++%2&&this.labelAutoFit||(this.tickThickness&&
|
||||
(this.ctx.lineWidth=this.tickThickness,this.ctx.strokeStyle=this.tickColor,d=1===this.ctx.lineWidth%2?(b.x<<0)+0.5:b.x<<0,this.ctx.beginPath(),this.ctx.moveTo(d,b.y<<0),this.ctx.lineTo(d,b.y-this.tickLength<<0),this.ctx.stroke()),0===p.textBlock.angle?(b.x-=p.textBlock.width/2,b.y-=this.tickLength+p.textBlock.height/2):(b.x+=(p.textBlock.height-this.tickLength-this.labelFontSize/2)*Math.sin(Math.PI/180*this.labelAngle)-(0<this.labelAngle?p.textBlock.width*Math.cos(Math.PI/180*this.labelAngle):0),
|
||||
b.y-=this.tickLength+(p.textBlock.height/2*Math.cos(Math.PI/180*this.labelAngle)+(0<this.labelAngle?p.textBlock.width*Math.sin(Math.PI/180*this.labelAngle):0))),p.textBlock.x=b.x,p.textBlock.y=b.y,p.textBlock.render(!0)));this.title&&(this._titleTextBlock.measureText(),this._titleTextBlock.x=this.lineCoordinates.x1+this.lineCoordinates.width/2-this._titleTextBlock.width/2,this._titleTextBlock.y=this.bounds.y1+1,this.titleMaxWidth=this._titleTextBlock.maxWidth,this._titleTextBlock.render(!0))}else if("left"===
|
||||
this._position){for(h=0;h<this._labels.length;h++)p=this._labels[h],p.position<this.viewportMinimum||p.position>this.viewportMaximum||(b=this.getPixelCoordinatesOnAxis(p.position),a&&0!==f++%2&&this.labelAutoFit||(this.tickThickness&&(this.ctx.lineWidth=this.tickThickness,this.ctx.strokeStyle=this.tickColor,d=1===this.ctx.lineWidth%2?(b.y<<0)+0.5:b.y<<0,this.ctx.beginPath(),this.ctx.moveTo(b.x<<0,d),this.ctx.lineTo(b.x-this.tickLength<<0,d),this.ctx.stroke()),0===this.labelAngle?(p.textBlock.y=b.y,
|
||||
p.textBlock.x=b.x-p.textBlock.width*Math.cos(Math.PI/180*this.labelAngle)-this.tickLength-5):(p.textBlock.y=b.y-p.textBlock.width*Math.sin(Math.PI/180*this.labelAngle),p.textBlock.x=0<this.labelAngle?b.x-p.textBlock.width*Math.cos(Math.PI/180*this.labelAngle)-this.tickLength-5:b.x-p.textBlock.width*Math.cos(Math.PI/180*this.labelAngle)+(p.textBlock.height-p.textBlock.fontSize/2-5)*Math.sin(Math.PI/180*this.labelAngle)-this.tickLength),p.textBlock.render(!0)));this.title&&(this._titleTextBlock.measureText(),
|
||||
this._titleTextBlock.x=this.bounds.x1+1,this._titleTextBlock.y=this.lineCoordinates.height/2+this._titleTextBlock.width/2+this.lineCoordinates.y1,this.titleMaxWidth=this._titleTextBlock.maxWidth,this._titleTextBlock.render(!0))}else if("right"===this._position){for(h=0;h<this._labels.length;h++)p=this._labels[h],p.position<this.viewportMinimum||p.position>this.viewportMaximum||(b=this.getPixelCoordinatesOnAxis(p.position),a&&0!==f++%2&&this.labelAutoFit||(this.tickThickness&&(this.ctx.lineWidth=this.tickThickness,
|
||||
this.ctx.strokeStyle=this.tickColor,d=1===this.ctx.lineWidth%2?(b.y<<0)+0.5:b.y<<0,this.ctx.beginPath(),this.ctx.moveTo(b.x<<0,d),this.ctx.lineTo(b.x+this.tickLength<<0,d),this.ctx.stroke()),0===this.labelAngle?(p.textBlock.y=b.y,p.textBlock.x=b.x+this.tickLength+5):(p.textBlock.y=0>this.labelAngle?b.y:b.y-(p.textBlock.height-p.textBlock.fontSize/2-5)*Math.cos(Math.PI/180*this.labelAngle),p.textBlock.x=0<this.labelAngle?b.x+(p.textBlock.height-p.textBlock.fontSize/2-5)*Math.sin(Math.PI/180*this.labelAngle)+
|
||||
this.tickLength:b.x+this.tickLength+5),p.textBlock.render(!0)));this.title&&(this._titleTextBlock.measureText(),this._titleTextBlock.x=this.bounds.x2-1,this._titleTextBlock.y=this.lineCoordinates.height/2-this._titleTextBlock.width/2+this.lineCoordinates.y1,this.titleMaxWidth=this._titleTextBlock.maxWidth,this._titleTextBlock.render(!0))}};B.prototype.renderInterlacedColors=function(){var a=this.chart.plotArea.ctx,c,b,d=this.chart.plotArea,f=0;c=!0;if(("bottom"===this._position||"top"===this._position)&&
|
||||
this.interlacedColor)for(a.fillStyle=this.interlacedColor,f=0;f<this._labels.length;f++)c?(c=this.getPixelCoordinatesOnAxis(this._labels[f].position),b=f+1>this._labels.length-1?this.getPixelCoordinatesOnAxis(this.viewportMaximum):this.getPixelCoordinatesOnAxis(this._labels[f+1].position),a.fillRect(Math.min(b.x,c.x),d.y1,Math.abs(b.x-c.x),Math.abs(d.y1-d.y2)),c=!1):c=!0;else if(("left"===this._position||"right"===this._position)&&this.interlacedColor)for(a.fillStyle=this.interlacedColor,f=0;f<this._labels.length;f++)c?
|
||||
(b=this.getPixelCoordinatesOnAxis(this._labels[f].position),c=f+1>this._labels.length-1?this.getPixelCoordinatesOnAxis(this.viewportMaximum):this.getPixelCoordinatesOnAxis(this._labels[f+1].position),a.fillRect(d.x1,Math.min(b.y,c.y),Math.abs(d.x1-d.x2),Math.abs(c.y-b.y)),c=!1):c=!0;a.beginPath()};B.prototype.renderStripLinesOfThicknessType=function(a){if(this.stripLines&&0<this.stripLines.length&&a){for(var c=this,b,d=0,f=0,g=!1,l=!1,k=[],h=[],l=!1,d=0;d<this.stripLines.length;d++){var m=this.stripLines[d];
|
||||
m._thicknessType===a&&("pixel"===a&&(m.value<this.viewportMinimum||m.value>this.viewportMaximum||y(m.value)||isNaN(this.range))||k.push(m))}for(d=0;d<this._stripLineLabels.length;d++)if(m=this.stripLines[d],b=this._stripLineLabels[d],!(b.position<this.viewportMinimum||b.position>this.viewportMaximum||isNaN(this.range))){a=this.getPixelCoordinatesOnAxis(b.position);if("outside"===b.stripLine.labelPlacement)if(m&&(this.ctx.strokeStyle=m.color,"pixel"===m._thicknessType&&(this.ctx.lineWidth=m.thickness)),
|
||||
"bottom"===this._position){var p=1===this.ctx.lineWidth%2?(a.x<<0)+0.5:a.x<<0;this.ctx.beginPath();this.ctx.moveTo(p,a.y<<0);this.ctx.lineTo(p,a.y+this.tickLength<<0);this.ctx.stroke();0===this.labelAngle?(a.x-=b.textBlock.width/2,a.y+=this.tickLength+b.textBlock.fontSize/2):(a.x-=0>this.labelAngle?b.textBlock.width*Math.cos(Math.PI/180*this.labelAngle):0,a.y+=this.tickLength+Math.abs(0>this.labelAngle?b.textBlock.width*Math.sin(Math.PI/180*this.labelAngle)-5:5))}else"top"===this._position?(p=1===
|
||||
this.ctx.lineWidth%2?(a.x<<0)+0.5:a.x<<0,this.ctx.beginPath(),this.ctx.moveTo(p,a.y<<0),this.ctx.lineTo(p,a.y-this.tickLength<<0),this.ctx.stroke(),0===this.labelAngle?(a.x-=b.textBlock.width/2,a.y-=this.tickLength+b.textBlock.height):(a.x+=(b.textBlock.height-this.tickLength-this.labelFontSize/2)*Math.sin(Math.PI/180*this.labelAngle)-(0<this.labelAngle?b.textBlock.width*Math.cos(Math.PI/180*this.labelAngle):0),a.y-=this.tickLength+(b.textBlock.height*Math.cos(Math.PI/180*this.labelAngle)+(0<this.labelAngle?
|
||||
b.textBlock.width*Math.sin(Math.PI/180*this.labelAngle):0)))):"left"===this._position?(p=1===this.ctx.lineWidth%2?(a.y<<0)+0.5:a.y<<0,this.ctx.beginPath(),this.ctx.moveTo(a.x<<0,p),this.ctx.lineTo(a.x-this.tickLength<<0,p),this.ctx.stroke(),0===this.labelAngle?a.x=a.x-b.textBlock.width*Math.cos(Math.PI/180*this.labelAngle)-this.tickLength-5:(a.y-=b.textBlock.width*Math.sin(Math.PI/180*this.labelAngle),a.x=0<this.labelAngle?a.x-b.textBlock.width*Math.cos(Math.PI/180*this.labelAngle)-this.tickLength-
|
||||
5:a.x-b.textBlock.width*Math.cos(Math.PI/180*this.labelAngle)+(b.textBlock.height-b.textBlock.fontSize/2-5)*Math.sin(Math.PI/180*this.labelAngle)-this.tickLength)):"right"===this._position&&(p=1===this.ctx.lineWidth%2?(a.y<<0)+0.5:a.y<<0,this.ctx.beginPath(),this.ctx.moveTo(a.x<<0,p),this.ctx.lineTo(a.x+this.tickLength<<0,p),this.ctx.stroke(),0===this.labelAngle?a.x=a.x+this.tickLength+5:(a.y=0>this.labelAngle?a.y:a.y-(b.textBlock.height-b.textBlock.fontSize/2-5)*Math.cos(Math.PI/180*this.labelAngle),
|
||||
a.x=0<this.labelAngle?a.x+(b.textBlock.height-b.textBlock.fontSize/2-5)*Math.sin(Math.PI/180*this.labelAngle)+this.tickLength:a.x+this.tickLength+5));else b.textBlock.angle=-90,"bottom"===this._position?(b.textBlock.maxWidth=this.options.stripLines[d].labelMaxWidth?this.options.stripLines[d].labelMaxWidth:this.chart.plotArea.height-3,b.textBlock.measureText(),a.x-b.textBlock.height>this.chart.plotArea.x1?y(m.startValue)?a.x-=b.textBlock.height-b.textBlock.fontSize/2:a.x-=b.textBlock.height/2-b.textBlock.fontSize/
|
||||
2+3:(b.textBlock.angle=90,y(m.startValue)?a.x+=b.textBlock.height-b.textBlock.fontSize/2:a.x+=b.textBlock.height/2-b.textBlock.fontSize/2+3),a.y=-90===b.textBlock.angle?"near"===b.stripLine.labelAlign?this.chart.plotArea.y2-3:"center"===b.stripLine.labelAlign?(this.chart.plotArea.y2+this.chart.plotArea.y1+b.textBlock.width)/2:this.chart.plotArea.y1+b.textBlock.width+3:"near"===b.stripLine.labelAlign?this.chart.plotArea.y2-b.textBlock.width-3:"center"===b.stripLine.labelAlign?(this.chart.plotArea.y2+
|
||||
this.chart.plotArea.y1-b.textBlock.width)/2:this.chart.plotArea.y1+3):"top"===this._position?(b.textBlock.maxWidth=this.options.stripLines[d].labelMaxWidth?this.options.stripLines[d].labelMaxWidth:this.chart.plotArea.height-3,b.textBlock.measureText(),a.x-b.textBlock.height>this.chart.plotArea.x1?y(m.startValue)?a.x-=b.textBlock.height-b.textBlock.fontSize/2:a.x-=b.textBlock.height/2-b.textBlock.fontSize/2+3:(b.textBlock.angle=90,y(m.startValue)?a.x+=b.textBlock.height-b.textBlock.fontSize/2:a.x+=
|
||||
b.textBlock.height/2-b.textBlock.fontSize/2+3),a.y=-90===b.textBlock.angle?"near"===b.stripLine.labelAlign?this.chart.plotArea.y1+b.textBlock.width+3:"center"===b.stripLine.labelAlign?(this.chart.plotArea.y2+this.chart.plotArea.y1+b.textBlock.width)/2:this.chart.plotArea.y2-3:"near"===b.stripLine.labelAlign?this.chart.plotArea.y1+3:"center"===b.stripLine.labelAlign?(this.chart.plotArea.y2+this.chart.plotArea.y1-b.textBlock.width)/2:this.chart.plotArea.y2-b.textBlock.width-3):"left"===this._position?
|
||||
(b.textBlock.maxWidth=this.options.stripLines[d].labelMaxWidth?this.options.stripLines[d].labelMaxWidth:this.chart.plotArea.width-3,b.textBlock.angle=0,b.textBlock.measureText(),a.y-b.textBlock.height>this.chart.plotArea.y1?y(m.startValue)?a.y-=b.textBlock.height-b.textBlock.fontSize/2:a.y-=b.textBlock.height/2-b.textBlock.fontSize+3:a.y-b.textBlock.height<this.chart.plotArea.y2?a.y+=b.textBlock.fontSize/2+3:y(m.startValue)?a.y-=b.textBlock.height-b.textBlock.fontSize/2:a.y-=b.textBlock.height/2-
|
||||
b.textBlock.fontSize+3,a.x="near"===b.stripLine.labelAlign?this.chart.plotArea.x1+3:"center"===b.stripLine.labelAlign?(this.chart.plotArea.x2+this.chart.plotArea.x1)/2-b.textBlock.width/2:this.chart.plotArea.x2-b.textBlock.width-3):"right"===this._position&&(b.textBlock.maxWidth=this.options.stripLines[d].labelMaxWidth?this.options.stripLines[d].labelMaxWidth:this.chart.plotArea.width-3,b.textBlock.angle=0,b.textBlock.measureText(),a.y-+b.textBlock.height>this.chart.plotArea.y1?y(m.startValue)?a.y-=
|
||||
b.textBlock.height-b.textBlock.fontSize/2:a.y-=b.textBlock.height/2-b.textBlock.fontSize/2-3:a.y-b.textBlock.height<this.chart.plotArea.y2?a.y+=b.textBlock.fontSize/2+3:y(m.startValue)?a.y-=b.textBlock.height-b.textBlock.fontSize/2:a.y-=b.textBlock.height/2-b.textBlock.fontSize/2+3,a.x="near"===b.stripLine.labelAlign?this.chart.plotArea.x2-b.textBlock.width-3:"center"===b.stripLine.labelAlign?(this.chart.plotArea.x2+this.chart.plotArea.x1)/2-b.textBlock.width/2:this.chart.plotArea.x1+3);b.textBlock.x=
|
||||
a.x;b.textBlock.y=a.y;h.push(b)}if(!l){l=!1;this.ctx.save();this.ctx.beginPath();this.ctx.rect(this.chart.plotArea.x1,this.chart.plotArea.y1,this.chart.plotArea.width,this.chart.plotArea.height);this.ctx.clip();for(d=0;d<k.length;d++)m=k[d],m.showOnTop?g||(g=!0,this.chart.addEventListener("dataAnimationIterationEnd",function(){this.ctx.save();this.ctx.beginPath();this.ctx.rect(this.chart.plotArea.x1,this.chart.plotArea.y1,this.chart.plotArea.width,this.chart.plotArea.height);this.ctx.clip();for(f=
|
||||
0;f<k.length;f++)m=k[f],m.showOnTop&&m.render();this.ctx.restore()},m)):m.render();for(d=0;d<h.length;d++)b=h[d],b.stripLine.showOnTop?l||(l=!0,this.chart.addEventListener("dataAnimationIterationEnd",function(){for(f=0;f<h.length;f++)b=h[f],"inside"===b.stripLine.labelPlacement&&b.stripLine.showOnTop&&(c.ctx.save(),c.ctx.beginPath(),c.ctx.rect(c.chart.plotArea.x1,c.chart.plotArea.y1,c.chart.plotArea.width,c.chart.plotArea.height),c.ctx.clip(),b.textBlock.render(!0),c.ctx.restore())},b.textBlock)):
|
||||
"inside"===b.stripLine.labelPlacement&&b.textBlock.render(!0);this.ctx.restore();l=!0}if(l)for(l=!1,d=0;d<h.length;d++)b=h[d],b.stripLine.showOnTop?l||(l=!0,this.chart.addEventListener("dataAnimationIterationEnd",function(){for(f=0;f<h.length;f++)b=h[f],"outside"===b.stripLine.labelPlacement&&b.stripLine.showOnTop&&b.textBlock.render(!0)},b.textBlock)):"outside"===b.stripLine.labelPlacement&&b.textBlock.render(!0)}};B.prototype.renderGrid=function(){if(this.gridThickness&&0<this.gridThickness){var a=
|
||||
this.chart.ctx;a.save();var c,b=this.chart.plotArea;a.lineWidth=this.gridThickness;a.strokeStyle=this.gridColor;a.setLineDash&&a.setLineDash(F(this.gridDashType,this.gridThickness));if("bottom"===this._position||"top"===this._position)for(d=0;d<this._labels.length;d++)this._labels[d].position<this.viewportMinimum||this._labels[d].position>this.viewportMaximum||(a.beginPath(),c=this.getPixelCoordinatesOnAxis(this._labels[d].position),c=1===a.lineWidth%2?(c.x<<0)+0.5:c.x<<0,a.moveTo(c,b.y1<<0),a.lineTo(c,
|
||||
b.y2<<0),a.stroke());else if("left"===this._position||"right"===this._position)for(var d=0;d<this._labels.length;d++)this._labels[d].position<this.viewportMinimum||this._labels[d].position>this.viewportMaximum||(a.beginPath(),c=this.getPixelCoordinatesOnAxis(this._labels[d].position),c=1===a.lineWidth%2?(c.y<<0)+0.5:c.y<<0,a.moveTo(b.x1<<0,c),a.lineTo(b.x2<<0,c),a.stroke());a.restore()}};B.prototype.renderAxisLine=function(){var a=this.chart.ctx;a.save();if("bottom"===this._position||"top"===this._position){if(this.lineThickness){a.lineWidth=
|
||||
this.lineThickness;a.strokeStyle=this.lineColor?this.lineColor:"black";a.setLineDash&&a.setLineDash(F(this.lineDashType,this.lineThickness));var c=1===this.lineThickness%2?(this.lineCoordinates.y1<<0)+0.5:this.lineCoordinates.y1<<0;a.beginPath();a.moveTo(this.lineCoordinates.x1,c);a.lineTo(this.lineCoordinates.x2,c);a.stroke()}}else"left"!==this._position&&"right"!==this._position||!this.lineThickness||(a.lineWidth=this.lineThickness,a.strokeStyle=this.lineColor,a.setLineDash&&a.setLineDash(F(this.lineDashType,
|
||||
this.lineThickness)),c=1===this.lineThickness%2?(this.lineCoordinates.x1<<0)+0.5:this.lineCoordinates.x1<<0,a.beginPath(),a.moveTo(c,this.lineCoordinates.y1),a.lineTo(c,this.lineCoordinates.y2),a.stroke());a.restore()};B.prototype.getPixelCoordinatesOnAxis=function(a){var c={};if("bottom"===this._position||"top"===this._position)c.x=this.convertValueToPixel(a),c.y=this.lineCoordinates.y1;if("left"===this._position||"right"===this._position)c.y=this.convertValueToPixel(a),c.x=this.lineCoordinates.x2;
|
||||
return c};B.prototype.convertPixelToValue=function(a){if("undefined"===typeof a)return null;var c=0,c=0,c="number"===typeof a?a:"left"===this._position||"right"===this._position?a.y:a.x;return c=this.logarithmic?Math.pow(this.logarithmBase,(c-this.conversionParameters.reference)/this.conversionParameters.pixelPerUnit)*this.viewportMinimum:this.conversionParameters.minimum+(c-this.conversionParameters.reference)/this.conversionParameters.pixelPerUnit};B.prototype.convertValueToPixel=function(a){return this.logarithmic?
|
||||
this.conversionParameters.reference+this.conversionParameters.pixelPerUnit*Math.log(a/this.conversionParameters.minimum)/this.conversionParameters.lnLogarithmBase+0.5<<0:this.conversionParameters.reference+this.conversionParameters.pixelPerUnit*(a-this.conversionParameters.minimum)+0.5<<0};B.prototype.setViewPortRange=function(a,c){this.sessionVariables.newViewportMinimum=this.viewportMinimum=Math.min(a,c);this.sessionVariables.newViewportMaximum=this.viewportMaximum=Math.max(a,c)};B.prototype.getXValueAt=
|
||||
function(a){if(!a)return null;var c=null;"left"===this._position?c=this.convertPixelToValue(a.y):"bottom"===this._position&&(c=this.convertPixelToValue(a.x));return c};B.prototype.calculateValueToPixelConversionParameters=function(a){a={pixelPerUnit:null,minimum:null,reference:null};var c=this.lineCoordinates.width,b=this.lineCoordinates.height;a.minimum=this.viewportMinimum;if("bottom"===this._position||"top"===this._position)this.logarithmic?(a.lnLogarithmBase=Math.log(this.logarithmBase),a.pixelPerUnit=
|
||||
(this.reversed?-1:1)*c*a.lnLogarithmBase/Math.log(Math.abs(this.range))):a.pixelPerUnit=(this.reversed?-1:1)*c/Math.abs(this.range),a.reference=this.reversed?this.lineCoordinates.x2:this.lineCoordinates.x1;if("left"===this._position||"right"===this._position)this.logarithmic?(a.lnLogarithmBase=Math.log(this.logarithmBase),a.pixelPerUnit=(this.reversed?1:-1)*b*a.lnLogarithmBase/Math.log(Math.abs(this.range))):a.pixelPerUnit=(this.reversed?1:-1)*b/Math.abs(this.range),a.reference=this.reversed?this.lineCoordinates.y1:
|
||||
this.lineCoordinates.y2;this.conversionParameters=a};B.prototype.calculateAxisParameters=function(){if(this.logarithmic)this.calculateLogarithamicAxisParameters();else{var a=this.chart.layoutManager.getFreeSpace(),c=!1,b=!1;"bottom"===this._position||"top"===this._position?(this.maxWidth=a.width,this.maxHeight=a.height):(this.maxWidth=a.height,this.maxHeight=a.width);var a="axisX"===this.type?"xySwapped"===this.chart.plotInfo.axisPlacement?62:70:"xySwapped"===this.chart.plotInfo.axisPlacement?50:
|
||||
40,d=4;"axisX"===this.type&&(d=600>this.maxWidth?8:6);var a=Math.max(d,Math.floor(this.maxWidth/a)),f,g,l,d=0;!y(this.options.viewportMinimum)&&(!y(this.options.viewportMaximum)&&this.options.viewportMinimum>=this.options.viewportMaximum)&&(this.viewportMinimum=this.viewportMaximum=null);if(y(this.options.viewportMinimum)&&!y(this.sessionVariables.newViewportMinimum)&&!isNaN(this.sessionVariables.newViewportMinimum))this.viewportMinimum=this.sessionVariables.newViewportMinimum;else if(null===this.viewportMinimum||
|
||||
isNaN(this.viewportMinimum))this.viewportMinimum=this.minimum;if(y(this.options.viewportMaximum)&&!y(this.sessionVariables.newViewportMaximum)&&!isNaN(this.sessionVariables.newViewportMaximum))this.viewportMaximum=this.sessionVariables.newViewportMaximum;else if(null===this.viewportMaximum||isNaN(this.viewportMaximum))this.viewportMaximum=this.maximum;if("axisX"===this.type){if(this.dataSeries&&0<this.dataSeries.length)for(f=0;f<this.dataSeries.length;f++)"dateTime"===this.dataSeries[f].xValueType&&
|
||||
(b=!0);f=null!==this.viewportMinimum?this.viewportMinimum:this.dataInfo.viewPortMin;g=null!==this.viewportMaximum?this.viewportMaximum:this.dataInfo.viewPortMax;0===g-f&&(d="undefined"===typeof this.options.interval?0.4:this.options.interval,g+=d,f-=d);Infinity!==this.dataInfo.minDiff?l=this.dataInfo.minDiff:1<g-f?l=0.5*Math.abs(g-f):(l=1,b&&(c=!0))}else"axisY"===this.type&&(f=null!==this.viewportMinimum?this.viewportMinimum:this.dataInfo.viewPortMin,g=null!==this.viewportMaximum?this.viewportMaximum:
|
||||
this.dataInfo.viewPortMax,isFinite(f)||isFinite(g)?isFinite(f)?isFinite(g)||(g=f):f=g:(g="undefined"===typeof this.options.interval?-Infinity:this.options.interval,f="undefined"!==typeof this.options.interval||isFinite(this.dataInfo.minDiff)?0:Infinity),0===f&&0===g?(g+=9,f=0):0===g-f?(d=Math.min(Math.abs(0.01*Math.abs(g)),5),g+=d,f-=d):f>g?(d=Math.min(Math.abs(0.01*Math.abs(g-f)),5),0<=g?f=g-d:g=isFinite(f)?f+d:0):(d=Math.min(Math.abs(0.01*Math.abs(g-f)),0.05),0!==g&&(g+=d),0!==f&&(f-=d)),l=Infinity!==
|
||||
this.dataInfo.minDiff?this.dataInfo.minDiff:1<g-f?0.5*Math.abs(g-f):1,this.includeZero&&(null===this.viewportMinimum||isNaN(this.viewportMinimum))&&0<f&&(f=0),this.includeZero&&(null===this.viewportMaximum||isNaN(this.viewportMaximum))&&0>g&&(g=0));d=(isNaN(this.viewportMaximum)||null===this.viewportMaximum?g:this.viewportMaximum)-(isNaN(this.viewportMinimum)||null===this.viewportMinimum?f:this.viewportMinimum);if("axisX"===this.type&&b){this.intervalType||(d/1<=a?(this.interval=1,this.intervalType=
|
||||
"millisecond"):d/2<=a?(this.interval=2,this.intervalType="millisecond"):d/5<=a?(this.interval=5,this.intervalType="millisecond"):d/10<=a?(this.interval=10,this.intervalType="millisecond"):d/20<=a?(this.interval=20,this.intervalType="millisecond"):d/50<=a?(this.interval=50,this.intervalType="millisecond"):d/100<=a?(this.interval=100,this.intervalType="millisecond"):d/200<=a?(this.interval=200,this.intervalType="millisecond"):d/250<=a?(this.interval=250,this.intervalType="millisecond"):d/300<=a?(this.interval=
|
||||
300,this.intervalType="millisecond"):d/400<=a?(this.interval=400,this.intervalType="millisecond"):d/500<=a?(this.interval=500,this.intervalType="millisecond"):d/(1*G.secondDuration)<=a?(this.interval=1,this.intervalType="second"):d/(2*G.secondDuration)<=a?(this.interval=2,this.intervalType="second"):d/(5*G.secondDuration)<=a?(this.interval=5,this.intervalType="second"):d/(10*G.secondDuration)<=a?(this.interval=10,this.intervalType="second"):d/(15*G.secondDuration)<=a?(this.interval=15,this.intervalType=
|
||||
"second"):d/(20*G.secondDuration)<=a?(this.interval=20,this.intervalType="second"):d/(30*G.secondDuration)<=a?(this.interval=30,this.intervalType="second"):d/(1*G.minuteDuration)<=a?(this.interval=1,this.intervalType="minute"):d/(2*G.minuteDuration)<=a?(this.interval=2,this.intervalType="minute"):d/(5*G.minuteDuration)<=a?(this.interval=5,this.intervalType="minute"):d/(10*G.minuteDuration)<=a?(this.interval=10,this.intervalType="minute"):d/(15*G.minuteDuration)<=a?(this.interval=15,this.intervalType=
|
||||
"minute"):d/(20*G.minuteDuration)<=a?(this.interval=20,this.intervalType="minute"):d/(30*G.minuteDuration)<=a?(this.interval=30,this.intervalType="minute"):d/(1*G.hourDuration)<=a?(this.interval=1,this.intervalType="hour"):d/(2*G.hourDuration)<=a?(this.interval=2,this.intervalType="hour"):d/(3*G.hourDuration)<=a?(this.interval=3,this.intervalType="hour"):d/(6*G.hourDuration)<=a?(this.interval=6,this.intervalType="hour"):d/(1*G.dayDuration)<=a?(this.interval=1,this.intervalType="day"):d/(2*G.dayDuration)<=
|
||||
a?(this.interval=2,this.intervalType="day"):d/(4*G.dayDuration)<=a?(this.interval=4,this.intervalType="day"):d/(1*G.weekDuration)<=a?(this.interval=1,this.intervalType="week"):d/(2*G.weekDuration)<=a?(this.interval=2,this.intervalType="week"):d/(3*G.weekDuration)<=a?(this.interval=3,this.intervalType="week"):d/(1*G.monthDuration)<=a?(this.interval=1,this.intervalType="month"):d/(2*G.monthDuration)<=a?(this.interval=2,this.intervalType="month"):d/(3*G.monthDuration)<=a?(this.interval=3,this.intervalType=
|
||||
"month"):d/(6*G.monthDuration)<=a?(this.interval=6,this.intervalType="month"):(this.interval=d/(1*G.yearDuration)<=a?1:d/(2*G.yearDuration)<=a?2:d/(4*G.yearDuration)<=a?4:Math.floor(B.getNiceNumber(d/(a-1),!0)/G.yearDuration),this.intervalType="year"));if(null===this.viewportMinimum||isNaN(this.viewportMinimum))this.viewportMinimum=f-l/2;if(null===this.viewportMaximum||isNaN(this.viewportMaximum))this.viewportMaximum=g+l/2;c?this.autoValueFormatString="MMM DD YYYY HH:mm":"year"===this.intervalType?
|
||||
this.autoValueFormatString="YYYY":"month"===this.intervalType?this.autoValueFormatString="MMM YYYY":"week"===this.intervalType?this.autoValueFormatString="MMM DD YYYY":"day"===this.intervalType?this.autoValueFormatString="MMM DD YYYY":"hour"===this.intervalType?this.autoValueFormatString="hh:mm TT":"minute"===this.intervalType?this.autoValueFormatString="hh:mm TT":"second"===this.intervalType?this.autoValueFormatString="hh:mm:ss TT":"millisecond"===this.intervalType&&(this.autoValueFormatString="fff'ms'");
|
||||
this.valueFormatString||(this.valueFormatString=this.autoValueFormatString)}else{this.intervalType="number";d=B.getNiceNumber(d,!1);this.interval=this.options&&0<this.options.interval?this.options.interval:B.getNiceNumber(d/(a-1),!0);if(null===this.viewportMinimum||isNaN(this.viewportMinimum))this.viewportMinimum="axisX"===this.type?f-l/2:Math.floor(f/this.interval)*this.interval;if(null===this.viewportMaximum||isNaN(this.viewportMaximum))this.viewportMaximum="axisX"===this.type?g+l/2:Math.ceil(g/
|
||||
this.interval)*this.interval;0===this.viewportMaximum&&0===this.viewportMinimum&&(0===this.options.viewportMinimum?this.viewportMaximum+=10:0===this.options.viewportMaximum&&(this.viewportMinimum-=10),this.options&&"undefined"===typeof this.options.interval&&(this.interval=B.getNiceNumber((this.viewportMaximum-this.viewportMinimum)/(a-1),!0)))}if(null===this.minimum||null===this.maximum)if("axisX"===this.type?(f=null!==this.minimum?this.minimum:this.dataInfo.min,g=null!==this.maximum?this.maximum:
|
||||
this.dataInfo.max,0===g-f&&(d="undefined"===typeof this.options.interval?0.4:this.options.interval,g+=d,f-=d),l=Infinity!==this.dataInfo.minDiff?this.dataInfo.minDiff:1<g-f?0.5*Math.abs(g-f):1):"axisY"===this.type&&(f=null!==this.minimum?this.minimum:this.dataInfo.min,g=null!==this.maximum?this.maximum:this.dataInfo.max,isFinite(f)||isFinite(g)?0===f&&0===g?(g+=9,f=0):0===g-f?(d=Math.min(Math.abs(0.01*Math.abs(g)),5),g+=d,f-=d):f>g?(d=Math.min(Math.abs(0.01*Math.abs(g-f)),5),0<=g?f=g-d:g=isFinite(f)?
|
||||
f+d:0):(d=Math.min(Math.abs(0.01*Math.abs(g-f)),0.05),0!==g&&(g+=d),0!==f&&(f-=d)):(g="undefined"===typeof this.options.interval?-Infinity:this.options.interval,f="undefined"!==typeof this.options.interval||isFinite(this.dataInfo.minDiff)?0:Infinity),l=Infinity!==this.dataInfo.minDiff?this.dataInfo.minDiff:1<g-f?0.5*Math.abs(g-f):1,this.includeZero&&(null===this.minimum||isNaN(this.minimum))&&0<f&&(f=0),this.includeZero&&(null===this.maximum||isNaN(this.maximum))&&0>g&&(g=0)),"axisX"===this.type&&
|
||||
b){if(null===this.minimum||isNaN(this.minimum))this.minimum=f-l/2;if(null===this.maximum||isNaN(this.maximum))this.maximum=g+l/2}else this.intervalType="number",null===this.minimum&&(this.minimum="axisX"===this.type?f-l/2:Math.floor(f/this.interval)*this.interval,this.minimum=Math.min(this.minimum,null===this.sessionVariables.viewportMinimum||isNaN(this.sessionVariables.viewportMinimum)?Infinity:this.sessionVariables.viewportMinimum)),null===this.maximum&&(this.maximum="axisX"===this.type?g+l/2:Math.ceil(g/
|
||||
this.interval)*this.interval,this.maximum=Math.max(this.maximum,null===this.sessionVariables.viewportMaximum||isNaN(this.sessionVariables.viewportMaximum)?-Infinity:this.sessionVariables.viewportMaximum)),0===this.maximum&&0===this.minimum&&(0===this.options.minimum?this.maximum+=10:0===this.options.maximum&&(this.minimum-=10));y(this.sessionVariables.newViewportMinimum)&&(this.viewportMinimum=Math.max(this.viewportMinimum,this.minimum));y(this.sessionVariables.newViewportMaximum)&&(this.viewportMaximum=
|
||||
Math.min(this.viewportMaximum,this.maximum));this.range=this.viewportMaximum-this.viewportMinimum;this.intervalStartPosition="axisX"===this.type&&b?this.getLabelStartPoint(new Date(this.viewportMinimum),this.intervalType,this.interval):Math.floor((this.viewportMinimum+0.2*this.interval)/this.interval)*this.interval;if(!this.valueFormatString&&(this.valueFormatString="#,##0.##",1>this.range)){c=Math.floor(Math.abs(Math.log(this.range)/Math.LN10))+2;if(isNaN(c)||!isFinite(c))c=2;if(2<c)for(b=0;b<c-
|
||||
2;b++)this.valueFormatString+="#"}}};B.prototype.calculateLogarithamicAxisParameters=function(){var a=this.chart.layoutManager.getFreeSpace(),c=Math.log(this.logarithmBase),b;"bottom"===this._position||"top"===this._position?(this.maxWidth=a.width,this.maxHeight=a.height):(this.maxWidth=a.height,this.maxHeight=a.width);var a="axisX"===this.type?500>this.maxWidth?7:Math.max(7,Math.floor(this.maxWidth/100)):Math.max(Math.floor(this.maxWidth/50),3),d,f,g,l;l=1;if(null===this.viewportMinimum||isNaN(this.viewportMinimum))this.viewportMinimum=
|
||||
this.minimum;if(null===this.viewportMaximum||isNaN(this.viewportMaximum))this.viewportMaximum=this.maximum;"axisX"===this.type?(d=null!==this.viewportMinimum?this.viewportMinimum:this.dataInfo.viewPortMin,f=null!==this.viewportMaximum?this.viewportMaximum:this.dataInfo.viewPortMax,1===f/d&&(l=Math.pow(this.logarithmBase,"undefined"===typeof this.options.interval?0.4:this.options.interval),f*=l,d/=l),g=Infinity!==this.dataInfo.minDiff?this.dataInfo.minDiff:f/d>this.logarithmBase?f/d*Math.pow(this.logarithmBase,
|
||||
0.5):this.logarithmBase):"axisY"===this.type&&(d=null!==this.viewportMinimum?this.viewportMinimum:this.dataInfo.viewPortMin,f=null!==this.viewportMaximum?this.viewportMaximum:this.dataInfo.viewPortMax,0>=d&&!isFinite(f)?(f="undefined"===typeof this.options.interval?0:this.options.interval,d=1):0>=d?d=f:isFinite(f)||(f=d),1===d&&1===f?(f*=this.logarithmBase-1/this.logarithmBase,d=1):1===f/d?(l=Math.min(f*Math.pow(this.logarithmBase,0.01),Math.pow(this.logarithmBase,5)),f*=l,d/=l):d>f?(l=Math.min(d/
|
||||
f*Math.pow(this.logarithmBase,0.01),Math.pow(this.logarithmBase,5)),1<=f?d=f/l:f=d*l):(l=Math.min(f/d*Math.pow(this.logarithmBase,0.01),Math.pow(this.logarithmBase,0.04)),1!==f&&(f*=l),1!==d&&(d/=l)),g=Infinity!==this.dataInfo.minDiff?this.dataInfo.minDiff:f/d>this.logarithmBase?f/d*Math.pow(this.logarithmBase,0.5):this.logarithmBase,this.includeZero&&(null===this.viewportMinimum||isNaN(this.viewportMinimum))&&1<d&&(d=1),this.includeZero&&(null===this.viewportMaximum||isNaN(this.viewportMaximum))&&
|
||||
1>f&&(f=1));l=(isNaN(this.viewportMaximum)||null===this.viewportMaximum?f:this.viewportMaximum)/(isNaN(this.viewportMinimum)||null===this.viewportMinimum?d:this.viewportMinimum);linearRange=(isNaN(this.viewportMaximum)||null===this.viewportMaximum?f:this.viewportMaximum)-(isNaN(this.viewportMinimum)||null===this.viewportMinimum?d:this.viewportMinimum);this.intervalType="number";l=Math.pow(this.logarithmBase,B.getNiceNumber(Math.abs(Math.log(l)/c),!1));this.options&&0<this.options.interval?this.interval=
|
||||
this.options.interval:(this.interval=B.getNiceExponent(Math.log(l)/c/(a-1),!0),b=B.getNiceNumber(linearRange/(a-1),!0));if(null===this.viewportMinimum||isNaN(this.viewportMinimum))this.viewportMinimum="axisX"===this.type?d/Math.sqrt(g):Math.pow(this.logarithmBase,this.interval*Math.floor(Math.log(d)/c/this.interval));if(null===this.viewportMaximum||isNaN(this.viewportMaximum))this.viewportMaximum="axisX"===this.type?f*Math.sqrt(g):Math.pow(this.logarithmBase,this.interval*Math.ceil(Math.log(f)/c/
|
||||
this.interval));1===this.viewportMaximum&&1===this.viewportMinimum&&(1===this.options.viewportMinimum?this.viewportMaximum*=this.logarithmBase-1/this.logarithmBase:1===this.options.viewportMaximum&&(this.viewportMinimum/=this.logarithmBase-1/this.logarithmBase),this.options&&"undefined"===typeof this.options.interval&&(this.interval=B.getNiceExponent(Math.ceil(Math.log(l)/c)/(a-1)),b=B.getNiceNumber((this.viewportMaximum-this.viewportMinimum)/(a-1),!0)));if(null===this.minimum||null===this.maximum)"axisX"===
|
||||
this.type?(d=null!==this.minimum?this.minimum:this.dataInfo.min,f=null!==this.maximum?this.maximum:this.dataInfo.max,1===f/d&&(l=Math.pow(this.logarithmBase,"undefined"===typeof this.options.interval?0.4:this.options.interval),f*=l,d/=l),g=Infinity!==this.dataInfo.minDiff?this.dataInfo.minDiff:f/d>this.logarithmBase?f/d*Math.pow(this.logarithmBase,0.5):this.logarithmBase):"axisY"===this.type&&(d=null!==this.minimum?this.minimum:this.dataInfo.min,f=null!==this.maximum?this.maximum:this.dataInfo.max,
|
||||
isFinite(d)||isFinite(f)?1===d&&1===f?(f*=this.logarithmBase,d/=this.logarithmBase):1===f/d?(l=Math.pow(this.logarithmBase,this.interval),f*=l,d/=l):d>f?(l=Math.min(0.01*(d/f),5),1<=f?d=f/l:f=d*l):(l=Math.min(f/d*Math.pow(this.logarithmBase,0.01),Math.pow(this.logarithmBase,0.04)),1!==f&&(f*=l),1!==d&&(d/=l)):(f="undefined"===typeof this.options.interval?0:this.options.interval,d=1),g=Infinity!==this.dataInfo.minDiff?this.dataInfo.minDiff:f/d>this.logarithmBase?f/d*Math.pow(this.logarithmBase,0.5):
|
||||
this.logarithmBase,this.includeZero&&(null===this.minimum||isNaN(this.minimum))&&1<d&&(d=1),this.includeZero&&(null===this.maximum||isNaN(this.maximum))&&1>f&&(f=1)),this.intervalType="number",null===this.minimum&&(this.minimum="axisX"===this.type?d/Math.sqrt(g):Math.pow(this.logarithmBase,this.interval*Math.floor(Math.log(d)/c/this.interval)),this.minimum=Math.min(this.minimum,null===this.sessionVariables.viewportMinimum||isNaN(this.sessionVariables.viewportMinimum)?"undefined"===typeof this.sessionVariables.newViewportMinimum?
|
||||
Infinity:this.sessionVariables.newViewportMinimum:this.sessionVariables.viewportMinimum)),null===this.maximum&&(this.maximum="axisX"===this.type?f*Math.sqrt(g):Math.pow(this.logarithmBase,this.interval*Math.ceil(Math.log(f)/c/this.interval)),this.maximum=Math.max(this.maximum,null===this.sessionVariables.viewportMaximum||isNaN(this.sessionVariables.viewportMaximum)?"undefined"===typeof this.sessionVariables.newViewportMaximum?0:this.sessionVariables.newViewportMaximum:this.sessionVariables.viewportMaximum)),
|
||||
1===this.maximum&&1===this.minimum&&(1===this.options.minimum?this.maximum*=this.logarithmBase-1/this.logarithmBase:1===this.options.maximum&&(this.minimum/=this.logarithmBase-1/this.logarithmBase));this.viewportMinimum=Math.max(this.viewportMinimum,this.minimum);this.viewportMaximum=Math.min(this.viewportMaximum,this.maximum);this.viewportMinimum>this.viewportMaximum&&(!this.options.viewportMinimum&&!this.options.minimum||this.options.viewportMaximum||this.options.maximum?this.options.viewportMinimum||
|
||||
this.options.minimum||!this.options.viewportMaximum&&!this.options.maximum||(this.viewportMinimum=this.minimum=(this.options.viewportMaximum||this.options.maximum)/Math.pow(this.logarithmBase,2*Math.ceil(this.interval))):this.viewportMaximum=this.maximum=this.options.viewportMinimum||this.options.minimum);d=Math.pow(this.logarithmBase,Math.floor(Math.log(this.viewportMinimum)/(c*this.interval)+0.2)*this.interval);this.range=this.viewportMaximum/this.viewportMinimum;this.noTicks=a;if(!this.options.interval&&
|
||||
this.range<Math.pow(this.logarithmBase,8>this.viewportMaximum||3>a?2:3)){for(c=Math.floor(this.viewportMinimum/b+0.5)*b;c<this.viewportMinimum;)c+=b;this.equidistantInterval=!1;this.intervalStartPosition=c;this.interval=b}else this.options.interval||(b=Math.ceil(this.interval),this.range>this.interval&&(this.interval=b,d=Math.pow(this.logarithmBase,Math.floor(Math.log(this.viewportMinimum)/(c*this.interval)+0.2)*this.interval))),this.equidistantInterval=!0,this.intervalStartPosition=d;if(!this.valueFormatString&&
|
||||
(this.valueFormatString="#,##0.##",1>this.viewportMinimum)){c=Math.floor(Math.abs(Math.log(this.viewportMinimum)/Math.LN10))+2;if(isNaN(c)||!isFinite(c))c=2;if(2<c)for(b=0;b<c-2;b++)this.valueFormatString+="#"}};B.getNiceExponent=function(a,c){var b=Math.floor(Math.log(a)/Math.LN10),d=a/Math.pow(10,b),d=0>b?1>=d?1:5>=d?5:10:Math.max(Math.floor(d),1);return Number((d*Math.pow(10,b)).toFixed(20))};B.getNiceNumber=function(a,c){var b=Math.floor(Math.log(a)/Math.LN10),d=a/Math.pow(10,b);return Number(((c?
|
||||
1.5>d?1:3>d?2:7>d?5:10:1>=d?1:2>=d?2:5>=d?5:10)*Math.pow(10,b)).toFixed(20))};B.prototype.getLabelStartPoint=function(){var a=G[this.intervalType+"Duration"]*this.interval,a=new Date(Math.floor(this.viewportMinimum/a)*a);if("millisecond"!==this.intervalType)if("second"===this.intervalType)0<a.getMilliseconds()&&(a.setSeconds(a.getSeconds()+1),a.setMilliseconds(0));else if("minute"===this.intervalType){if(0<a.getSeconds()||0<a.getMilliseconds())a.setMinutes(a.getMinutes()+1),a.setSeconds(0),a.setMilliseconds(0)}else if("hour"===
|
||||
this.intervalType){if(0<a.getMinutes()||0<a.getSeconds()||0<a.getMilliseconds())a.setHours(a.getHours()+1),a.setMinutes(0),a.setSeconds(0),a.setMilliseconds(0)}else if("day"===this.intervalType){if(0<a.getHours()||0<a.getMinutes()||0<a.getSeconds()||0<a.getMilliseconds())a.setDate(a.getDate()+1),a.setHours(0),a.setMinutes(0),a.setSeconds(0),a.setMilliseconds(0)}else if("week"===this.intervalType){if(0<a.getDay()||0<a.getHours()||0<a.getMinutes()||0<a.getSeconds()||0<a.getMilliseconds())a.setDate(a.getDate()+
|
||||
(7-a.getDay())),a.setHours(0),a.setMinutes(0),a.setSeconds(0),a.setMilliseconds(0)}else if("month"===this.intervalType){if(1<a.getDate()||0<a.getHours()||0<a.getMinutes()||0<a.getSeconds()||0<a.getMilliseconds())a.setMonth(a.getMonth()+1),a.setDate(1),a.setHours(0),a.setMinutes(0),a.setSeconds(0),a.setMilliseconds(0)}else"year"===this.intervalType&&(0<a.getMonth()||1<a.getDate()||0<a.getHours()||0<a.getMinutes()||0<a.getSeconds()||0<a.getMilliseconds())&&(a.setFullYear(a.getFullYear()+1),a.setMonth(0),
|
||||
a.setDate(1),a.setHours(0),a.setMinutes(0),a.setSeconds(0),a.setMilliseconds(0));return a};T(pa,L);pa.prototype.createUserOptions=function(a){if("undefined"!==typeof a||this.options._isPlaceholder){var c=0;this.parent.options._isPlaceholder&&this.parent.createUserOptions();this.options._isPlaceholder||(sa(this.parent.stripLines),c=this.parent.options.stripLines.indexOf(this.options));this.options="undefined"===typeof a?{}:a;this.parent.options.stripLines[c]=this.options}};pa.prototype.render=function(){this.ctx.save();
|
||||
var a=this.parent.getPixelCoordinatesOnAxis(this.value),c=Math.abs("pixel"===this._thicknessType?this.thickness:this.parent.conversionParameters.pixelPerUnit*this.thickness);if(0<c){var b=null===this.opacity?1:this.opacity;this.ctx.strokeStyle=this.color;this.ctx.beginPath();var d=this.ctx.globalAlpha;this.ctx.globalAlpha=b;D(this.id);var f,g,l,k;this.ctx.lineWidth=c;this.ctx.setLineDash&&this.ctx.setLineDash(F(this.lineDashType,c));if("bottom"===this.parent._position||"top"===this.parent._position)f=
|
||||
g=1===this.ctx.lineWidth%2?(a.x<<0)+0.5:a.x<<0,l=this.chart.plotArea.y1,k=this.chart.plotArea.y2,this.bounds={x1:f-c/2,y1:l,x2:g+c/2,y2:k};else if("left"===this.parent._position||"right"===this.parent._position)l=k=1===this.ctx.lineWidth%2?(a.y<<0)+0.5:a.y<<0,f=this.chart.plotArea.x1,g=this.chart.plotArea.x2,this.bounds={x1:f,y1:l-c/2,x2:g,y2:k+c/2};this.ctx.moveTo(f,l);this.ctx.lineTo(g,k);this.ctx.stroke();this.ctx.globalAlpha=d}this.ctx.restore()};T(R,L);R.prototype._initialize=function(){if(this.enabled){this.container=
|
||||
document.createElement("div");this.container.setAttribute("class","canvasjs-chart-tooltip");this.container.style.position="absolute";this.container.style.height="auto";this.container.style.boxShadow="1px 1px 2px 2px rgba(0,0,0,0.1)";this.container.style.zIndex="1000";this.container.style.display="none";var a;a='<div style=" width: auto;height: auto;min-width: 50px;';a+="line-height: auto;";a+="margin: 0px 0px 0px 0px;";a+="padding: 5px;";a+="font-family: Calibri, Arial, Georgia, serif;";a+="font-weight: normal;";
|
||||
a+="font-style: "+(t?"italic;":"normal;");a+="font-size: 14px;";a+="color: #000000;";a+="text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.1);";a+="text-align: left;";a+="border: 2px solid gray;";a+=t?"background: rgba(255,255,255,.9);":"background: rgb(255,255,255);";a+="text-indent: 0px;";a+="white-space: nowrap;";a+="border-radius: 5px;";a+="-moz-user-select:none;";a+="-khtml-user-select: none;";a+="-webkit-user-select: none;";a+="-ms-user-select: none;";a+="user-select: none;";t||(a+="filter: alpha(opacity = 90);",
|
||||
a+="filter: progid:DXImageTransform.Microsoft.Shadow(Strength=3, Direction=135, Color='#666666');");a+='} "> Sample Tooltip</div>';this.container.innerHTML=a;this.contentDiv=this.container.firstChild;this.container.style.borderRadius=this.contentDiv.style.borderRadius;this.chart._canvasJSContainer.appendChild(this.container)}};R.prototype.mouseMoveHandler=function(a,c){this._lastUpdated&&40>(new Date).getTime()-this._lastUpdated||(this._lastUpdated=(new Date).getTime(),this._updateToolTip(a,c))};
|
||||
R.prototype._updateToolTip=function(a,c,b){b="undefined"===typeof b?!0:b;this.container||this._initialize();this.enabled||this.hide();if(!this.chart.disableToolTip){if("undefined"===typeof a||"undefined"===typeof c){if(isNaN(this._prevX)||isNaN(this._prevY))return;a=this._prevX;c=this._prevY}else this._prevX=a,this._prevY=c;var d=null,f=null,g=[],l=0;if(this.shared&&this.enabled&&"none"!==this.chart.plotInfo.axisPlacement){if("xySwapped"===this.chart.plotInfo.axisPlacement){f=[];if(this.chart.axisX)for(var k=
|
||||
0;k<this.chart.axisX.length;k++){for(var l=this.chart.axisX[k].convertPixelToValue({y:c}),h=null,d=0;d<this.chart.axisX[k].dataSeries.length;d++)(h=this.chart.axisX[k].dataSeries[d].getDataPointAtX(l,b))&&0<=h.index&&(h.dataSeries=this.chart.axisX[k].dataSeries[d],null!==h.dataPoint.y&&f.push(h));h=null}if(this.chart.axisX2)for(k=0;k<this.chart.axisX2.length;k++){l=this.chart.axisX2[k].convertPixelToValue({y:c});h=null;for(d=0;d<this.chart.axisX2[k].dataSeries.length;d++)(h=this.chart.axisX2[k].dataSeries[d].getDataPointAtX(l,
|
||||
b))&&0<=h.index&&(h.dataSeries=this.chart.axisX2[k].dataSeries[d],null!==h.dataPoint.y&&f.push(h));h=null}}else{f=[];if(this.chart.axisX)for(k=0;k<this.chart.axisX.length;k++)for(l=this.chart.axisX[k].convertPixelToValue({x:a}),h=null,d=0;d<this.chart.axisX[k].dataSeries.length;d++)(h=this.chart.axisX[k].dataSeries[d].getDataPointAtX(l,b))&&0<=h.index&&(h.dataSeries=this.chart.axisX[k].dataSeries[d],null!==h.dataPoint.y&&f.push(h));if(this.chart.axisX2)for(k=0;k<this.chart.axisX2.length;k++)for(l=
|
||||
this.chart.axisX2[k].convertPixelToValue({x:a}),h=null,d=0;d<this.chart.axisX2[k].dataSeries.length;d++)(h=this.chart.axisX2[k].dataSeries[d].getDataPointAtX(l,b))&&0<=h.index&&(h.dataSeries=this.chart.axisX2[k].dataSeries[d],null!==h.dataPoint.y&&f.push(h))}if(0===f.length)return;f.sort(function(a,b){return a.distance-b.distance});b=f[0];for(d=0;d<f.length;d++)f[d].dataPoint.x.valueOf()===b.dataPoint.x.valueOf()&&g.push(f[d]);f=null}else{if(h=this.chart.getDataPointAtXY(a,c,b))this.currentDataPointIndex=
|
||||
h.dataPointIndex,this.currentSeriesIndex=h.dataSeries.index;else if(t)if(h=Na(a,c,this.chart._eventManager.ghostCtx),0<h&&"undefined"!==typeof this.chart._eventManager.objectMap[h]){h=this.chart._eventManager.objectMap[h];if("legendItem"===h.objectType)return;this.currentSeriesIndex=h.dataSeriesIndex;this.currentDataPointIndex=0<=h.dataPointIndex?h.dataPointIndex:-1}else this.currentDataPointIndex=-1;else this.currentDataPointIndex=-1;if(0<=this.currentSeriesIndex){f=this.chart.data[this.currentSeriesIndex];
|
||||
h={};if(0<=this.currentDataPointIndex)d=f.dataPoints[this.currentDataPointIndex],h.dataSeries=f,h.dataPoint=d,h.index=this.currentDataPointIndex,h.distance=Math.abs(d.x-l);else{if(!this.enabled||"line"!==f.type&&"stepLine"!==f.type&&"spline"!==f.type&&"area"!==f.type&&"stepArea"!==f.type&&"splineArea"!==f.type&&"stackedArea"!==f.type&&"stackedArea100"!==f.type&&"rangeArea"!==f.type&&"rangeSplineArea"!==f.type&&"candlestick"!==f.type&&"ohlc"!==f.type)return;l=f.axisX.convertPixelToValue({x:a});h=f.getDataPointAtX(l,
|
||||
b);h.dataSeries=f;this.currentDataPointIndex=h.index;d=h.dataPoint}if(!y(h.dataPoint.y))if(h.dataSeries.axisY)if(0<h.dataPoint.y.length){for(d=b=0;d<h.dataPoint.y.length;d++)h.dataPoint.y[d]<h.dataSeries.axisY.viewportMinimum?b--:h.dataPoint.y[d]>h.dataSeries.axisY.viewportMaximum&&b++;b<h.dataPoint.y.length&&b>-h.dataPoint.y.length&&g.push(h)}else"column"===f.type||"bar"===f.type?0>h.dataPoint.y?0>h.dataSeries.axisY.viewportMinimum&&h.dataSeries.axisY.viewportMaximum>=h.dataPoint.y&&g.push(h):h.dataSeries.axisY.viewportMinimum<=
|
||||
h.dataPoint.y&&0<=h.dataSeries.axisY.viewportMaximum&&g.push(h):"bubble"===f.type?(b=this.chart._eventManager.objectMap[f.dataPointIds[h.index]].size/2,h.dataPoint.y>=h.dataSeries.axisY.viewportMinimum-b&&h.dataPoint.y<=h.dataSeries.axisY.viewportMaximum+b&&g.push(h)):(0<=h.dataSeries.type.indexOf("100")||"stackedColumn"===f.type||"stackedBar"===f.type||h.dataPoint.y>=h.dataSeries.axisY.viewportMinimum&&h.dataPoint.y<=h.dataSeries.axisY.viewportMaximum)&&g.push(h);else g.push(h)}}if(0<g.length&&(this.highlightObjects(g),
|
||||
this.enabled))if(b="",b=this.getToolTipInnerHTML({entries:g}),null!==b){this.contentDiv.innerHTML=b;this.contentDiv.innerHTML=b;b=!1;"none"===this.container.style.display&&(b=!0,this.container.style.display="block");try{this.contentDiv.style.background=this.backgroundColor?this.backgroundColor:t?"rgba(255,255,255,.9)":"rgb(255,255,255)",this.borderColor=this.contentDiv.style.borderRightColor=this.contentDiv.style.borderLeftColor=this.contentDiv.style.borderColor=this.options.borderColor?this.options.borderColor:
|
||||
g[0].dataPoint.color?g[0].dataPoint.color:g[0].dataSeries.color?g[0].dataSeries.color:g[0].dataSeries._colorSet[g[0].index%g[0].dataSeries._colorSet.length],this.contentDiv.style.borderWidth=this.borderThickness||0===this.borderThickness?this.borderThickness+"px":"2px",this.contentDiv.style.borderRadius=this.cornerRadius||0===this.cornerRadius?this.cornerRadius+"px":"5px",this.container.style.borderRadius=this.contentDiv.style.borderRadius,this.contentDiv.style.fontSize=this.fontSize||0===this.fontSize?
|
||||
this.fontSize+"px":"14px",this.contentDiv.style.color=this.fontColor?this.fontColor:"#000000",this.contentDiv.style.fontFamily=this.fontFamily?this.fontFamily:"Calibri, Arial, Georgia, serif;",this.contentDiv.style.fontWeight=this.fontWeight?this.fontWeight:"normal",this.contentDiv.style.fontStyle=this.fontStyle?this.fontStyle:t?"italic":"normal"}catch(m){}"pie"===g[0].dataSeries.type||"doughnut"===g[0].dataSeries.type||"funnel"===g[0].dataSeries.type||"bar"===g[0].dataSeries.type||"rangeBar"===g[0].dataSeries.type||
|
||||
"stackedBar"===g[0].dataSeries.type||"stackedBar100"===g[0].dataSeries.type?a=a-10-this.container.clientWidth:(a=g[0].dataSeries.axisX.convertValueToPixel(g[0].dataPoint.x)-this.container.clientWidth<<0,a-=10);0>a&&(a+=this.container.clientWidth+20);a+this.container.clientWidth>Math.max(this.chart.container.clientWidth,this.chart.width)&&(a=Math.max(0,Math.max(this.chart.container.clientWidth,this.chart.width)-this.container.clientWidth));a+="px";c=1!==g.length||this.shared||"line"!==g[0].dataSeries.type&&
|
||||
"stepLine"!==g[0].dataSeries.type&&"spline"!==g[0].dataSeries.type&&"area"!==g[0].dataSeries.type&&"stepArea"!==g[0].dataSeries.type&&"splineArea"!==g[0].dataSeries.type?"bar"===g[0].dataSeries.type||"rangeBar"===g[0].dataSeries.type||"stackedBar"===g[0].dataSeries.type||"stackedBar100"===g[0].dataSeries.type?g[0].dataSeries.axisX.convertValueToPixel(g[0].dataPoint.x):c:g[0].dataSeries.axisY.convertValueToPixel(g[0].dataPoint.y);c=-c+10;0<c+this.container.clientHeight+5&&(c-=c+this.container.clientHeight+
|
||||
5-0);this.container.style.left=a;this.container.style.bottom=c+"px";!this.animationEnabled||b?this.disableAnimation():this.enableAnimation()}else this.hide(!1)}};R.prototype.highlightObjects=function(a){var c=this.chart.overlaidCanvasCtx;this.chart.resetOverlayedCanvas();c.clearRect(0,0,this.chart.width,this.chart.height);c.save();var b=this.chart.plotArea,d=0;c.beginPath();c.rect(b.x1,b.y1,b.x2-b.x1,b.y2-b.y1);c.clip();for(b=0;b<a.length;b++){var f=a[b];if((f=this.chart._eventManager.objectMap[f.dataSeries.dataPointIds[f.index]])&&
|
||||
f.objectType&&"dataPoint"===f.objectType){var d=this.chart.data[f.dataSeriesIndex],g=d.dataPoints[f.dataPointIndex],l=f.dataPointIndex;!1===g.highlightEnabled||!0!==d.highlightEnabled&&!0!==g.highlightEnabled||("line"===d.type||"stepLine"===d.type||"spline"===d.type||"scatter"===d.type||"area"===d.type||"stepArea"===d.type||"splineArea"===d.type||"stackedArea"===d.type||"stackedArea100"===d.type||"rangeArea"===d.type||"rangeSplineArea"===d.type?(g=d.getMarkerProperties(l,f.x1,f.y1,this.chart.overlaidCanvasCtx),
|
||||
g.size=Math.max(1.5*g.size<<0,10),g.borderColor=g.borderColor||"#FFFFFF",g.borderThickness=g.borderThickness||Math.ceil(0.1*g.size),O.drawMarkers([g]),"undefined"!==typeof f.y2&&(g=d.getMarkerProperties(l,f.x1,f.y2,this.chart.overlaidCanvasCtx),g.size=Math.max(1.5*g.size<<0,10),g.borderColor=g.borderColor||"#FFFFFF",g.borderThickness=g.borderThickness||Math.ceil(0.1*g.size),O.drawMarkers([g]))):"bubble"===d.type?(g=d.getMarkerProperties(l,f.x1,f.y1,this.chart.overlaidCanvasCtx),g.size=f.size,g.color=
|
||||
"white",g.borderColor="white",c.globalAlpha=0.3,O.drawMarkers([g]),c.globalAlpha=1):"column"===d.type||"stackedColumn"===d.type||"stackedColumn100"===d.type||"bar"===d.type||"rangeBar"===d.type||"stackedBar"===d.type||"stackedBar100"===d.type||"rangeColumn"===d.type?N(c,f.x1,f.y1,f.x2,f.y2,"white",0,null,!1,!1,!1,!1,0.3):"pie"===d.type||"doughnut"===d.type?Ha(c,f.center,f.radius,"white",d.type,f.startAngle,f.endAngle,0.3,f.percentInnerRadius):"candlestick"===d.type?(c.globalAlpha=1,c.strokeStyle=
|
||||
f.color,c.lineWidth=2*f.borderThickness,d=0===c.lineWidth%2?0:0.5,c.beginPath(),c.moveTo(f.x3-d,Math.min(f.y2,f.y3)),c.lineTo(f.x3-d,Math.min(f.y1,f.y4)),c.stroke(),c.beginPath(),c.moveTo(f.x3-d,Math.max(f.y1,f.y4)),c.lineTo(f.x3-d,Math.max(f.y2,f.y3)),c.stroke(),N(c,f.x1,Math.min(f.y1,f.y4),f.x2,Math.max(f.y1,f.y4),"transparent",2*f.borderThickness,f.color,!1,!1,!1,!1),c.globalAlpha=1):"ohlc"===d.type&&(c.globalAlpha=1,c.strokeStyle=f.color,c.lineWidth=2*f.borderThickness,d=0===c.lineWidth%2?0:0.5,
|
||||
c.beginPath(),c.moveTo(f.x3-d,f.y2),c.lineTo(f.x3-d,f.y3),c.stroke(),c.beginPath(),c.moveTo(f.x3,f.y1),c.lineTo(f.x1,f.y1),c.stroke(),c.beginPath(),c.moveTo(f.x3,f.y4),c.lineTo(f.x2,f.y4),c.stroke(),c.globalAlpha=1))}}c.restore();c.globalAlpha=1;c.beginPath()};R.prototype.getToolTipInnerHTML=function(a){a=a.entries;for(var c=null,b=null,d=null,f=0,g="",l=!0,k=0;k<a.length;k++)if(a[k].dataSeries.toolTipContent||a[k].dataPoint.toolTipContent){l=!1;break}if(l&&(this.content&&"function"===typeof this.content||
|
||||
this.contentFormatter))a={chart:this.chart,toolTip:this.options,entries:a},c=this.contentFormatter?this.contentFormatter(a):this.content(a);else if(this.shared&&"none"!==this.chart.plotInfo.axisPlacement){for(var h=null,m="",k=0;k<a.length;k++)if(b=a[k].dataSeries,d=a[k].dataPoint,f=a[k].index,g="",0===k&&(l&&!this.content)&&(this.chart.axisX&&0<this.chart.axisX.length?m+="undefined"!==typeof this.chart.axisX[0].labels[d.x]?this.chart.axisX[0].labels[d.x]:"{x}":this.chart.axisX2&&0<this.chart.axisX2.length&&
|
||||
(m+="undefined"!==typeof this.chart.axisX2[0].labels[d.x]?this.chart.axisX2[0].labels[d.x]:"{x}"),m+="</br>",m=this.chart.replaceKeywordsWithValue(m,d,b,f)),null!==d.toolTipContent&&("undefined"!==typeof d.toolTipContent||null!==b.options.toolTipContent)){if("line"===b.type||"stepLine"===b.type||"spline"===b.type||"area"===b.type||"stepArea"===b.type||"splineArea"===b.type||"column"===b.type||"bar"===b.type||"scatter"===b.type||"stackedColumn"===b.type||"stackedColumn100"===b.type||"stackedBar"===
|
||||
b.type||"stackedBar100"===b.type||"stackedArea"===b.type||"stackedArea100"===b.type)this.chart.axisX&&1<this.chart.axisX.length&&(g+=h!=b.axisXIndex?b.axisX.title?b.axisX.title+"<br/>":"X:{axisXIndex}<br/>":""),g+=d.toolTipContent?d.toolTipContent:b.toolTipContent?b.toolTipContent:this.content&&"function"!==typeof this.content?this.content:"<span style='\""+(this.options.fontColor?"":"'color:{color};'")+"\"'>{name}:</span> {y}",h=b.axisXIndex;else if("bubble"===b.type)this.chart.axisX&&
|
||||
1<this.chart.axisX.length&&(g+=h!=b.axisXIndex?b.axisX.title?b.axisX.title+"<br/>":"X:{axisXIndex}<br/>":""),g+=d.toolTipContent?d.toolTipContent:b.toolTipContent?b.toolTipContent:this.content&&"function"!==typeof this.content?this.content:"<span style='\""+(this.options.fontColor?"":"'color:{color};'")+"\"'>{name}:</span> {y}, {z}";else if("rangeColumn"===b.type||"rangeBar"===b.type||"rangeArea"===b.type||"rangeSplineArea"===b.type)this.chart.axisX&&1<this.chart.axisX.length&&
|
||||
(g+=h!=b.axisXIndex?b.axisX.title?b.axisX.title+"<br/>":"X:{axisXIndex}<br/>":""),g+=d.toolTipContent?d.toolTipContent:b.toolTipContent?b.toolTipContent:this.content&&"function"!==typeof this.content?this.content:"<span style='\""+(this.options.fontColor?"":"'color:{color};'")+"\"'>{name}:</span> {y[0]}, {y[1]}";else if("candlestick"===b.type||"ohlc"===b.type)this.chart.axisX&&1<this.chart.axisX.length&&(g+=h!=b.axisXIndex?b.axisX.title?b.axisX.title+"<br/>":"X:{axisXIndex}<br/>":
|
||||
""),g+=d.toolTipContent?d.toolTipContent:b.toolTipContent?b.toolTipContent:this.content&&"function"!==typeof this.content?this.content:"<span style='\""+(this.options.fontColor?"":"'color:{color};'")+"\"'>{name}:</span><br/>Open: {y[0]}<br/>High: {y[1]}<br/>Low: {y[2]}<br/>Close: {y[3]}";null===c&&(c="");!0===this.reversed?(c=this.chart.replaceKeywordsWithValue(g,d,b,f)+c,k<a.length-1&&(c="</br>"+c)):(c+=this.chart.replaceKeywordsWithValue(g,
|
||||
d,b,f),k<a.length-1&&(c+="</br>"))}null!==c&&(c=m+c)}else{b=a[0].dataSeries;d=a[0].dataPoint;f=a[0].index;if(null===d.toolTipContent||"undefined"===typeof d.toolTipContent&&null===b.options.toolTipContent)return null;if("line"===b.type||"stepLine"===b.type||"spline"===b.type||"area"===b.type||"stepArea"===b.type||"splineArea"===b.type||"column"===b.type||"bar"===b.type||"scatter"===b.type||"stackedColumn"===b.type||"stackedColumn100"===b.type||"stackedBar"===b.type||"stackedBar100"===b.type||"stackedArea"===
|
||||
b.type||"stackedArea100"===b.type)g=d.toolTipContent?d.toolTipContent:b.toolTipContent?b.toolTipContent:this.content&&"function"!==typeof this.content?this.content:"<span style='\""+(this.options.fontColor?"":"'color:{color};'")+"\"'>"+(d.label?"{label}":"{x}")+":</span> {y}";else if("bubble"===b.type)g=d.toolTipContent?d.toolTipContent:b.toolTipContent?b.toolTipContent:this.content&&"function"!==typeof this.content?this.content:"<span style='\""+(this.options.fontColor?"":"'color:{color};'")+
|
||||
"\"'>"+(d.label?"{label}":"{x}")+":</span> {y}, {z}";else if("pie"===b.type||"doughnut"===b.type||"funnel"===b.type)g=d.toolTipContent?d.toolTipContent:b.toolTipContent?b.toolTipContent:this.content&&"function"!==typeof this.content?this.content:"<span style='\""+(this.options.fontColor?"":"'color:{color};'")+"\"'>"+(d.name?"{name}:</span> ":d.label?"{label}:</span> ":"</span>")+"{y}";else if("rangeColumn"===b.type||"rangeBar"===b.type||"rangeArea"===b.type||
|
||||
"rangeSplineArea"===b.type)g=d.toolTipContent?d.toolTipContent:b.toolTipContent?b.toolTipContent:this.content&&"function"!==typeof this.content?this.content:"<span style='\""+(this.options.fontColor?"":"'color:{color};'")+"\"'>"+(d.label?"{label}":"{x}")+" :</span> {y[0]}, {y[1]}";else if("candlestick"===b.type||"ohlc"===b.type)g=d.toolTipContent?d.toolTipContent:b.toolTipContent?b.toolTipContent:this.content&&"function"!==typeof this.content?this.content:"<span style='\""+(this.options.fontColor?
|
||||
"":"'color:{color};'")+"\"'>"+(d.label?"{label}":"{x}")+"</span><br/>Open: {y[0]}<br/>High: {y[1]}<br/>Low: {y[2]}<br/>Close: {y[3]}";null===c&&(c="");c+=this.chart.replaceKeywordsWithValue(g,d,b,f)}return c};R.prototype.enableAnimation=function(){this.container.style.WebkitTransition||(this.container.style.WebkitTransition="left .2s ease-out, bottom .2s ease-out",this.container.style.MozTransition="left .2s ease-out, bottom .2s ease-out",
|
||||
this.container.style.MsTransition="left .2s ease-out, bottom .2s ease-out",this.container.style.transition="left .2s ease-out, bottom .2s ease-out")};R.prototype.disableAnimation=function(){this.container.style.WebkitTransition&&(this.container.style.WebkitTransition="",this.container.style.MozTransition="",this.container.style.MsTransition="",this.container.style.transition="")};R.prototype.hide=function(a){this.container&&(this.container.style.display="none",this.currentSeriesIndex=-1,this._prevY=
|
||||
this._prevX=NaN,("undefined"===typeof a||a)&&this.chart.resetOverlayedCanvas())};R.prototype.show=function(a,c,b){this._updateToolTip(a,c,"undefined"===typeof b?!1:b)};A.prototype.getPercentAndTotal=function(a,c){var b=null,d=null,f=null;if(0<=a.type.indexOf("stacked"))d=0,b=c.x.getTime?c.x.getTime():c.x,b in a.plotUnit.yTotals&&(d=a.plotUnit.yTotals[b],f=isNaN(c.y)?0:0===d?0:100*(c.y/d));else if("pie"===a.type||"doughnut"===a.type){for(i=d=0;i<a.dataPoints.length;i++)isNaN(a.dataPoints[i].y)||(d+=
|
||||
a.dataPoints[i].y);f=isNaN(c.y)?0:100*(c.y/d)}return{percent:f,total:d}};A.prototype.replaceKeywordsWithValue=function(a,c,b,d,f){var g=this;f="undefined"===typeof f?0:f;if((0<=b.type.indexOf("stacked")||"pie"===b.type||"doughnut"===b.type)&&(0<=a.indexOf("#percent")||0<=a.indexOf("#total"))){var l="#percent",k="#total",h=this.getPercentAndTotal(b,c),k=isNaN(h.total)?k:h.total,l=isNaN(h.percent)?l:h.percent;do{h="";if(b.percentFormatString)h=b.percentFormatString;else{var h="#,##0.",m=Math.max(Math.ceil(Math.log(1/
|
||||
Math.abs(l))/Math.LN10),2);if(isNaN(m)||!isFinite(m))m=2;for(var p=0;p<m;p++)h+="#";b.percentFormatString=h}a=a.replace("#percent",fa(l,h,g._cultureInfo));a=a.replace("#total",fa(k,b.yValueFormatString?b.yValueFormatString:"#,##0.########",g._cultureInfo))}while(0<=a.indexOf("#percent")||0<=a.indexOf("#total"))}return a.replace(/\{.*?\}|"[^"]*"|'[^']*'/g,function(a){if('"'===a[0]&&'"'===a[a.length-1]||"'"===a[0]&&"'"===a[a.length-1])return a.slice(1,a.length-1);a=ma(a.slice(1,a.length-1));a=a.replace("#index",
|
||||
f);var e=null;try{var h=a.match(/(.*?)\s*\[\s*(.*?)\s*\]/);h&&0<h.length&&(e=ma(h[2]),a=ma(h[1]))}catch(k){}h=null;if("color"===a)return c.color?c.color:b.color?b.color:b._colorSet[d%b._colorSet.length];if(c.hasOwnProperty(a))h=c;else if(b.hasOwnProperty(a))h=b;else return"";h=h[a];null!==e&&(h=h[e]);if("x"===a)if("dateTime"===g.plotInfo.axisXValueType||"dateTime"===b.xValueType||c.x&&c.x.getTime){if(g.plotInfo.plotTypes[0].plotUnits[0].axisX&&!g.plotInfo.plotTypes[0].plotUnits[0].axisX.logarithmic)return Fa(h,
|
||||
c.xValueFormatString?c.xValueFormatString:b.xValueFormatString?b.xValueFormatString:b.xValueFormatString=g.axisX&&g.axisX.autoValueFormatString?g.axisX.autoValueFormatString:"DD MMM YY",g._cultureInfo)}else return fa(h,c.xValueFormatString?c.xValueFormatString:b.xValueFormatString?b.xValueFormatString:b.xValueFormatString="#,##0.########",g._cultureInfo);else return"y"===a?fa(h,c.yValueFormatString?c.yValueFormatString:b.yValueFormatString?b.yValueFormatString:b.yValueFormatString="#,##0.########",
|
||||
g._cultureInfo):"z"===a?fa(h,c.zValueFormatString?c.zValueFormatString:b.zValueFormatString?b.zValueFormatString:b.zValueFormatString="#,##0.########",g._cultureInfo):h})};na.prototype.reset=function(){this.lastObjectId=0;this.objectMap=[];this.rectangularRegionEventSubscriptions=[];this.previousDataPointEventObject=null;this.eventObjects=[];t&&(this.ghostCtx.clearRect(0,0,this.chart.width,this.chart.height),this.ghostCtx.beginPath())};na.prototype.getNewObjectTrackingId=function(){return++this.lastObjectId};
|
||||
na.prototype.mouseEventHandler=function(a){if("mousemove"===a.type||"click"===a.type){var c=[],b=za(a),d=null;if((d=this.chart.getObjectAtXY(b.x,b.y,!1))&&"undefined"!==typeof this.objectMap[d])if(d=this.objectMap[d],"dataPoint"===d.objectType){var f=this.chart.data[d.dataSeriesIndex],g=f.dataPoints[d.dataPointIndex],l=d.dataPointIndex;d.eventParameter={x:b.x,y:b.y,dataPoint:g,dataSeries:f.options,dataPointIndex:l,dataSeriesIndex:f.index,chart:this.chart};d.eventContext={context:g,userContext:g,mouseover:"mouseover",
|
||||
mousemove:"mousemove",mouseout:"mouseout",click:"click"};c.push(d);d=this.objectMap[f.id];d.eventParameter={x:b.x,y:b.y,dataPoint:g,dataSeries:f.options,dataPointIndex:l,dataSeriesIndex:f.index,chart:this.chart};d.eventContext={context:f,userContext:f.options,mouseover:"mouseover",mousemove:"mousemove",mouseout:"mouseout",click:"click"};c.push(this.objectMap[f.id])}else"legendItem"===d.objectType&&(f=this.chart.data[d.dataSeriesIndex],g=null!==d.dataPointIndex?f.dataPoints[d.dataPointIndex]:null,
|
||||
d.eventParameter={x:b.x,y:b.y,dataSeries:f.options,dataPoint:g,dataPointIndex:d.dataPointIndex,dataSeriesIndex:d.dataSeriesIndex,chart:this.chart},d.eventContext={context:this.chart.legend,userContext:this.chart.legend.options,mouseover:"itemmouseover",mousemove:"itemmousemove",mouseout:"itemmouseout",click:"itemclick"},c.push(d));f=[];for(b=0;b<this.mouseoveredObjectMaps.length;b++){g=!0;for(d=0;d<c.length;d++)if(c[d].id===this.mouseoveredObjectMaps[b].id){g=!1;break}g?this.fireEvent(this.mouseoveredObjectMaps[b],
|
||||
"mouseout",a):f.push(this.mouseoveredObjectMaps[b])}this.mouseoveredObjectMaps=f;for(b=0;b<c.length;b++){f=!1;for(d=0;d<this.mouseoveredObjectMaps.length;d++)if(c[b].id===this.mouseoveredObjectMaps[d].id){f=!0;break}f||(this.fireEvent(c[b],"mouseover",a),this.mouseoveredObjectMaps.push(c[b]));"click"===a.type?this.fireEvent(c[b],"click",a):"mousemove"===a.type&&this.fireEvent(c[b],"mousemove",a)}}};na.prototype.fireEvent=function(a,c,b){if(a&&c){var d=a.eventParameter,f=a.eventContext,g=a.eventContext.userContext;
|
||||
g&&(f&&g[f[c]])&&g[f[c]].call(g,d);"mouseout"!==c?g.cursor&&g.cursor!==b.target.style.cursor&&(b.target.style.cursor=g.cursor):(b.target.style.cursor=this.chart._defaultCursor,delete a.eventParameter,delete a.eventContext);"click"===c&&("dataPoint"===a.objectType&&this.chart.pieDoughnutClickHandler)&&this.chart.pieDoughnutClickHandler.call(this.chart.data[a.dataSeriesIndex],d)}};T(qa,L);Ea.prototype.animate=function(a,c,b,d,f){var g=this;this.chart.isAnimating=!0;f=f||E.easing.linear;b&&this.animations.push({startTime:(new Date).getTime()+
|
||||
(a?a:0),duration:c,animationCallback:b,onComplete:d});for(a=[];0<this.animations.length;)if(c=this.animations.shift(),b=(new Date).getTime(),d=0,c.startTime<=b&&(d=f(Math.min(b-c.startTime,c.duration),0,1,c.duration),d=Math.min(d,1),isNaN(d)||!isFinite(d))&&(d=1),1>d&&a.push(c),c.animationCallback(d),1<=d&&c.onComplete)c.onComplete();this.animations=a;0<this.animations.length?this.animationRequestId=this.chart.requestAnimFrame.call(window,function(){g.animate.call(g)}):this.chart.isAnimating=!1};
|
||||
Ea.prototype.cancelAllAnimations=function(){this.animations=[];this.animationRequestId&&this.chart.cancelRequestAnimFrame.call(window,this.animationRequestId);this.animationRequestId=null;this.chart.isAnimating=!1};var E={yScaleAnimation:function(a,c){if(0!==a){var b=c.dest,d=c.source.canvas,f=c.animationBase;b.drawImage(d,0,0,d.width,d.height,0,f-f*a,b.canvas.width/Q,a*b.canvas.height/Q)}},xScaleAnimation:function(a,c){if(0!==a){var b=c.dest,d=c.source.canvas,f=c.animationBase;b.drawImage(d,0,0,
|
||||
d.width,d.height,f-f*a,0,a*b.canvas.width/Q,b.canvas.height/Q)}},xClipAnimation:function(a,c){if(0!==a){var b=c.dest,d=c.source.canvas;b.save();0<a&&b.drawImage(d,0,0,d.width*a,d.height,0,0,d.width*a/Q,d.height/Q);b.restore()}},fadeInAnimation:function(a,c){if(0!==a){var b=c.dest,d=c.source.canvas;b.save();b.globalAlpha=a;b.drawImage(d,0,0,d.width,d.height,0,0,b.canvas.width/Q,b.canvas.height/Q);b.restore()}},easing:{linear:function(a,c,b,d){return b*a/d+c},easeOutQuad:function(a,c,b,d){return-b*
|
||||
(a/=d)*(a-2)+c},easeOutQuart:function(a,c,b,d){return-b*((a=a/d-1)*a*a*a-1)+c},easeInQuad:function(a,c,b,d){return b*(a/=d)*a+c},easeInQuart:function(a,c,b,d){return b*(a/=d)*a*a*a+c}}},O={drawMarker:function(a,c,b,d,f,g,l,k){if(b){var h=1;b.fillStyle=g?g:"#000000";b.strokeStyle=l?l:"#000000";b.lineWidth=k?k:0;"circle"===d?(b.moveTo(a,c),b.beginPath(),b.arc(a,c,f/2,0,2*Math.PI,!1),g&&b.fill(),k&&(l?b.stroke():(h=b.globalAlpha,b.globalAlpha=0.15,b.strokeStyle="black",b.stroke(),b.globalAlpha=h))):
|
||||
"square"===d?(b.beginPath(),b.rect(a-f/2,c-f/2,f,f),g&&b.fill(),k&&(l?b.stroke():(h=b.globalAlpha,b.globalAlpha=0.15,b.strokeStyle="black",b.stroke(),b.globalAlpha=h))):"triangle"===d?(b.beginPath(),b.moveTo(a-f/2,c+f/2),b.lineTo(a+f/2,c+f/2),b.lineTo(a,c-f/2),b.closePath(),g&&b.fill(),k&&(l?b.stroke():(h=b.globalAlpha,b.globalAlpha=0.15,b.strokeStyle="black",b.stroke(),b.globalAlpha=h)),b.beginPath()):"cross"===d&&(b.strokeStyle=g,b.lineWidth=f/4,b.beginPath(),b.moveTo(a-f/2,c-f/2),b.lineTo(a+f/
|
||||
2,c+f/2),b.stroke(),b.moveTo(a+f/2,c-f/2),b.lineTo(a-f/2,c+f/2),b.stroke())}},drawMarkers:function(a){for(var c=0;c<a.length;c++){var b=a[c];O.drawMarker(b.x,b.y,b.ctx,b.type,b.size,b.color,b.borderColor,b.borderThickness)}}},Ra={Chart:A,addColorSet:function(a,c){ja[a]=c},addCultureInfo:function(a,c){ra[a]=c},formatNumber:function(a,c,b){b=b||"en";if(ra[b])return fa(a,c||"#,##0.##",new qa(b));throw"Unknown Culture Name";},formatDate:function(a,c,b){b=b||"en";if(ra[b])return Fa(a,c||"DD MMM YYYY",
|
||||
new qa(b));throw"Unknown Culture Name";}};Ra.Chart.version="v1.9.10 GA";window.CanvasJS=Ra})();
|
||||
|
||||
/*
|
||||
excanvas is used to support IE678 which do not implement HTML5 Canvas Element. You can safely remove the following excanvas code if you don't need to support older browsers.
|
||||
|
||||
Copyright 2006 Google Inc. https://code.google.com/p/explorercanvas/
|
||||
Licensed under the Apache License, Version 2.0
|
||||
*/
|
||||
document.createElement("canvas").getContext||function(){function V(){return this.context_||(this.context_=new C(this))}function W(a,b,c){var g=M.call(arguments,2);return function(){return a.apply(b,g.concat(M.call(arguments)))}}function N(a){return String(a).replace(/&/g,"&").replace(/"/g,""")}function O(a){a.namespaces.g_vml_||a.namespaces.add("g_vml_","urn:schemas-microsoft-com:vml","#default#VML");a.namespaces.g_o_||a.namespaces.add("g_o_","urn:schemas-microsoft-com:office:office","#default#VML");
|
||||
a.styleSheets.ex_canvas_||(a=a.createStyleSheet(),a.owningElement.id="ex_canvas_",a.cssText="canvas{display:inline-block;overflow:hidden;text-align:left;width:300px;height:150px}")}function X(a){var b=a.srcElement;switch(a.propertyName){case "width":b.getContext().clearRect();b.style.width=b.attributes.width.nodeValue+"px";b.firstChild.style.width=b.clientWidth+"px";break;case "height":b.getContext().clearRect(),b.style.height=b.attributes.height.nodeValue+"px",b.firstChild.style.height=b.clientHeight+
|
||||
"px"}}function Y(a){a=a.srcElement;a.firstChild&&(a.firstChild.style.width=a.clientWidth+"px",a.firstChild.style.height=a.clientHeight+"px")}function D(){return[[1,0,0],[0,1,0],[0,0,1]]}function t(a,b){for(var c=D(),g=0;3>g;g++)for(var e=0;3>e;e++){for(var f=0,d=0;3>d;d++)f+=a[g][d]*b[d][e];c[g][e]=f}return c}function P(a,b){b.fillStyle=a.fillStyle;b.lineCap=a.lineCap;b.lineJoin=a.lineJoin;b.lineWidth=a.lineWidth;b.miterLimit=a.miterLimit;b.shadowBlur=a.shadowBlur;b.shadowColor=a.shadowColor;b.shadowOffsetX=
|
||||
a.shadowOffsetX;b.shadowOffsetY=a.shadowOffsetY;b.strokeStyle=a.strokeStyle;b.globalAlpha=a.globalAlpha;b.font=a.font;b.textAlign=a.textAlign;b.textBaseline=a.textBaseline;b.arcScaleX_=a.arcScaleX_;b.arcScaleY_=a.arcScaleY_;b.lineScale_=a.lineScale_}function Q(a){var b=a.indexOf("(",3),c=a.indexOf(")",b+1),b=a.substring(b+1,c).split(",");if(4!=b.length||"a"!=a.charAt(3))b[3]=1;return b}function E(a,b,c){return Math.min(c,Math.max(b,a))}function F(a,b,c){0>c&&c++;1<c&&c--;return 1>6*c?a+6*(b-a)*c:
|
||||
1>2*c?b:2>3*c?a+6*(b-a)*(2/3-c):a}function G(a){if(a in H)return H[a];var b,c=1;a=String(a);if("#"==a.charAt(0))b=a;else if(/^rgb/.test(a)){c=Q(a);b="#";for(var g,e=0;3>e;e++)g=-1!=c[e].indexOf("%")?Math.floor(255*(parseFloat(c[e])/100)):+c[e],b+=v[E(g,0,255)];c=+c[3]}else if(/^hsl/.test(a)){e=c=Q(a);b=parseFloat(e[0])/360%360;0>b&&b++;g=E(parseFloat(e[1])/100,0,1);e=E(parseFloat(e[2])/100,0,1);if(0==g)g=e=b=e;else{var f=0.5>e?e*(1+g):e+g-e*g,d=2*e-f;g=F(d,f,b+1/3);e=F(d,f,b);b=F(d,f,b-1/3)}b="#"+
|
||||
v[Math.floor(255*g)]+v[Math.floor(255*e)]+v[Math.floor(255*b)];c=c[3]}else b=Z[a]||a;return H[a]={color:b,alpha:c}}function C(a){this.m_=D();this.mStack_=[];this.aStack_=[];this.currentPath_=[];this.fillStyle=this.strokeStyle="#000";this.lineWidth=1;this.lineJoin="miter";this.lineCap="butt";this.miterLimit=1*q;this.globalAlpha=1;this.font="10px sans-serif";this.textAlign="left";this.textBaseline="alphabetic";this.canvas=a;var b="width:"+a.clientWidth+"px;height:"+a.clientHeight+"px;overflow:hidden;position:absolute",
|
||||
c=a.ownerDocument.createElement("div");c.style.cssText=b;a.appendChild(c);b=c.cloneNode(!1);b.style.backgroundColor="red";b.style.filter="alpha(opacity=0)";a.appendChild(b);this.element_=c;this.lineScale_=this.arcScaleY_=this.arcScaleX_=1}function R(a,b,c,g){a.currentPath_.push({type:"bezierCurveTo",cp1x:b.x,cp1y:b.y,cp2x:c.x,cp2y:c.y,x:g.x,y:g.y});a.currentX_=g.x;a.currentY_=g.y}function S(a,b){var c=G(a.strokeStyle),g=c.color,c=c.alpha*a.globalAlpha,e=a.lineScale_*a.lineWidth;1>e&&(c*=e);b.push("<g_vml_:stroke",
|
||||
' opacity="',c,'"',' joinstyle="',a.lineJoin,'"',' miterlimit="',a.miterLimit,'"',' endcap="',$[a.lineCap]||"square",'"',' weight="',e,'px"',' color="',g,'" />')}function T(a,b,c,g){var e=a.fillStyle,f=a.arcScaleX_,d=a.arcScaleY_,k=g.x-c.x,n=g.y-c.y;if(e instanceof w){var h=0,l=g=0,u=0,m=1;if("gradient"==e.type_){h=e.x1_/f;c=e.y1_/d;var p=s(a,e.x0_/f,e.y0_/d),h=s(a,h,c),h=180*Math.atan2(h.x-p.x,h.y-p.y)/Math.PI;0>h&&(h+=360);1E-6>h&&(h=0)}else p=s(a,e.x0_,e.y0_),g=(p.x-c.x)/k,l=(p.y-c.y)/n,k/=f*q,
|
||||
n/=d*q,m=x.max(k,n),u=2*e.r0_/m,m=2*e.r1_/m-u;f=e.colors_;f.sort(function(a,b){return a.offset-b.offset});d=f.length;p=f[0].color;c=f[d-1].color;k=f[0].alpha*a.globalAlpha;a=f[d-1].alpha*a.globalAlpha;for(var n=[],r=0;r<d;r++){var t=f[r];n.push(t.offset*m+u+" "+t.color)}b.push('<g_vml_:fill type="',e.type_,'"',' method="none" focus="100%"',' color="',p,'"',' color2="',c,'"',' colors="',n.join(","),'"',' opacity="',a,'"',' g_o_:opacity2="',k,'"',' angle="',h,'"',' focusposition="',g,",",l,'" />')}else e instanceof
|
||||
I?k&&n&&b.push("<g_vml_:fill",' position="',-c.x/k*f*f,",",-c.y/n*d*d,'"',' type="tile"',' src="',e.src_,'" />'):(e=G(a.fillStyle),b.push('<g_vml_:fill color="',e.color,'" opacity="',e.alpha*a.globalAlpha,'" />'))}function s(a,b,c){a=a.m_;return{x:q*(b*a[0][0]+c*a[1][0]+a[2][0])-r,y:q*(b*a[0][1]+c*a[1][1]+a[2][1])-r}}function z(a,b,c){isFinite(b[0][0])&&(isFinite(b[0][1])&&isFinite(b[1][0])&&isFinite(b[1][1])&&isFinite(b[2][0])&&isFinite(b[2][1]))&&(a.m_=b,c&&(a.lineScale_=aa(ba(b[0][0]*b[1][1]-b[0][1]*
|
||||
b[1][0]))))}function w(a){this.type_=a;this.r1_=this.y1_=this.x1_=this.r0_=this.y0_=this.x0_=0;this.colors_=[]}function I(a,b){if(!a||1!=a.nodeType||"IMG"!=a.tagName)throw new A("TYPE_MISMATCH_ERR");if("complete"!=a.readyState)throw new A("INVALID_STATE_ERR");switch(b){case "repeat":case null:case "":this.repetition_="repeat";break;case "repeat-x":case "repeat-y":case "no-repeat":this.repetition_=b;break;default:throw new A("SYNTAX_ERR");}this.src_=a.src;this.width_=a.width;this.height_=a.height}
|
||||
function A(a){this.code=this[a];this.message=a+": DOM Exception "+this.code}var x=Math,k=x.round,J=x.sin,K=x.cos,ba=x.abs,aa=x.sqrt,q=10,r=q/2;navigator.userAgent.match(/MSIE ([\d.]+)?/);var M=Array.prototype.slice;O(document);var U={init:function(a){a=a||document;a.createElement("canvas");a.attachEvent("onreadystatechange",W(this.init_,this,a))},init_:function(a){a=a.getElementsByTagName("canvas");for(var b=0;b<a.length;b++)this.initElement(a[b])},initElement:function(a){if(!a.getContext){a.getContext=
|
||||
V;O(a.ownerDocument);a.innerHTML="";a.attachEvent("onpropertychange",X);a.attachEvent("onresize",Y);var b=a.attributes;b.width&&b.width.specified?a.style.width=b.width.nodeValue+"px":a.width=a.clientWidth;b.height&&b.height.specified?a.style.height=b.height.nodeValue+"px":a.height=a.clientHeight}return a}};U.init();for(var v=[],d=0;16>d;d++)for(var B=0;16>B;B++)v[16*d+B]=d.toString(16)+B.toString(16);var Z={aliceblue:"#F0F8FF",antiquewhite:"#FAEBD7",aquamarine:"#7FFFD4",azure:"#F0FFFF",beige:"#F5F5DC",
|
||||
bisque:"#FFE4C4",black:"#000000",blanchedalmond:"#FFEBCD",blueviolet:"#8A2BE2",brown:"#A52A2A",burlywood:"#DEB887",cadetblue:"#5F9EA0",chartreuse:"#7FFF00",chocolate:"#D2691E",coral:"#FF7F50",cornflowerblue:"#6495ED",cornsilk:"#FFF8DC",crimson:"#DC143C",cyan:"#00FFFF",darkblue:"#00008B",darkcyan:"#008B8B",darkgoldenrod:"#B8860B",darkgray:"#A9A9A9",darkgreen:"#006400",darkgrey:"#A9A9A9",darkkhaki:"#BDB76B",darkmagenta:"#8B008B",darkolivegreen:"#556B2F",darkorange:"#FF8C00",darkorchid:"#9932CC",darkred:"#8B0000",
|
||||
darksalmon:"#E9967A",darkseagreen:"#8FBC8F",darkslateblue:"#483D8B",darkslategray:"#2F4F4F",darkslategrey:"#2F4F4F",darkturquoise:"#00CED1",darkviolet:"#9400D3",deeppink:"#FF1493",deepskyblue:"#00BFFF",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1E90FF",firebrick:"#B22222",floralwhite:"#FFFAF0",forestgreen:"#228B22",gainsboro:"#DCDCDC",ghostwhite:"#F8F8FF",gold:"#FFD700",goldenrod:"#DAA520",grey:"#808080",greenyellow:"#ADFF2F",honeydew:"#F0FFF0",hotpink:"#FF69B4",indianred:"#CD5C5C",indigo:"#4B0082",
|
||||
ivory:"#FFFFF0",khaki:"#F0E68C",lavender:"#E6E6FA",lavenderblush:"#FFF0F5",lawngreen:"#7CFC00",lemonchiffon:"#FFFACD",lightblue:"#ADD8E6",lightcoral:"#F08080",lightcyan:"#E0FFFF",lightgoldenrodyellow:"#FAFAD2",lightgreen:"#90EE90",lightgrey:"#D3D3D3",lightpink:"#FFB6C1",lightsalmon:"#FFA07A",lightseagreen:"#20B2AA",lightskyblue:"#87CEFA",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#B0C4DE",lightyellow:"#FFFFE0",limegreen:"#32CD32",linen:"#FAF0E6",magenta:"#FF00FF",mediumaquamarine:"#66CDAA",
|
||||
mediumblue:"#0000CD",mediumorchid:"#BA55D3",mediumpurple:"#9370DB",mediumseagreen:"#3CB371",mediumslateblue:"#7B68EE",mediumspringgreen:"#00FA9A",mediumturquoise:"#48D1CC",mediumvioletred:"#C71585",midnightblue:"#191970",mintcream:"#F5FFFA",mistyrose:"#FFE4E1",moccasin:"#FFE4B5",navajowhite:"#FFDEAD",oldlace:"#FDF5E6",olivedrab:"#6B8E23",orange:"#FFA500",orangered:"#FF4500",orchid:"#DA70D6",palegoldenrod:"#EEE8AA",palegreen:"#98FB98",paleturquoise:"#AFEEEE",palevioletred:"#DB7093",papayawhip:"#FFEFD5",
|
||||
peachpuff:"#FFDAB9",peru:"#CD853F",pink:"#FFC0CB",plum:"#DDA0DD",powderblue:"#B0E0E6",rosybrown:"#BC8F8F",royalblue:"#4169E1",saddlebrown:"#8B4513",salmon:"#FA8072",sandybrown:"#F4A460",seagreen:"#2E8B57",seashell:"#FFF5EE",sienna:"#A0522D",skyblue:"#87CEEB",slateblue:"#6A5ACD",slategray:"#708090",slategrey:"#708090",snow:"#FFFAFA",springgreen:"#00FF7F",steelblue:"#4682B4",tan:"#D2B48C",thistle:"#D8BFD8",tomato:"#FF6347",turquoise:"#40E0D0",violet:"#EE82EE",wheat:"#F5DEB3",whitesmoke:"#F5F5F5",yellowgreen:"#9ACD32"},
|
||||
H={},L={},$={butt:"flat",round:"round"},d=C.prototype;d.clearRect=function(){this.textMeasureEl_&&(this.textMeasureEl_.removeNode(!0),this.textMeasureEl_=null);this.element_.innerHTML=""};d.beginPath=function(){this.currentPath_=[]};d.moveTo=function(a,b){var c=s(this,a,b);this.currentPath_.push({type:"moveTo",x:c.x,y:c.y});this.currentX_=c.x;this.currentY_=c.y};d.lineTo=function(a,b){var c=s(this,a,b);this.currentPath_.push({type:"lineTo",x:c.x,y:c.y});this.currentX_=c.x;this.currentY_=c.y};d.bezierCurveTo=
|
||||
function(a,b,c,g,e,f){e=s(this,e,f);a=s(this,a,b);c=s(this,c,g);R(this,a,c,e)};d.quadraticCurveTo=function(a,b,c,g){a=s(this,a,b);c=s(this,c,g);g={x:this.currentX_+2/3*(a.x-this.currentX_),y:this.currentY_+2/3*(a.y-this.currentY_)};R(this,g,{x:g.x+(c.x-this.currentX_)/3,y:g.y+(c.y-this.currentY_)/3},c)};d.arc=function(a,b,c,g,e,f){c*=q;var d=f?"at":"wa",k=a+K(g)*c-r,n=b+J(g)*c-r;g=a+K(e)*c-r;e=b+J(e)*c-r;k!=g||f||(k+=0.125);a=s(this,a,b);k=s(this,k,n);g=s(this,g,e);this.currentPath_.push({type:d,
|
||||
x:a.x,y:a.y,radius:c,xStart:k.x,yStart:k.y,xEnd:g.x,yEnd:g.y})};d.rect=function(a,b,c,g){this.moveTo(a,b);this.lineTo(a+c,b);this.lineTo(a+c,b+g);this.lineTo(a,b+g);this.closePath()};d.strokeRect=function(a,b,c,g){var e=this.currentPath_;this.beginPath();this.moveTo(a,b);this.lineTo(a+c,b);this.lineTo(a+c,b+g);this.lineTo(a,b+g);this.closePath();this.stroke();this.currentPath_=e};d.fillRect=function(a,b,c,g){var e=this.currentPath_;this.beginPath();this.moveTo(a,b);this.lineTo(a+c,b);this.lineTo(a+
|
||||
c,b+g);this.lineTo(a,b+g);this.closePath();this.fill();this.currentPath_=e};d.createLinearGradient=function(a,b,c,g){var e=new w("gradient");e.x0_=a;e.y0_=b;e.x1_=c;e.y1_=g;return e};d.createRadialGradient=function(a,b,c,g,e,f){var d=new w("gradientradial");d.x0_=a;d.y0_=b;d.r0_=c;d.x1_=g;d.y1_=e;d.r1_=f;return d};d.drawImage=function(a,b){var c,g,e,d,r,y,n,h;e=a.runtimeStyle.width;d=a.runtimeStyle.height;a.runtimeStyle.width="auto";a.runtimeStyle.height="auto";var l=a.width,u=a.height;a.runtimeStyle.width=
|
||||
e;a.runtimeStyle.height=d;if(3==arguments.length)c=arguments[1],g=arguments[2],r=y=0,n=e=l,h=d=u;else if(5==arguments.length)c=arguments[1],g=arguments[2],e=arguments[3],d=arguments[4],r=y=0,n=l,h=u;else if(9==arguments.length)r=arguments[1],y=arguments[2],n=arguments[3],h=arguments[4],c=arguments[5],g=arguments[6],e=arguments[7],d=arguments[8];else throw Error("Invalid number of arguments");var m=s(this,c,g),p=[];p.push(" <g_vml_:group",' coordsize="',10*q,",",10*q,'"',' coordorigin="0,0"',' style="width:',
|
||||
10,"px;height:",10,"px;position:absolute;");if(1!=this.m_[0][0]||this.m_[0][1]||1!=this.m_[1][1]||this.m_[1][0]){var t=[];t.push("M11=",this.m_[0][0],",","M12=",this.m_[1][0],",","M21=",this.m_[0][1],",","M22=",this.m_[1][1],",","Dx=",k(m.x/q),",","Dy=",k(m.y/q),"");var v=s(this,c+e,g),w=s(this,c,g+d);c=s(this,c+e,g+d);m.x=x.max(m.x,v.x,w.x,c.x);m.y=x.max(m.y,v.y,w.y,c.y);p.push("padding:0 ",k(m.x/q),"px ",k(m.y/q),"px 0;filter:progid:DXImageTransform.Microsoft.Matrix(",t.join(""),", sizingmethod='clip');")}else p.push("top:",
|
||||
k(m.y/q),"px;left:",k(m.x/q),"px;");p.push(' ">','<g_vml_:image src="',a.src,'"',' style="width:',q*e,"px;"," height:",q*d,'px"',' cropleft="',r/l,'"',' croptop="',y/u,'"',' cropright="',(l-r-n)/l,'"',' cropbottom="',(u-y-h)/u,'"'," />","</g_vml_:group>");this.element_.insertAdjacentHTML("BeforeEnd",p.join(""))};d.stroke=function(a){var b=[];b.push("<g_vml_:shape",' filled="',!!a,'"',' style="position:absolute;width:',10,"px;height:",10,'px;"',' coordorigin="0,0"',' coordsize="',10*q,",",10*q,'"',
|
||||
' stroked="',!a,'"',' path="');for(var c={x:null,y:null},d={x:null,y:null},e=0;e<this.currentPath_.length;e++){var f=this.currentPath_[e];switch(f.type){case "moveTo":b.push(" m ",k(f.x),",",k(f.y));break;case "lineTo":b.push(" l ",k(f.x),",",k(f.y));break;case "close":b.push(" x ");f=null;break;case "bezierCurveTo":b.push(" c ",k(f.cp1x),",",k(f.cp1y),",",k(f.cp2x),",",k(f.cp2y),",",k(f.x),",",k(f.y));break;case "at":case "wa":b.push(" ",f.type," ",k(f.x-this.arcScaleX_*f.radius),",",k(f.y-this.arcScaleY_*
|
||||
f.radius)," ",k(f.x+this.arcScaleX_*f.radius),",",k(f.y+this.arcScaleY_*f.radius)," ",k(f.xStart),",",k(f.yStart)," ",k(f.xEnd),",",k(f.yEnd))}if(f){if(null==c.x||f.x<c.x)c.x=f.x;if(null==d.x||f.x>d.x)d.x=f.x;if(null==c.y||f.y<c.y)c.y=f.y;if(null==d.y||f.y>d.y)d.y=f.y}}b.push(' ">');a?T(this,b,c,d):S(this,b);b.push("</g_vml_:shape>");this.element_.insertAdjacentHTML("beforeEnd",b.join(""))};d.fill=function(){this.stroke(!0)};d.closePath=function(){this.currentPath_.push({type:"close"})};d.save=function(){var a=
|
||||
{};P(this,a);this.aStack_.push(a);this.mStack_.push(this.m_);this.m_=t(D(),this.m_)};d.restore=function(){this.aStack_.length&&(P(this.aStack_.pop(),this),this.m_=this.mStack_.pop())};d.translate=function(a,b){z(this,t([[1,0,0],[0,1,0],[a,b,1]],this.m_),!1)};d.rotate=function(a){var b=K(a);a=J(a);z(this,t([[b,a,0],[-a,b,0],[0,0,1]],this.m_),!1)};d.scale=function(a,b){this.arcScaleX_*=a;this.arcScaleY_*=b;z(this,t([[a,0,0],[0,b,0],[0,0,1]],this.m_),!0)};d.transform=function(a,b,c,d,e,f){z(this,t([[a,
|
||||
b,0],[c,d,0],[e,f,1]],this.m_),!0)};d.setTransform=function(a,b,c,d,e,f){z(this,[[a,b,0],[c,d,0],[e,f,1]],!0)};d.drawText_=function(a,b,c,d,e){var f=this.m_;d=0;var r=1E3,t=0,n=[],h;h=this.font;if(L[h])h=L[h];else{var l=document.createElement("div").style;try{l.font=h}catch(u){}h=L[h]={style:l.fontStyle||"normal",variant:l.fontVariant||"normal",weight:l.fontWeight||"normal",size:l.fontSize||10,family:l.fontFamily||"sans-serif"}}var l=h,m=this.element_;h={};for(var p in l)h[p]=l[p];p=parseFloat(m.currentStyle.fontSize);
|
||||
m=parseFloat(l.size);"number"==typeof l.size?h.size=l.size:-1!=l.size.indexOf("px")?h.size=m:-1!=l.size.indexOf("em")?h.size=p*m:-1!=l.size.indexOf("%")?h.size=p/100*m:-1!=l.size.indexOf("pt")?h.size=m/0.75:h.size=p;h.size*=0.981;p=h.style+" "+h.variant+" "+h.weight+" "+h.size+"px "+h.family;m=this.element_.currentStyle;l=this.textAlign.toLowerCase();switch(l){case "left":case "center":case "right":break;case "end":l="ltr"==m.direction?"right":"left";break;case "start":l="rtl"==m.direction?"right":
|
||||
"left";break;default:l="left"}switch(this.textBaseline){case "hanging":case "top":t=h.size/1.75;break;case "middle":break;default:case null:case "alphabetic":case "ideographic":case "bottom":t=-h.size/2.25}switch(l){case "right":d=1E3;r=0.05;break;case "center":d=r=500}b=s(this,b+0,c+t);n.push('<g_vml_:line from="',-d,' 0" to="',r,' 0.05" ',' coordsize="100 100" coordorigin="0 0"',' filled="',!e,'" stroked="',!!e,'" style="position:absolute;width:1px;height:1px;">');e?S(this,n):T(this,n,{x:-d,y:0},
|
||||
{x:r,y:h.size});e=f[0][0].toFixed(3)+","+f[1][0].toFixed(3)+","+f[0][1].toFixed(3)+","+f[1][1].toFixed(3)+",0,0";b=k(b.x/q)+","+k(b.y/q);n.push('<g_vml_:skew on="t" matrix="',e,'" ',' offset="',b,'" origin="',d,' 0" />','<g_vml_:path textpathok="true" />','<g_vml_:textpath on="true" string="',N(a),'" style="v-text-align:',l,";font:",N(p),'" /></g_vml_:line>');this.element_.insertAdjacentHTML("beforeEnd",n.join(""))};d.fillText=function(a,b,c,d){this.drawText_(a,b,c,d,!1)};d.strokeText=function(a,
|
||||
b,c,d){this.drawText_(a,b,c,d,!0)};d.measureText=function(a){this.textMeasureEl_||(this.element_.insertAdjacentHTML("beforeEnd",'<span style="position:absolute;top:-20000px;left:0;padding:0;margin:0;border:none;white-space:pre;"></span>'),this.textMeasureEl_=this.element_.lastChild);var b=this.element_.ownerDocument;this.textMeasureEl_.innerHTML="";this.textMeasureEl_.style.font=this.font;this.textMeasureEl_.appendChild(b.createTextNode(a));return{width:this.textMeasureEl_.offsetWidth}};d.clip=function(){};
|
||||
d.arcTo=function(){};d.createPattern=function(a,b){return new I(a,b)};w.prototype.addColorStop=function(a,b){b=G(b);this.colors_.push({offset:a,color:b.color,alpha:b.alpha})};d=A.prototype=Error();d.INDEX_SIZE_ERR=1;d.DOMSTRING_SIZE_ERR=2;d.HIERARCHY_REQUEST_ERR=3;d.WRONG_DOCUMENT_ERR=4;d.INVALID_CHARACTER_ERR=5;d.NO_DATA_ALLOWED_ERR=6;d.NO_MODIFICATION_ALLOWED_ERR=7;d.NOT_FOUND_ERR=8;d.NOT_SUPPORTED_ERR=9;d.INUSE_ATTRIBUTE_ERR=10;d.INVALID_STATE_ERR=11;d.SYNTAX_ERR=12;d.INVALID_MODIFICATION_ERR=
|
||||
13;d.NAMESPACE_ERR=14;d.INVALID_ACCESS_ERR=15;d.VALIDATION_ERR=16;d.TYPE_MISMATCH_ERR=17;G_vmlCanvasManager=U;CanvasRenderingContext2D=C;CanvasGradient=w;CanvasPattern=I;DOMException=A}();
|
||||
@@ -1,10 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
</head>
|
||||
<script src="../../y.js"></script>
|
||||
<script src='../../../y-websockets-client/y-websockets-client.js'></script>
|
||||
<script src="./index.js"></script>
|
||||
</head>
|
||||
<body contenteditable="true">
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,29 +0,0 @@
|
||||
/* global Y */
|
||||
|
||||
window.onload = function () {
|
||||
window.domBinding = new Y.DomBinding(window.yXmlType, document.body, { scrollingElement: document.scrollingElement })
|
||||
}
|
||||
|
||||
let y = new Y('htmleditor', {
|
||||
connector: {
|
||||
name: 'websockets-client',
|
||||
url: 'http://127.0.0.1:1234'
|
||||
}
|
||||
})
|
||||
|
||||
window.y = y
|
||||
window.yXmlType = y.define('xml', Y.XmlFragment)
|
||||
window.undoManager = new Y.utils.UndoManager(window.yXmlType, {
|
||||
captureTimeout: 500
|
||||
})
|
||||
|
||||
document.onkeydown = function interceptUndoRedo (e) {
|
||||
if (e.keyCode === 90 && (e.metaKey || e.ctrlKey)) {
|
||||
if (!e.shiftKey) {
|
||||
window.undoManager.undo()
|
||||
} else {
|
||||
window.undoManager.redo()
|
||||
}
|
||||
e.preventDefault()
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<div id="codeMirrorContainer"></div>
|
||||
<script src="../bower_components/codemirror/lib/codemirror.js"></script>
|
||||
<script src="../bower_components/codemirror/mode/javascript/javascript.js"></script>
|
||||
<link rel="stylesheet" href="../bower_components/codemirror/lib/codemirror.css">
|
||||
<style>
|
||||
.CodeMirror {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
<script src="../../y.js"></script>
|
||||
<script src='../../../y-websockets-client/y-websockets-client.js'></script>
|
||||
<script src='../../../y-indexeddb/y-indexeddb.js'></script>
|
||||
<script src="./index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,19 +0,0 @@
|
||||
/* global Y, CodeMirror */
|
||||
|
||||
const persistence = new Y.IndexedDB()
|
||||
const connector = {
|
||||
connector: {
|
||||
name: 'websockets-client',
|
||||
room: 'codemirror-example'
|
||||
}
|
||||
}
|
||||
|
||||
const y = new Y('codemirror-example', connector, persistence)
|
||||
window.yCodeMirror = y
|
||||
|
||||
var editor = CodeMirror(document.querySelector('#codeMirrorContainer'), {
|
||||
mode: 'javascript',
|
||||
lineNumbers: true
|
||||
})
|
||||
|
||||
y.define('codemirror', Y.Text).bindCodeMirror(editor)
|
||||
@@ -1,55 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<style>
|
||||
.wrapper {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
grid-gap: 7px;
|
||||
}
|
||||
.one {
|
||||
grid-column: 1 ;
|
||||
}
|
||||
.two {
|
||||
grid-column: 2;
|
||||
}
|
||||
.three {
|
||||
grid-column: 3;
|
||||
}
|
||||
textarea {
|
||||
width: calc(100% - 10px)
|
||||
}
|
||||
.editor-container {
|
||||
background-color: #4caf50;
|
||||
padding: 4px 5px 10px 5px;
|
||||
border-radius: 11px;
|
||||
}
|
||||
.editor-container[disconnected] {
|
||||
background-color: red;
|
||||
}
|
||||
.disconnected-info {
|
||||
display: none;
|
||||
}
|
||||
.editor-container[disconnected] .disconnected-info {
|
||||
display: inline;
|
||||
}
|
||||
</style>
|
||||
<div class="wrapper">
|
||||
<div id="container1" class="one editor-container">
|
||||
<h1>Server 1 <span class="disconnected-info">(disconnected)</span></h1>
|
||||
<textarea id="textarea1" rows=40 autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"></textarea>
|
||||
</div>
|
||||
<div id="container2" class="two editor-container">
|
||||
<h1>Server 2 <span class="disconnected-info">(disconnected)</span></h1>
|
||||
<textarea id="textarea2" rows=40 autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"></textarea>
|
||||
</div>
|
||||
<div id="container3" class="three editor-container">
|
||||
<h1>Server 3 <span class="disconnected-info">(disconnected)</span></h1>
|
||||
<textarea id="textarea3" rows=40 autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<script src="../../y.js"></script>
|
||||
<script src='../../../y-websockets-client/y-websockets-client.js'></script>
|
||||
<script src="./index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,38 +0,0 @@
|
||||
/* global Y */
|
||||
|
||||
function bindYjsInstance (y, suffix) {
|
||||
y.define('textarea', Y.Text).bind(document.getElementById('textarea' + suffix))
|
||||
y.connector.socket.on('connection', function () {
|
||||
document.getElementById('container' + suffix).removeAttribute('disconnected')
|
||||
})
|
||||
y.connector.socket.on('disconnect', function () {
|
||||
document.getElementById('container' + suffix).setAttribute('disconnected', true)
|
||||
})
|
||||
}
|
||||
|
||||
let y1 = new Y('infinite-example', {
|
||||
connector: {
|
||||
name: 'websockets-client',
|
||||
url: 'http://127.0.0.1:1234'
|
||||
}
|
||||
})
|
||||
window.y1 = y1
|
||||
bindYjsInstance(y1, '1')
|
||||
|
||||
let y2 = new Y('infinite-example', {
|
||||
connector: {
|
||||
name: 'websockets-client',
|
||||
url: 'http://127.0.0.1:1234'
|
||||
}
|
||||
})
|
||||
window.y2 = y2
|
||||
bindYjsInstance(y2, '2')
|
||||
|
||||
let y3 = new Y('infinite-example', {
|
||||
connector: {
|
||||
name: 'websockets-client',
|
||||
url: 'http://127.0.0.1:1234'
|
||||
}
|
||||
})
|
||||
window.y3 = y3
|
||||
bindYjsInstance(y1, '3')
|
||||
@@ -1,24 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style type="text/css">
|
||||
.draggable {
|
||||
cursor: move;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<svg id="puzzle-example" width="100%" viewBox="0 0 800 800">
|
||||
<g>
|
||||
<path d="M 311.76636,154.23389 C 312.14136,171.85693 318.14087,184.97998 336.13843,184.23047 C 354.13647,183.48047 351.88647,180.48096 354.88599,178.98096 C 357.8855,177.48096 368.38452,170.35693 380.00806,169.98193 C 424.61841,168.54297 419.78296,223.6001 382.25757,223.6001 C 377.75806,223.6001 363.51001,219.10107 356.38599,211.97656 C 349.26196,204.85254 310.64185,207.10254 314.76636,236.34863 C 316.34888,247.5708 324.08374,267.90723 324.84595,286.23486 C 325.29321,296.99414 323.17603,307.00635 321.58911,315.6377 C 360.11353,305.4585 367.73462,304.30518 404.00513,312.83936 C 410.37915,314.33887 436.62573,310.21436 421.25269,290.3418 C 405.87964,270.46924 406.25464,248.34717 417.12817,240.84814 C 428.00171,233.34912 446.74976,228.84961 457.99829,234.09912 C 469.24683,239.34814 484.61987,255.84619 475.24585,271.59424 C 465.87231,287.34229 452.74878,290.7168 456.49829,303.84033 C 460.2478,316.96387 479.74536,320.33838 500.74292,321.83789 C 509.70142,322.47803 527.97192,323.28467 542.10864,320.12939 C 549.91821,318.38672 556.92212,315.89502 562.46753,313.56396 C 561.40796,277.80664 560.84888,245.71729 560.3606,241.97314 C 558.85278,230.41455 542.49536,217.28564 525.86499,223.2251 C 520.61548,225.1001 519.86548,231.84912 505.24243,232.59912 C 444.92798,235.69238 462.06958,143.26709 525.86499,180.48096 C 539.52759,188.45068 575.19409,190.7583 570.10913,156.85889 C 567.85962,141.86035 553.98608,102.86523 553.98608,102.86523 C 553.98608,102.86523 477.23755,111.82227 451.99878,91.991699 C 441.50024,83.74292 444.87476,69.494629 449.37427,61.245605 C 453.87378,52.996582 465.12231,46.622559 464.74731,36.123779 C 463.02563,-12.086426 392.96704,-10.902832 396.5061,36.873535 C 397.25562,46.997314 406.62964,52.621582 410.75415,60.495605 C 420.00757,78.161377 405.50024,96.073486 384.50757,99.490723 C 377.36206,100.65381 349.17505,102.65332 320.39429,102.23486 C 319.677,102.22461 318.95923,102.21143 318.24194,102.19775 C 315.08423,120.9751 311.55688,144.39697 311.76636,154.23389 z " style="fill:#f2c569;stroke:#000000" id="path2502"/>
|
||||
<path d="M 500.74292,321.83789 C 479.74536,320.33838 460.2478,316.96387 456.49829,303.84033 C 452.74878,290.7168 465.87231,287.34229 475.24585,271.59424 C 484.61987,255.84619 469.24683,239.34814 457.99829,234.09912 C 446.74976,228.84961 428.00171,233.34912 417.12817,240.84814 C 406.25464,248.34717 405.87964,270.46924 421.25269,290.3418 C 436.62573,310.21436 410.37915,314.33887 404.00513,312.83936 C 367.73462,304.30518 360.11353,305.4585 321.58911,315.6377 C 320.56372,321.21484 319.75854,326.2207 320.01538,330.46191 C 320.76538,342.83545 329.3894,385.95508 327.8894,392.7041 C 326.3894,399.45312 313.64136,418.20117 297.89331,407.32715 C 282.14526,396.45361 276.52075,393.4541 265.27222,394.5791 C 254.02368,395.70361 239.77563,402.07812 239.77563,419.32568 C 239.77563,436.57373 250.27417,449.69727 268.64673,447.82227 C 287.36353,445.9126 317.92163,423.11035 325.63989,452.69678 C 330.1394,469.94434 330.51392,487.19238 330.1394,498.44092 C 329.95825,503.87646 326.09985,518.06592 322.16089,531.28125 C 353.2854,532.73682 386.47095,531.26611 394.2561,529.93701 C 430.30933,523.78174 429.31909,496.09766 412.62866,477.44385 C 406.25464,470.31934 401.75513,455.32129 405.87964,444.82275 C 414.07056,423.97314 458.8064,422.17773 473.37134,438.82324 C 483.86987,450.82178 475.99585,477.44385 468.49683,482.69287 C 453.52222,493.17529 457.22485,516.83008 473.37134,528.06201 C 504.79126,549.91943 572.35913,535.56152 572.35913,535.56152 C 572.35913,535.56152 567.85962,498.06592 567.48462,471.81934 C 567.10962,445.57275 589.60669,450.07227 593.3562,450.07227 C 597.10571,450.07227 604.22974,455.32129 609.47925,459.4458 C 614.72876,463.57031 618.85327,469.94434 630.85181,470.69434 C 677.43726,473.60596 674.58813,420.7373 631.97632,413.32666 C 623.35229,411.82666 614.72876,416.32617 603.10522,424.57519 C 591.48169,432.82422 577.23315,425.32519 570.10913,417.45117 C 566.07788,412.99561 563.8479,360.16406 562.46753,313.56396 C 556.92212,315.89502 549.91821,318.38672 542.10864,320.12939 C 527.97192,323.28467 509.70142,322.47803 500.74292,321.83789 z " style="fill:#f3f3d6;stroke:#000000" id="path2504"/>
|
||||
<path d="M 240.52563,141.86035 C 257.60327,159.6499 243.94507,188.68799 214.65356,190.22949 C 185.09448,191.78516 164.66675,157.17822 190.28589,136.61621 C 200.49585,128.42139 198.05786,114.12158 179.78296,106.98975 C 154.4187,97.091553 90.54419,107.73975 90.54419,107.73975 C 90.54419,107.73975 100.88794,135.11328 101.41772,168.48242 C 101.79272,192.104 68.796875,189.47949 63.172607,186.85498 C 57.54834,184.23047 45.924805,173.73145 37.675781,173.73145 C -14.411865,173.73145 -10.013184,245.84375 39.925537,232.22412 C 48.174316,229.97461 56.42334,220.97559 68.796875,222.47559 C 81.17041,223.9751 87.544434,232.59912 87.544434,246.09766 C 87.544434,252.51709 87.0354,281.24268 86.340576,312.87012 C 119.15894,313.67676 160.60962,314.46582 170.03442,313.58887 C 186.15698,312.08936 195.90601,301.59033 188.40698,293.3418 C 180.90796,285.09277 156.16089,256.59619 179.03296,239.34814 C 201.90503,222.10059 235.65112,231.84912 239.77563,247.22217 C 243.90015,262.59521 240.52563,273.46924 234.90112,279.09326 C 229.27661,284.71777 210.52905,298.96582 221.40259,308.71484 C 232.27661,318.46338 263.77222,330.83691 302.39282,320.71338 C 309.58862,318.82715 315.92114,317.13525 321.58911,315.6377 C 323.17603,307.00635 325.29321,296.99414 324.84595,286.23486 C 324.08374,267.90723 316.34888,247.5708 314.76636,236.34863 C 310.64185,207.10254 349.26196,204.85254 356.38599,211.97656 C 363.51001,219.10107 377.75806,223.6001 382.25757,223.6001 C 419.78296,223.6001 424.61841,168.54297 380.00806,169.98193 C 368.38452,170.35693 357.8855,177.48096 354.88599,178.98096 C 351.88647,180.48096 354.13647,183.48047 336.13843,184.23047 C 318.14087,184.97998 312.14136,171.85693 311.76636,154.23389 C 311.55688,144.39697 315.08423,120.9751 318.24194,102.19775 C 290.37524,101.67725 262.46069,98.968262 254.39868,97.991211 C 233.38013,95.443359 217.17456,117.53662 240.52563,141.86035 z " style="fill:#bebcdb;stroke:#000000" id="path2506"/>
|
||||
<path d="M 325.63989,452.69678 C 317.92163,423.11035 287.36353,445.9126 268.64673,447.82227 C 250.27417,449.69727 239.77563,436.57373 239.77563,419.32568 C 239.77563,402.07812 254.02368,395.70361 265.27222,394.5791 C 276.52075,393.4541 282.14526,396.45361 297.89331,407.32715 C 313.64136,418.20117 326.3894,399.45313 327.8894,392.7041 C 329.3894,385.95508 320.76538,342.83545 320.01538,330.46191 C 319.75855,326.2207 320.56372,321.21484 321.58911,315.6377 C 315.92114,317.13525 309.58862,318.82715 302.39282,320.71338 C 263.77222,330.83691 232.27661,318.46338 221.40259,308.71484 C 210.52905,298.96582 229.27661,284.71777 234.90112,279.09326 C 240.52563,273.46924 243.90015,262.59521 239.77563,247.22217 C 235.65112,231.84912 201.90503,222.10059 179.03296,239.34814 C 156.16089,256.59619 180.90796,285.09277 188.40698,293.3418 C 195.90601,301.59033 186.15698,312.08936 170.03442,313.58887 C 160.60962,314.46582 119.15894,313.67676 86.340576,312.87012 C 85.573975,347.74561 84.581299,386.15088 83.794922,402.07812 C 82.295166,432.44922 109.29175,422.32568 115.66577,420.82568 C 122.04028,419.32568 126.16479,409.57715 143.03735,408.45215 C 185.9231,405.59326 186.09985,466.69629 144.16235,467.69482 C 128.41431,468.06982 113.79126,451.19678 108.16675,447.44727 C 102.54272,443.69775 87.919433,442.94775 83.794922,457.9458 C 82.01709,464.41113 78.118652,481.65137 78.098144,496.18994 C 78.071045,515.38037 82.295166,531.81201 82.295166,531.81201 C 82.295166,531.81201 105.54224,526.5625 149.41187,526.5625 C 193.28149,526.5625 199.65552,547.93506 194.78101,558.80859 C 189.90649,569.68213 181.28296,568.93213 179.40796,583.18066 C 172.7063,634.11133 253.34106,631.08203 249.14917,584.68018 C 247.96948,571.62354 237.16528,571.66699 232.27661,557.68359 C 222.17944,528.80273 244.64966,523.56299 257.39819,524.68799 C 263.59351,525.23437 290.95679,529.73389 320.75757,531.21582 C 321.22437,531.23877 321.69312,531.25928 322.16089,531.28125 C 326.09985,518.06592 329.95825,503.87646 330.1394,498.44092 C 330.51392,487.19238 330.1394,469.94434 325.63989,452.69678 z " style="fill:#d3ea9d;stroke:#000000" id="path2508"/>
|
||||
</g>
|
||||
</svg>
|
||||
<script src="../../y.js"></script>
|
||||
<script src='../../../y-websockets-client/y-websockets-client.js'></script>
|
||||
<script src="../bower_components/d3/d3.js"></script>
|
||||
<script src="./index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,67 +0,0 @@
|
||||
/* global Y, d3 */
|
||||
|
||||
let y = new Y('jigsaw-example', {
|
||||
connector: {
|
||||
name: 'websockets-client',
|
||||
url: 'http://127.0.0.1:1234'
|
||||
}
|
||||
})
|
||||
|
||||
let jigsaw = y.define('jigsaw', Y.Map)
|
||||
window.yJigsaw = y
|
||||
|
||||
var origin // mouse start position - translation of piece
|
||||
var drag = d3.behavior.drag()
|
||||
.on('dragstart', function (params) {
|
||||
// get the translation of the element
|
||||
var translation = d3
|
||||
.select(this)
|
||||
.attr('transform')
|
||||
.slice(10, -1)
|
||||
.split(',')
|
||||
.map(Number)
|
||||
// mouse coordinates
|
||||
var mouse = d3.mouse(this.parentNode)
|
||||
origin = {
|
||||
x: mouse[0] - translation[0],
|
||||
y: mouse[1] - translation[1]
|
||||
}
|
||||
})
|
||||
.on('drag', function () {
|
||||
var mouse = d3.mouse(this.parentNode)
|
||||
var x = mouse[0] - origin.x // =^= mouse - mouse at dragstart + translation at dragstart
|
||||
var y = mouse[1] - origin.y
|
||||
d3.select(this).attr('transform', 'translate(' + x + ',' + y + ')')
|
||||
})
|
||||
.on('dragend', function (piece, i) {
|
||||
// save the current translation of the puzzle piece
|
||||
var mouse = d3.mouse(this.parentNode)
|
||||
var x = mouse[0] - origin.x
|
||||
var y = mouse[1] - origin.y
|
||||
jigsaw.set(piece, {x: x, y: y})
|
||||
})
|
||||
|
||||
var data = ['piece1', 'piece2', 'piece3', 'piece4']
|
||||
var pieces = d3.select(document.querySelector('#puzzle-example')).selectAll('path').data(data)
|
||||
|
||||
pieces
|
||||
.classed('draggable', true)
|
||||
.attr('transform', function (piece) {
|
||||
var translation = piece.get('translation') || {x: 0, y: 0}
|
||||
return 'translate(' + translation.x + ',' + translation.y + ')'
|
||||
}).call(drag)
|
||||
|
||||
data.forEach(function (piece) {
|
||||
jigsaw.observe(function () {
|
||||
// whenever a property of a piece changes, update the translation of the pieces
|
||||
pieces
|
||||
.transition()
|
||||
.attr('transform', function (piece) {
|
||||
var translation = piece.get(piece)
|
||||
if (translation == null || typeof translation.x !== 'number' || typeof translation.y !== 'number') {
|
||||
translation = { x: 0, y: 0 }
|
||||
}
|
||||
return 'translate(' + translation.x + ',' + translation.y + ')'
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,21 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<div id="monacoContainer"></div>
|
||||
<style>
|
||||
#monacoContainer {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
<script src="../../y.js"></script>
|
||||
<script src='../../../y-websockets-client/y-websockets-client.js'></script>
|
||||
<script src="../node_modules/monaco-editor/min/vs/loader.js"></script>
|
||||
<script src="./index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,22 +0,0 @@
|
||||
/* global Y, monaco */
|
||||
|
||||
require.config({ paths: { 'vs': '../node_modules/monaco-editor/min/vs' } })
|
||||
|
||||
let y = new Y('monaco-example', {
|
||||
connector: {
|
||||
name: 'websockets-client',
|
||||
url: 'http://127.0.0.1:1234'
|
||||
}
|
||||
})
|
||||
|
||||
require(['vs/editor/editor.main'], function () {
|
||||
window.yMonaco = y
|
||||
|
||||
// Create Monaco editor
|
||||
var editor = monaco.editor.create(document.getElementById('monacoContainer'), {
|
||||
language: 'javascript'
|
||||
})
|
||||
|
||||
// Bind to y.share.monaco
|
||||
y.define('monaco', Y.Text).bindMonaco(editor)
|
||||
})
|
||||
1650
examples/package-lock.json
generated
1650
examples/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"name": "examples",
|
||||
"version": "0.0.0",
|
||||
"description": "",
|
||||
"scripts": {
|
||||
"dist": "rollup -c",
|
||||
"watch": "rollup -cw"
|
||||
},
|
||||
"author": "Kevin Jahns",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"monaco-editor": "^0.8.3",
|
||||
"rollup": "^0.52.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"standard": "^10.0.2"
|
||||
},
|
||||
"standard": {
|
||||
"ignore": [
|
||||
"bower_components"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<!-- Main quill library -->
|
||||
<script src="../../node_modules/quill/dist/quill.min.js"></script>
|
||||
<link href="../../node_modules/quill/dist/quill.snow.css" rel="stylesheet">
|
||||
<!-- Quill cursors module -->
|
||||
<script src="../../node_modules/quill-cursors/dist/quill-cursors.min.js"></script>
|
||||
<link href="../../node_modules/quill-cursors/dist/quill-cursors.css" rel="stylesheet">
|
||||
<!-- Yjs Library and connector -->
|
||||
<script src="../../y.js"></script>
|
||||
<script src='../../../y-websockets-client/y-websockets-client.js'></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="quill-container">
|
||||
<div id="quill">
|
||||
</div>
|
||||
</div>
|
||||
<script src="./index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,78 +0,0 @@
|
||||
/* global Y, Quill, QuillCursors */
|
||||
|
||||
Quill.register('modules/cursors', QuillCursors)
|
||||
|
||||
let y = new Y('quill-0', {
|
||||
connector: {
|
||||
name: 'websockets-client',
|
||||
url: 'http://127.0.0.1:1234'
|
||||
}
|
||||
})
|
||||
let users = y.define('users', Y.Array)
|
||||
let myUserInfo = new Y.Map()
|
||||
myUserInfo.set('name', 'dada')
|
||||
myUserInfo.set('color', 'red')
|
||||
users.push([myUserInfo])
|
||||
|
||||
let quill = new Quill('#quill-container', {
|
||||
modules: {
|
||||
toolbar: [
|
||||
[{ header: [1, 2, false] }],
|
||||
['bold', 'italic', 'underline'],
|
||||
['image', 'code-block'],
|
||||
[{ color: [] }, { background: [] }], // Snow theme fills in values
|
||||
[{ script: 'sub' }, { script: 'super' }],
|
||||
['link', 'image'],
|
||||
['link', 'code-block'],
|
||||
[{ list: 'ordered' }, { list: 'bullet' }]
|
||||
],
|
||||
cursors: {
|
||||
hideDelay: 500
|
||||
}
|
||||
},
|
||||
placeholder: 'Compose an epic...',
|
||||
theme: 'snow' // or 'bubble'
|
||||
})
|
||||
|
||||
let cursors = quill.getModule('cursors')
|
||||
|
||||
function drawCursors () {
|
||||
cursors.clearCursors()
|
||||
users.map((user, userId) => {
|
||||
if (user !== myUserInfo) {
|
||||
let relativeRange = user.get('range')
|
||||
let lastUpdated = new Date(user.get('last updated'))
|
||||
if (lastUpdated != null && new Date() - lastUpdated < 20000 && relativeRange != null) {
|
||||
let start = Y.utils.fromRelativePosition(y, relativeRange.start).offset
|
||||
let end = Y.utils.fromRelativePosition(y, relativeRange.end).offset
|
||||
let range = { index: start, length: end - start }
|
||||
cursors.setCursor(userId + '', range, user.get('name'), user.get('color'))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
users.observeDeep(drawCursors)
|
||||
drawCursors()
|
||||
|
||||
quill.on('selection-change', function (range) {
|
||||
if (range != null) {
|
||||
myUserInfo.set('range', {
|
||||
start: Y.utils.getRelativePosition(yText, range.index),
|
||||
end: Y.utils.getRelativePosition(yText, range.index + range.length)
|
||||
})
|
||||
} else {
|
||||
myUserInfo.delete('range')
|
||||
}
|
||||
myUserInfo.set('last updated', new Date().toString())
|
||||
})
|
||||
|
||||
let yText = y.define('quill', Y.Text)
|
||||
let quillBinding = new Y.QuillBinding(yText, quill)
|
||||
|
||||
window.quillBinding = quillBinding
|
||||
window.yText = yText
|
||||
window.y = y
|
||||
window.quill = quill
|
||||
window.users = users
|
||||
window.cursors = cursors
|
||||
@@ -1,18 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<!-- Main Quill library -->
|
||||
<script src="../../node_modules/quill/dist/quill.min.js"></script>
|
||||
<link href="../../node_modules/quill/dist/quill.snow.css" rel="stylesheet">
|
||||
<!-- Yjs Library and connector -->
|
||||
<script src="../../y.js"></script>
|
||||
<script src='../../../y-websockets-client/y-websockets-client.js'></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="quill-container">
|
||||
<div id="quill">
|
||||
</div>
|
||||
</div>
|
||||
<script src="./index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,33 +0,0 @@
|
||||
/* global Y, Quill */
|
||||
|
||||
let y = new Y('quill-cursors-0', {
|
||||
connector: {
|
||||
name: 'websockets-client',
|
||||
url: 'http://127.0.0.1:1234'
|
||||
}
|
||||
})
|
||||
|
||||
let quill = new Quill('#quill-container', {
|
||||
modules: {
|
||||
toolbar: [
|
||||
[{ header: [1, 2, false] }],
|
||||
['bold', 'italic', 'underline'],
|
||||
['image', 'code-block'],
|
||||
[{ color: [] }, { background: [] }], // Snow theme fills in values
|
||||
[{ script: 'sub' }, { script: 'super' }],
|
||||
['link', 'image'],
|
||||
['link', 'code-block'],
|
||||
[{ list: 'ordered' }, { list: 'bullet' }]
|
||||
]
|
||||
},
|
||||
placeholder: 'Compose an epic...',
|
||||
theme: 'snow' // or 'bubble'
|
||||
})
|
||||
|
||||
let yText = y.define('quill', Y.Text)
|
||||
|
||||
let quillBinding = new Y.QuillBinding(yText, quill)
|
||||
window.quillBinding = quillBinding
|
||||
window.yText = yText
|
||||
window.y = y
|
||||
window.quill = quill
|
||||
@@ -1,29 +0,0 @@
|
||||
import nodeResolve from 'rollup-plugin-node-resolve'
|
||||
import commonjs from 'rollup-plugin-commonjs'
|
||||
|
||||
var pkg = require('./package.json')
|
||||
|
||||
export default {
|
||||
input: 'yjs-dist.mjs',
|
||||
name: 'Y',
|
||||
output: {
|
||||
file: 'yjs-dist.js',
|
||||
format: 'umd'
|
||||
},
|
||||
plugins: [
|
||||
nodeResolve({
|
||||
main: true,
|
||||
module: true,
|
||||
browser: true
|
||||
}),
|
||||
commonjs()
|
||||
],
|
||||
sourcemap: true,
|
||||
banner: `
|
||||
/**
|
||||
* ${pkg.name} - ${pkg.description}
|
||||
* @version v${pkg.version}
|
||||
* @license ${pkg.license}
|
||||
*/
|
||||
`
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<!-- quill does not include dist files! We are using the hosted version instead -->
|
||||
<!--link rel="stylesheet" href="../bower_components/quill/dist/quill.snow.css" /-->
|
||||
<link href="https://cdn.quilljs.com/1.0.4/quill.snow.css" rel="stylesheet">
|
||||
<link href="//cdnjs.cloudflare.com/ajax/libs/KaTeX/0.5.1/katex.min.css" rel="stylesheet">
|
||||
<link href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.2.0/styles/monokai-sublime.min.css" rel="stylesheet">
|
||||
<style>
|
||||
#quill-container {
|
||||
border: 1px solid gray;
|
||||
box-shadow: 0px 0px 10px gray;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="quill-container">
|
||||
<div id="quill">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/KaTeX/0.5.1/katex.min.js" type="text/javascript"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.2.0/highlight.min.js" type="text/javascript"></script>
|
||||
<script src="https://cdn.quilljs.com/1.0.4/quill.js"></script>
|
||||
<!-- quill does not include dist files! We are using the hosted version instead (see above)
|
||||
<script src="../bower_components/quill/dist/quill.js"></script>
|
||||
-->
|
||||
<script src="../bower_components/yjs/y.js"></script>
|
||||
<script src="./index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,49 +0,0 @@
|
||||
/* global Y, Quill */
|
||||
|
||||
// register yjs service worker
|
||||
if ('serviceWorker' in navigator) {
|
||||
// Register service worker
|
||||
// it is important to copy yjs-sw-template to the root directory!
|
||||
navigator.serviceWorker.register('./yjs-sw-template.js').then(function (reg) {
|
||||
console.log('Yjs service worker registration succeeded. Scope is ' + reg.scope)
|
||||
}).catch(function (err) {
|
||||
console.error('Yjs service worker registration failed with error ' + err)
|
||||
})
|
||||
}
|
||||
|
||||
// initialize a shared object. This function call returns a promise!
|
||||
Y({
|
||||
db: {
|
||||
name: 'memory'
|
||||
},
|
||||
connector: {
|
||||
name: 'serviceworker',
|
||||
room: 'ServiceWorkerExample2'
|
||||
},
|
||||
sourceDir: '/bower_components',
|
||||
share: {
|
||||
richtext: 'Richtext' // y.share.richtext is of type Y.Richtext
|
||||
}
|
||||
}).then(function (y) {
|
||||
window.yServiceWorker = y
|
||||
|
||||
// create quill element
|
||||
window.quill = new Quill('#quill', {
|
||||
modules: {
|
||||
formula: true,
|
||||
syntax: true,
|
||||
toolbar: [
|
||||
[{ size: ['small', false, 'large', 'huge'] }],
|
||||
['bold', 'italic', 'underline'],
|
||||
[{ color: [] }, { background: [] }], // Snow theme fills in values
|
||||
[{ script: 'sub' }, { script: 'super' }],
|
||||
['link', 'image'],
|
||||
['link', 'code-block'],
|
||||
[{ list: 'ordered' }]
|
||||
]
|
||||
},
|
||||
theme: 'snow'
|
||||
})
|
||||
// bind quill to richtext type
|
||||
y.share.richtext.bind(window.quill)
|
||||
})
|
||||
@@ -1,22 +0,0 @@
|
||||
/* eslint-env worker */
|
||||
|
||||
// copy and modify this file
|
||||
|
||||
self.DBConfig = {
|
||||
name: 'indexeddb'
|
||||
}
|
||||
self.ConnectorConfig = {
|
||||
name: 'websockets-client',
|
||||
// url: '..',
|
||||
options: {
|
||||
jsonp: false
|
||||
}
|
||||
}
|
||||
|
||||
importScripts(
|
||||
'/bower_components/yjs/y.js',
|
||||
'/bower_components/y-memory/y-memory.js',
|
||||
'/bower_components/y-indexeddb/y-indexeddb.js',
|
||||
'/bower_components/y-websockets-client/y-websockets-client.js',
|
||||
'/bower_components/y-serviceworker/yjs-sw-include.js'
|
||||
)
|
||||
@@ -1,9 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<textarea style="width:80%;" rows=40 autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"></textarea>
|
||||
<script src="../../y.js"></script>
|
||||
<script src='../../../y-websockets-client/y-websockets-client.js'></script>
|
||||
<script src="./index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,15 +0,0 @@
|
||||
/* global Y */
|
||||
|
||||
let y = new Y('textarea-example', {
|
||||
connector: {
|
||||
name: 'websockets-client',
|
||||
url: 'http://127.0.0.1:1234'
|
||||
}
|
||||
})
|
||||
|
||||
window.yTextarea = y
|
||||
|
||||
// bind the textarea to a shared text element
|
||||
let type = y.define('textarea', Y.Text)
|
||||
let textarea = document.querySelector('textarea')
|
||||
window.binding = new Y.TextareaBinding(type, textarea)
|
||||
@@ -1,43 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
</head>
|
||||
<!-- jquery is not required for YXml. It is just here for convenience, and to test batch operations. -->
|
||||
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
|
||||
<script src="../../y.js"></script>
|
||||
<script src='../../../y-websockets-client/y-websockets-client.js'></script>
|
||||
<script src="./index.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1> Shared DOM Example </h1>
|
||||
<p> Use native DOM function or jQuery to manipulate the shared DOM (window.sharedDom). </p>
|
||||
<div class="command">
|
||||
<button type="button">Execute</button>
|
||||
<input type="text" value='$(sharedDom).append("<h3>Appended headline</h3>")' size="40"/>
|
||||
</div>
|
||||
<div class="command">
|
||||
<button type="button">Execute</button>
|
||||
<input type="text" value='$(sharedDom).attr("align","right")' size="40"/>
|
||||
</div>
|
||||
<div class="command">
|
||||
<button type="button">Execute</button>
|
||||
<input type="text" value='$(sharedDom).attr("style","color:blue;")' size="40"/>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
/* global $ */
|
||||
var commands = document.querySelectorAll('.command')
|
||||
Array.prototype.forEach.call(commands, function (command) {
|
||||
var execute = function () {
|
||||
// eslint-disable-next-line no-eval
|
||||
eval(command.querySelector('input').value)
|
||||
}
|
||||
command.querySelector('button').onclick = execute
|
||||
$(command.querySelector('input')).keyup(function (e) {
|
||||
if (e.keyCode === 13) {
|
||||
execute()
|
||||
}
|
||||
})
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,13 +0,0 @@
|
||||
/* global Y */
|
||||
|
||||
let y = new Y('xml-example', {
|
||||
connector: {
|
||||
name: 'websockets-client',
|
||||
url: 'http://127.0.0.1:1234'
|
||||
}
|
||||
})
|
||||
|
||||
window.yXml = y
|
||||
// bind xml type to a dom, and put it in body
|
||||
window.sharedDom = y.define('xml', Y.XmlElement).toDom()
|
||||
document.body.appendChild(window.sharedDom)
|
||||
@@ -1,9 +0,0 @@
|
||||
|
||||
import Y from '../src/Y.js'
|
||||
import yWebsocketsClient from '../../y-websockets-client/src/y-websockets-client.js'
|
||||
import extendYIndexedDBPersistence from '../../y-indexeddb/src/y-indexeddb.js'
|
||||
|
||||
Y.extend(yWebsocketsClient)
|
||||
extendYIndexedDBPersistence(Y)
|
||||
|
||||
export default Y
|
||||
7940
package-lock.json
generated
7940
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
121
package.json
121
package.json
@@ -1,78 +1,89 @@
|
||||
{
|
||||
"name": "yjs",
|
||||
"version": "13.0.0-58",
|
||||
"description": "A framework for real-time p2p shared editing on any data",
|
||||
"main": "./y.node.js",
|
||||
"browser": "./y.js",
|
||||
"module": "./src/y.js",
|
||||
"version": "13.5.14",
|
||||
"description": "Shared Editing Library",
|
||||
"main": "./dist/yjs.cjs",
|
||||
"module": "./dist/yjs.mjs",
|
||||
"types": "./dist/src/index.d.ts",
|
||||
"sideEffects": false,
|
||||
"funding": {
|
||||
"type": "GitHub Sponsors ❤",
|
||||
"url": "https://github.com/sponsors/dmonad"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "npm run lint",
|
||||
"debug": "concurrently 'rollup -wc rollup.test.js' 'cutest-serve y.test.js -o'",
|
||||
"lint": "standard",
|
||||
"docs": "esdoc",
|
||||
"serve-docs": "npm run docs && serve ./docs/",
|
||||
"dist": "rollup -c rollup.browser.js; rollup -c rollup.node.js",
|
||||
"watch": "concurrently 'rollup -wc rollup.browser.js' 'rollup -wc rollup.node.js'",
|
||||
"postversion": "npm run dist",
|
||||
"postpublish": "tag-dist-files --overwrite-existing-tag"
|
||||
"test": "npm run dist && node ./dist/tests.cjs --repetition-time 50",
|
||||
"test-extensive": "npm run lint && npm run dist && node ./dist/tests.cjs --production --repetition-time 10000",
|
||||
"dist": "rm -rf dist && rollup -c && tsc",
|
||||
"watch": "rollup -wc",
|
||||
"lint": "markdownlint README.md && standard && tsc",
|
||||
"docs": "rm -rf docs; jsdoc --configure ./.jsdoc.json --verbose --readme ./README.md --package ./package.json || true",
|
||||
"serve-docs": "npm run docs && http-server ./docs/",
|
||||
"preversion": "npm run lint && PRODUCTION=1 npm run dist && npm run docs && node ./dist/tests.cjs --repetition-time 1000 && test -e dist/src/index.d.ts && test -e dist/yjs.cjs && test -e dist/yjs.cjs",
|
||||
"debug": "concurrently 'http-server -o test.html' 'npm run watch'",
|
||||
"trace-deopt": "clear && rollup -c && node --trace-deopt dist/test.cjs",
|
||||
"trace-opt": "clear && rollup -c && node --trace-opt dist/test.cjs",
|
||||
"postinstall": "node ./sponsor-y.js"
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/yjs.mjs",
|
||||
"require": "./dist/yjs.cjs"
|
||||
},
|
||||
"./src/index.js": "./src/index.js",
|
||||
"./tests/testHelper.js": "./tests/testHelper.js",
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"files": [
|
||||
"y.*",
|
||||
"src/*",
|
||||
".esdoc.json",
|
||||
"docs/*"
|
||||
"dist/yjs.*",
|
||||
"dist/src",
|
||||
"src",
|
||||
"tests/testHelper.js",
|
||||
"sponsor-y.js"
|
||||
],
|
||||
"dictionaries": {
|
||||
"test": "tests"
|
||||
},
|
||||
"standard": {
|
||||
"ignore": [
|
||||
"/y.js",
|
||||
"/y.js.map"
|
||||
"/dist",
|
||||
"/node_modules",
|
||||
"/docs"
|
||||
]
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/y-js/yjs.git"
|
||||
"url": "https://github.com/yjs/yjs.git"
|
||||
},
|
||||
"keywords": [
|
||||
"Yjs",
|
||||
"OT",
|
||||
"Collaboration",
|
||||
"Synchronization",
|
||||
"ShareJS",
|
||||
"Coweb",
|
||||
"Concurrency"
|
||||
"CRDT",
|
||||
"offline",
|
||||
"offline-first",
|
||||
"shared-editing",
|
||||
"concurrency",
|
||||
"collaboration"
|
||||
],
|
||||
"author": "Kevin Jahns",
|
||||
"email": "kevin.jahns@rwth-aachen.de",
|
||||
"email": "kevin.jahns@protonmail.com",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/y-js/yjs/issues"
|
||||
},
|
||||
"homepage": "http://y-js.org",
|
||||
"devDependencies": {
|
||||
"babel-cli": "^6.24.1",
|
||||
"babel-plugin-external-helpers": "^6.22.0",
|
||||
"babel-plugin-transform-regenerator": "^6.24.1",
|
||||
"babel-plugin-transform-runtime": "^6.23.0",
|
||||
"babel-preset-latest": "^6.24.1",
|
||||
"chance": "^1.0.9",
|
||||
"concurrently": "^3.4.0",
|
||||
"cutest": "^0.1.9",
|
||||
"esdoc": "^1.0.4",
|
||||
"esdoc-standard-plugin": "^1.0.0",
|
||||
"quill": "^1.3.5",
|
||||
"quill-cursors": "^1.0.2",
|
||||
"rollup-plugin-babel": "^2.7.1",
|
||||
"rollup-plugin-commonjs": "^8.0.2",
|
||||
"rollup-plugin-inject": "^2.0.0",
|
||||
"rollup-plugin-multi-entry": "^2.0.1",
|
||||
"rollup-plugin-node-resolve": "^3.0.0",
|
||||
"rollup-plugin-uglify": "^1.0.2",
|
||||
"rollup-regenerator-runtime": "^6.23.1",
|
||||
"rollup-watch": "^3.2.2",
|
||||
"standard": "^10.0.2",
|
||||
"tag-dist-files": "^0.1.6"
|
||||
"url": "https://github.com/yjs/yjs/issues"
|
||||
},
|
||||
"homepage": "https://docs.yjs.dev",
|
||||
"dependencies": {
|
||||
"debug": "^2.6.8"
|
||||
"lib0": "^0.2.42"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-commonjs": "^17.0.0",
|
||||
"@rollup/plugin-node-resolve": "^11.2.1",
|
||||
"concurrently": "^3.6.1",
|
||||
"http-server": "^0.12.3",
|
||||
"jsdoc": "^3.6.7",
|
||||
"markdownlint-cli": "^0.23.2",
|
||||
"rollup": "^2.58.0",
|
||||
"standard": "^16.0.4",
|
||||
"tui-jsdoc-template": "^1.2.2",
|
||||
"typescript": "^4.4.4",
|
||||
"y-protocols": "^1.0.5"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
import babel from 'rollup-plugin-babel'
|
||||
import uglify from 'rollup-plugin-uglify'
|
||||
import nodeResolve from 'rollup-plugin-node-resolve'
|
||||
import commonjs from 'rollup-plugin-commonjs'
|
||||
var pkg = require('./package.json')
|
||||
|
||||
export default {
|
||||
input: 'src/Y.dist.js',
|
||||
name: 'Y',
|
||||
sourcemap: true,
|
||||
output: {
|
||||
file: 'y.js',
|
||||
format: 'umd'
|
||||
},
|
||||
plugins: [
|
||||
nodeResolve({
|
||||
main: true,
|
||||
module: true,
|
||||
browser: true
|
||||
}),
|
||||
commonjs(),
|
||||
babel(),
|
||||
uglify({
|
||||
mangle: {
|
||||
except: ['YMap', 'Y', 'YArray', 'YText', 'YXmlHook', 'YXmlFragment', 'YXmlElement', 'YXmlEvent', 'YXmlText', 'YEvent', 'YArrayEvent', 'YMapEvent', 'Type', 'Delete', 'ItemJSON', 'ItemString', 'Item']
|
||||
},
|
||||
output: {
|
||||
comments: function (node, comment) {
|
||||
var text = comment.value
|
||||
var type = comment.type
|
||||
if (type === 'comment2') {
|
||||
// multiline comment
|
||||
return /@license/i.test(text)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
],
|
||||
banner: `
|
||||
/**
|
||||
* ${pkg.name} - ${pkg.description}
|
||||
* @version v${pkg.version}
|
||||
* @license ${pkg.license}
|
||||
*/
|
||||
`
|
||||
}
|
||||
94
rollup.config.js
Normal file
94
rollup.config.js
Normal file
@@ -0,0 +1,94 @@
|
||||
import nodeResolve from '@rollup/plugin-node-resolve'
|
||||
import commonjs from '@rollup/plugin-commonjs'
|
||||
|
||||
const localImports = process.env.LOCALIMPORTS
|
||||
|
||||
const customModules = new Set([
|
||||
'y-websocket',
|
||||
'y-codemirror',
|
||||
'y-ace',
|
||||
'y-textarea',
|
||||
'y-quill',
|
||||
'y-dom',
|
||||
'y-prosemirror'
|
||||
])
|
||||
/**
|
||||
* @type {Set<any>}
|
||||
*/
|
||||
const customLibModules = new Set([
|
||||
'lib0',
|
||||
'y-protocols'
|
||||
])
|
||||
const debugResolve = {
|
||||
resolveId (importee) {
|
||||
if (importee === 'yjs') {
|
||||
return `${process.cwd()}/src/index.js`
|
||||
}
|
||||
if (localImports) {
|
||||
if (customModules.has(importee.split('/')[0])) {
|
||||
return `${process.cwd()}/../${importee}/src/${importee}.js`
|
||||
}
|
||||
if (customLibModules.has(importee.split('/')[0])) {
|
||||
return `${process.cwd()}/../${importee}`
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
export default [{
|
||||
input: './src/index.js',
|
||||
output: {
|
||||
name: 'Y',
|
||||
file: 'dist/yjs.cjs',
|
||||
format: 'cjs',
|
||||
sourcemap: true,
|
||||
paths: path => {
|
||||
if (/^lib0\//.test(path)) {
|
||||
return `lib0/dist/${path.slice(5)}.cjs`
|
||||
}
|
||||
return path
|
||||
}
|
||||
},
|
||||
external: id => /^lib0\//.test(id)
|
||||
}, {
|
||||
input: './src/index.js',
|
||||
output: {
|
||||
name: 'Y',
|
||||
file: 'dist/yjs.mjs',
|
||||
format: 'esm',
|
||||
sourcemap: true
|
||||
},
|
||||
external: id => /^lib0\//.test(id)
|
||||
}, {
|
||||
input: './tests/index.js',
|
||||
output: {
|
||||
name: 'test',
|
||||
file: 'dist/tests.js',
|
||||
format: 'iife',
|
||||
sourcemap: true
|
||||
},
|
||||
plugins: [
|
||||
debugResolve,
|
||||
nodeResolve({
|
||||
mainFields: ['module', 'browser', 'main']
|
||||
}),
|
||||
commonjs()
|
||||
]
|
||||
}, {
|
||||
input: './tests/index.js',
|
||||
output: {
|
||||
name: 'test',
|
||||
file: 'dist/tests.cjs',
|
||||
format: 'cjs',
|
||||
sourcemap: true
|
||||
},
|
||||
plugins: [
|
||||
debugResolve,
|
||||
nodeResolve({
|
||||
mainFields: ['module', 'main']
|
||||
}),
|
||||
commonjs()
|
||||
],
|
||||
external: ['isomorphic.js']
|
||||
}]
|
||||
@@ -1,28 +0,0 @@
|
||||
import nodeResolve from 'rollup-plugin-node-resolve'
|
||||
import commonjs from 'rollup-plugin-commonjs'
|
||||
var pkg = require('./package.json')
|
||||
|
||||
export default {
|
||||
input: 'src/Y.dist.js',
|
||||
nameame: 'Y',
|
||||
sourcemap: true,
|
||||
output: {
|
||||
file: 'y.node.js',
|
||||
format: 'cjs'
|
||||
},
|
||||
plugins: [
|
||||
nodeResolve({
|
||||
main: true,
|
||||
module: true,
|
||||
browser: true
|
||||
}),
|
||||
commonjs()
|
||||
],
|
||||
banner: `
|
||||
/**
|
||||
* ${pkg.name} - ${pkg.description}
|
||||
* @version v${pkg.version}
|
||||
* @license ${pkg.license}
|
||||
*/
|
||||
`
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
import nodeResolve from 'rollup-plugin-node-resolve'
|
||||
import commonjs from 'rollup-plugin-commonjs'
|
||||
import multiEntry from 'rollup-plugin-multi-entry'
|
||||
|
||||
export default {
|
||||
input: 'test/index.js',
|
||||
name: 'y-tests',
|
||||
sourcemap: true,
|
||||
output: {
|
||||
file: 'y.test.js',
|
||||
format: 'umd'
|
||||
},
|
||||
plugins: [
|
||||
multiEntry(),
|
||||
nodeResolve({
|
||||
main: true,
|
||||
module: true,
|
||||
browser: true
|
||||
}),
|
||||
commonjs()
|
||||
]
|
||||
}
|
||||
12
sponsor-y.js
Normal file
12
sponsor-y.js
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
try {
|
||||
const log = require('lib0/dist/logging.cjs')
|
||||
|
||||
log.print()
|
||||
log.print(log.BOLD, log.GREEN, log.BOLD, 'Thank you for using Yjs ', log.RED, '❤\n')
|
||||
log.print(
|
||||
log.GREY,
|
||||
'The project has grown considerably in the past year. Too much for me to maintain\nin my spare time. Several companies built their products with Yjs.\nYet, this project receives very little funding. Yjs is far from done. I want to\ncreate more awesome extensions and work on the growing number of open issues.\n', log.BOLD, 'Dear user, the future of this project entirely depends on you.\n')
|
||||
log.print(log.BLUE, log.BOLD, 'Please start funding the project now: https://github.com/sponsors/dmonad \n')
|
||||
log.print(log.GREY, '(This message will be removed when I achieved my funding goal)\n\n')
|
||||
} catch (e) { }
|
||||
@@ -1,47 +0,0 @@
|
||||
|
||||
import { createMutualExclude } from '../Util/mutualExclude.js'
|
||||
|
||||
/**
|
||||
* Abstract class for bindings.
|
||||
*
|
||||
* A binding handles data binding from a Yjs type to a data object. For example,
|
||||
* you can bind a Quill editor instance to a YText instance with the `QuillBinding` class.
|
||||
*
|
||||
* It is expected that a concrete implementation accepts two parameters
|
||||
* (type and binding target).
|
||||
*
|
||||
* @example
|
||||
* const quill = new Quill(document.createElement('div'))
|
||||
* const type = y.define('quill', Y.Text)
|
||||
* const binding = new Y.QuillBinding(quill, type)
|
||||
*
|
||||
*/
|
||||
export default class Binding {
|
||||
/**
|
||||
* @param {YType} type Yjs type.
|
||||
* @param {any} target Binding Target.
|
||||
*/
|
||||
constructor (type, target) {
|
||||
/**
|
||||
* The Yjs type that is bound to `target`
|
||||
* @type {YType}
|
||||
*/
|
||||
this.type = type
|
||||
/**
|
||||
* The target that `type` is bound to.
|
||||
* @type {*}
|
||||
*/
|
||||
this.target = target
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
this._mutualExclude = createMutualExclude()
|
||||
}
|
||||
/**
|
||||
* Remove all data observers (both from the type and the target).
|
||||
*/
|
||||
destroy () {
|
||||
this.type = null
|
||||
this.target = null
|
||||
}
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
/* global MutationObserver */
|
||||
|
||||
import Binding from '../Binding.js'
|
||||
import { createAssociation, removeAssociation } from './util.js'
|
||||
import { beforeTransactionSelectionFixer, afterTransactionSelectionFixer } from './selection.js'
|
||||
import { defaultFilter, applyFilterOnType } from './filter.js'
|
||||
import typeObserver from './typeObserver.js'
|
||||
import domObserver from './domObserver.js'
|
||||
|
||||
/**
|
||||
* A binding that binds the children of a YXmlFragment to a DOM element.
|
||||
*
|
||||
* This binding is automatically destroyed when its parent is deleted.
|
||||
*
|
||||
* @example
|
||||
* const div = document.createElement('div')
|
||||
* const type = y.define('xml', Y.XmlFragment)
|
||||
* const binding = new Y.QuillBinding(type, div)
|
||||
*
|
||||
*/
|
||||
export default class DomBinding extends Binding {
|
||||
/**
|
||||
* @param {YXmlFragment} type The bind source. This is the ultimate source of
|
||||
* truth.
|
||||
* @param {Element} target The bind target. Mirrors the target.
|
||||
* @param {Object} [opts] Optional configurations
|
||||
|
||||
* @param {FilterFunction} [opts.filter=defaultFilter] The filter function to use.
|
||||
*/
|
||||
constructor (type, target, opts = {}) {
|
||||
// Binding handles textType as this.type and domTextarea as this.target
|
||||
super(type, target)
|
||||
this.opts = opts
|
||||
opts.document = opts.document || document
|
||||
opts.hooks = opts.hooks || {}
|
||||
this.scrollingElement = opts.scrollingElement || null
|
||||
/**
|
||||
* Maps each DOM element to the type that it is associated with.
|
||||
* @type {Map}
|
||||
*/
|
||||
this.domToType = new Map()
|
||||
/**
|
||||
* Maps each YXml type to the DOM element that it is associated with.
|
||||
* @type {Map}
|
||||
*/
|
||||
this.typeToDom = new Map()
|
||||
/**
|
||||
* Defines which DOM attributes and elements to filter out.
|
||||
* Also filters remote changes.
|
||||
* @type {FilterFunction}
|
||||
*/
|
||||
this.filter = opts.filter || defaultFilter
|
||||
// set initial value
|
||||
target.innerHTML = ''
|
||||
type.forEach(child => {
|
||||
target.insertBefore(child.toDom(opts.document, opts.hooks, this), null)
|
||||
})
|
||||
this._typeObserver = typeObserver.bind(this)
|
||||
this._domObserver = (mutations) => {
|
||||
domObserver.call(this, mutations, opts.document)
|
||||
}
|
||||
type.observeDeep(this._typeObserver)
|
||||
this._mutationObserver = new MutationObserver(this._domObserver)
|
||||
this._mutationObserver.observe(target, {
|
||||
childList: true,
|
||||
attributes: true,
|
||||
characterData: true,
|
||||
subtree: true
|
||||
})
|
||||
const y = type._y
|
||||
// Force flush dom changes before Type changes are applied (they might
|
||||
// modify the dom)
|
||||
this._beforeTransactionHandler = (y, transaction, remote) => {
|
||||
this._domObserver(this._mutationObserver.takeRecords())
|
||||
beforeTransactionSelectionFixer(y, this, transaction, remote)
|
||||
}
|
||||
y.on('beforeTransaction', this._beforeTransactionHandler)
|
||||
this._afterTransactionHandler = (y, transaction, remote) => {
|
||||
afterTransactionSelectionFixer(y, this, transaction, remote)
|
||||
// remove associations
|
||||
// TODO: this could be done more efficiently
|
||||
// e.g. Always delete using the following approach, or removeAssociation
|
||||
// in dom/type-observer..
|
||||
transaction.deletedStructs.forEach(type => {
|
||||
const dom = this.typeToDom.get(type)
|
||||
if (dom !== undefined) {
|
||||
removeAssociation(this, dom, type)
|
||||
}
|
||||
})
|
||||
}
|
||||
y.on('afterTransaction', this._afterTransactionHandler)
|
||||
// Before calling observers, apply dom filter to all changed and new types.
|
||||
this._beforeObserverCallsHandler = (y, transaction) => {
|
||||
// Apply dom filter to new and changed types
|
||||
transaction.changedTypes.forEach((subs, type) => {
|
||||
// Only check attributes. New types are filtered below.
|
||||
if ((subs.size > 1 || (subs.size === 1 && subs.has(null) === false))) {
|
||||
applyFilterOnType(y, this, type)
|
||||
}
|
||||
})
|
||||
transaction.newTypes.forEach(type => {
|
||||
applyFilterOnType(y, this, type)
|
||||
})
|
||||
}
|
||||
y.on('beforeObserverCalls', this._beforeObserverCallsHandler)
|
||||
createAssociation(this, target, type)
|
||||
}
|
||||
|
||||
/**
|
||||
* NOTE: currently does not apply filter to existing elements!
|
||||
* @param {FilterFunction} filter The filter function to use from now on.
|
||||
*/
|
||||
setFilter (filter) {
|
||||
this.filter = filter
|
||||
// TODO: apply filter to all elements
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all properties that are handled by this class.
|
||||
*/
|
||||
destroy () {
|
||||
this.domToType = null
|
||||
this.typeToDom = null
|
||||
this.type.unobserve(this._typeObserver)
|
||||
this._mutationObserver.disconnect()
|
||||
const y = this.type._y
|
||||
y.off('beforeTransaction', this._beforeTransactionHandler)
|
||||
y.off('beforeObserverCalls', this._beforeObserverCallsHandler)
|
||||
y.off('afterObserverCalls', this._afterObserverCallsHandler)
|
||||
y.off('afterTransaction', this._afterTransactionHandler)
|
||||
super.destroy()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A filter defines which elements and attributes to share.
|
||||
* Return null if the node should be filtered. Otherwise return the Map of
|
||||
* accepted attributes.
|
||||
*
|
||||
* @typedef {function(nodeName: String, attrs: Map): Map|null} FilterFunction
|
||||
*/
|
||||
@@ -1,145 +0,0 @@
|
||||
|
||||
import YXmlHook from '../../Types/YXml/YXmlHook.js'
|
||||
import {
|
||||
iterateUntilUndeleted,
|
||||
removeAssociation,
|
||||
insertNodeHelper } from './util.js'
|
||||
import diff from '../../Util/simpleDiff.js'
|
||||
import YXmlFragment from '../../Types/YXml/YXmlFragment.js'
|
||||
|
||||
/**
|
||||
* 1. Check if any of the nodes was deleted
|
||||
* 2. Iterate over the children.
|
||||
* 2.1 If a node exists that is not yet bound to a type, insert a new node
|
||||
* 2.2 If _contents.length < dom.childNodes.length, fill the
|
||||
* rest of _content with childNodes
|
||||
* 2.3 If a node was moved, delete it and
|
||||
* recreate a new yxml element that is bound to that node.
|
||||
* You can detect that a node was moved because expectedId
|
||||
* !== actualId in the list
|
||||
* @private
|
||||
*/
|
||||
function applyChangesFromDom (binding, dom, yxml, _document) {
|
||||
if (yxml == null || yxml === false || yxml.constructor === YXmlHook) {
|
||||
return
|
||||
}
|
||||
const y = yxml._y
|
||||
const knownChildren = new Set()
|
||||
for (let i = dom.childNodes.length - 1; i >= 0; i--) {
|
||||
const type = binding.domToType.get(dom.childNodes[i])
|
||||
if (type !== undefined && type !== false) {
|
||||
knownChildren.add(type)
|
||||
}
|
||||
}
|
||||
// 1. Check if any of the nodes was deleted
|
||||
yxml.forEach(function (childType) {
|
||||
if (knownChildren.has(childType) === false) {
|
||||
childType._delete(y)
|
||||
removeAssociation(binding, binding.typeToDom.get(childType), childType)
|
||||
}
|
||||
})
|
||||
// 2. iterate
|
||||
const childNodes = dom.childNodes
|
||||
const len = childNodes.length
|
||||
let prevExpectedType = null
|
||||
let expectedType = iterateUntilUndeleted(yxml._start)
|
||||
for (let domCnt = 0; domCnt < len; domCnt++) {
|
||||
const childNode = childNodes[domCnt]
|
||||
const childType = binding.domToType.get(childNode)
|
||||
if (childType !== undefined) {
|
||||
if (childType === false) {
|
||||
// should be ignored or is going to be deleted
|
||||
continue
|
||||
}
|
||||
if (expectedType !== null) {
|
||||
if (expectedType !== childType) {
|
||||
// 2.3 Not expected node
|
||||
if (childType._parent !== yxml) {
|
||||
// child was moved from another parent
|
||||
// childType is going to be deleted by its previous parent
|
||||
removeAssociation(binding, childNode, childType)
|
||||
} else {
|
||||
// child was moved to a different position.
|
||||
removeAssociation(binding, childNode, childType)
|
||||
childType._delete(y)
|
||||
}
|
||||
prevExpectedType = insertNodeHelper(yxml, prevExpectedType, childNode, _document, binding)
|
||||
} else {
|
||||
// Found expected node. Continue.
|
||||
prevExpectedType = expectedType
|
||||
expectedType = iterateUntilUndeleted(expectedType._right)
|
||||
}
|
||||
} else {
|
||||
// 2.2 Fill _content with child nodes
|
||||
prevExpectedType = insertNodeHelper(yxml, prevExpectedType, childNode, _document, binding)
|
||||
}
|
||||
} else {
|
||||
// 2.1 A new node was found
|
||||
prevExpectedType = insertNodeHelper(yxml, prevExpectedType, childNode, _document, binding)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
export default function domObserver (mutations, _document) {
|
||||
this._mutualExclude(() => {
|
||||
this.type._y.transact(() => {
|
||||
let diffChildren = new Set()
|
||||
mutations.forEach(mutation => {
|
||||
const dom = mutation.target
|
||||
const yxml = this.domToType.get(dom)
|
||||
if (yxml === false || yxml === undefined || yxml.constructor === YXmlHook) {
|
||||
// dom element is filtered
|
||||
if (yxml === undefined) { // In case yxml is undefined, we double check if we forgot to bind the dom
|
||||
console.error('Yjs DomBinding: Reconstructing DomBinding, please report how to reproduce this.')
|
||||
let parent
|
||||
let yParent
|
||||
do {
|
||||
parent = dom.parentNode
|
||||
yParent = this.domToType.get(parent)
|
||||
} while (yParent === undefined)
|
||||
if (yParent !== false && yParent !== undefined && yParent.constructor !== YXmlHook) {
|
||||
diffChildren.add(parent)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
switch (mutation.type) {
|
||||
case 'characterData':
|
||||
var change = diff(yxml.toString(), dom.nodeValue)
|
||||
yxml.delete(change.pos, change.remove)
|
||||
yxml.insert(change.pos, change.insert)
|
||||
break
|
||||
case 'attributes':
|
||||
if (yxml.constructor === YXmlFragment) {
|
||||
break
|
||||
}
|
||||
let name = mutation.attributeName
|
||||
let val = dom.getAttribute(name)
|
||||
// check if filter accepts attribute
|
||||
let attributes = new Map()
|
||||
attributes.set(name, val)
|
||||
if (yxml.constructor !== YXmlFragment && this.filter(dom.nodeName, attributes).size > 0) {
|
||||
if (yxml.getAttribute(name) !== val) {
|
||||
if (val == null) {
|
||||
yxml.removeAttribute(name)
|
||||
} else {
|
||||
yxml.setAttribute(name, val)
|
||||
}
|
||||
}
|
||||
}
|
||||
break
|
||||
case 'childList':
|
||||
diffChildren.add(mutation.target)
|
||||
break
|
||||
}
|
||||
})
|
||||
for (let dom of diffChildren) {
|
||||
const yxml = this.domToType.get(dom)
|
||||
applyChangesFromDom(this, dom, yxml, _document)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
|
||||
import { YXmlText, YXmlElement, YXmlHook } from '../../Types/YXml/YXml.js'
|
||||
import { createAssociation, domsToTypes } from './util.js'
|
||||
import { filterDomAttributes, defaultFilter } from './filter.js'
|
||||
|
||||
/**
|
||||
* Creates a Yjs type (YXml) based on the contents of a DOM Element.
|
||||
*
|
||||
* @param {Element|TextNode} element The DOM Element
|
||||
* @param {?Document} _document Optional. Provide the global document object
|
||||
* @param {Hooks} [hooks = {}] Optional. Set of Yjs Hooks
|
||||
* @param {Filter} [filter=defaultFilter] Optional. Dom element filter
|
||||
* @param {?DomBinding} binding Warning: This property is for internal use only!
|
||||
* @return {YXmlElement | YXmlText}
|
||||
*/
|
||||
export default function domToType (element, _document = document, hooks = {}, filter = defaultFilter, binding) {
|
||||
let type
|
||||
switch (element.nodeType) {
|
||||
case _document.ELEMENT_NODE:
|
||||
let hookName = null
|
||||
let hook
|
||||
// configure `hookName !== undefined` if element is a hook.
|
||||
if (element.hasAttribute('data-yjs-hook')) {
|
||||
hookName = element.getAttribute('data-yjs-hook')
|
||||
hook = hooks[hookName]
|
||||
if (hook === undefined) {
|
||||
console.error(`Unknown hook "${hookName}". Deleting yjsHook dataset property.`)
|
||||
delete element.removeAttribute('data-yjs-hook')
|
||||
hookName = null
|
||||
}
|
||||
}
|
||||
if (hookName === null) {
|
||||
// Not a hook
|
||||
const attrs = filterDomAttributes(element, filter)
|
||||
if (attrs === null) {
|
||||
type = false
|
||||
} else {
|
||||
type = new YXmlElement(element.nodeName)
|
||||
attrs.forEach((val, key) => {
|
||||
type.setAttribute(key, val)
|
||||
})
|
||||
type.insert(0, domsToTypes(element.childNodes, document, hooks, filter, binding))
|
||||
}
|
||||
} else {
|
||||
// Is a hook
|
||||
type = new YXmlHook(hookName)
|
||||
hook.fillType(element, type)
|
||||
}
|
||||
break
|
||||
case _document.TEXT_NODE:
|
||||
type = new YXmlText()
|
||||
type.insert(0, element.nodeValue)
|
||||
break
|
||||
default:
|
||||
throw new Error('Can\'t transform this node type to a YXml type!')
|
||||
}
|
||||
createAssociation(binding, element, type)
|
||||
return type
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
import isParentOf from '../../Util/isParentOf.js'
|
||||
|
||||
/**
|
||||
* Default filter method (does nothing).
|
||||
*
|
||||
* @param {String} nodeName The nodeName of the element
|
||||
* @param {Map} attrs Map of key-value pairs that are attributes of the node.
|
||||
* @return {Map | null} The allowed attributes or null, if the element should be
|
||||
* filtered.
|
||||
*/
|
||||
export function defaultFilter (nodeName, attrs) {
|
||||
// TODO: implement basic filter that filters out dangerous properties!
|
||||
return attrs
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export function filterDomAttributes (dom, filter) {
|
||||
const attrs = new Map()
|
||||
for (let i = dom.attributes.length - 1; i >= 0; i--) {
|
||||
const attr = dom.attributes[i]
|
||||
attrs.set(attr.name, attr.value)
|
||||
}
|
||||
return filter(dom.nodeName, attrs)
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies a filter on a type.
|
||||
*
|
||||
* @param {Y} y The Yjs instance.
|
||||
* @param {DomBinding} binding The DOM binding instance that has the dom filter.
|
||||
* @param {YXmlElement | YXmlFragment } type The type to apply the filter to.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
export function applyFilterOnType (y, binding, type) {
|
||||
if (isParentOf(binding.type, type)) {
|
||||
const nodeName = type.nodeName
|
||||
let attributes = new Map()
|
||||
if (type.getAttributes !== undefined) {
|
||||
let attrs = type.getAttributes()
|
||||
for (let key in attrs) {
|
||||
attributes.set(key, attrs[key])
|
||||
}
|
||||
}
|
||||
const filteredAttributes = binding.filter(nodeName, new Map(attributes))
|
||||
if (filteredAttributes === null) {
|
||||
type._delete(y)
|
||||
} else {
|
||||
// iterate original attributes
|
||||
attributes.forEach((value, key) => {
|
||||
// delete all attributes that are not in filteredAttributes
|
||||
if (filteredAttributes.has(key) === false) {
|
||||
type.removeAttribute(key)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
/* globals getSelection */
|
||||
|
||||
import { getRelativePosition, fromRelativePosition } from '../../Util/relativePosition.js'
|
||||
|
||||
let browserSelection = null
|
||||
let relativeSelection = null
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
export let beforeTransactionSelectionFixer
|
||||
if (typeof getSelection !== 'undefined') {
|
||||
beforeTransactionSelectionFixer = function _beforeTransactionSelectionFixer (y, domBinding, transaction, remote) {
|
||||
if (!remote) {
|
||||
return
|
||||
}
|
||||
relativeSelection = { from: null, to: null, fromY: null, toY: null }
|
||||
browserSelection = getSelection()
|
||||
const anchorNode = browserSelection.anchorNode
|
||||
const anchorNodeType = domBinding.domToType.get(anchorNode)
|
||||
if (anchorNode !== null && anchorNodeType !== undefined) {
|
||||
relativeSelection.from = getRelativePosition(anchorNodeType, browserSelection.anchorOffset)
|
||||
relativeSelection.fromY = anchorNodeType._y
|
||||
}
|
||||
const focusNode = browserSelection.focusNode
|
||||
const focusNodeType = domBinding.domToType.get(focusNode)
|
||||
if (focusNode !== null && focusNodeType !== undefined) {
|
||||
relativeSelection.to = getRelativePosition(focusNodeType, browserSelection.focusOffset)
|
||||
relativeSelection.toY = focusNodeType._y
|
||||
}
|
||||
}
|
||||
} else {
|
||||
beforeTransactionSelectionFixer = function _fakeBeforeTransactionSelectionFixer () {}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
export function afterTransactionSelectionFixer (y, domBinding, transaction, remote) {
|
||||
if (relativeSelection === null || !remote) {
|
||||
return
|
||||
}
|
||||
const to = relativeSelection.to
|
||||
const from = relativeSelection.from
|
||||
const fromY = relativeSelection.fromY
|
||||
const toY = relativeSelection.toY
|
||||
let shouldUpdate = false
|
||||
let anchorNode = browserSelection.anchorNode
|
||||
let anchorOffset = browserSelection.anchorOffset
|
||||
let focusNode = browserSelection.focusNode
|
||||
let focusOffset = browserSelection.focusOffset
|
||||
if (from !== null) {
|
||||
let sel = fromRelativePosition(fromY, from)
|
||||
if (sel !== null) {
|
||||
let node = domBinding.typeToDom.get(sel.type)
|
||||
let offset = sel.offset
|
||||
if (node !== anchorNode || offset !== anchorOffset) {
|
||||
anchorNode = node
|
||||
anchorOffset = offset
|
||||
shouldUpdate = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if (to !== null) {
|
||||
let sel = fromRelativePosition(toY, to)
|
||||
if (sel !== null) {
|
||||
let node = domBinding.typeToDom.get(sel.type)
|
||||
let offset = sel.offset
|
||||
if (node !== focusNode || offset !== focusOffset) {
|
||||
focusNode = node
|
||||
focusOffset = offset
|
||||
shouldUpdate = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if (shouldUpdate) {
|
||||
browserSelection.setBaseAndExtent(
|
||||
anchorNode,
|
||||
anchorOffset,
|
||||
focusNode,
|
||||
focusOffset
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
/* global getSelection */
|
||||
|
||||
import YXmlText from '../../Types/YXml/YXmlText.js'
|
||||
import YXmlHook from '../../Types/YXml/YXmlHook.js'
|
||||
import { removeDomChildrenUntilElementFound } from './util.js'
|
||||
|
||||
function findScrollReference (scrollingElement) {
|
||||
if (scrollingElement !== null) {
|
||||
let anchor = getSelection().anchorNode
|
||||
if (anchor == null) {
|
||||
let children = scrollingElement.children // only iterate through non-text nodes
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
const elem = children[i]
|
||||
const rect = elem.getBoundingClientRect()
|
||||
if (rect.top >= 0) {
|
||||
return { elem, top: rect.top }
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (anchor.nodeType === document.TEXT_NODE) {
|
||||
anchor = anchor.parentElement
|
||||
}
|
||||
const top = anchor.getBoundingClientRect().top
|
||||
return { elem: anchor, top: top }
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
function fixScroll (scrollingElement, ref) {
|
||||
if (ref !== null) {
|
||||
const { elem, top } = ref
|
||||
const currentTop = elem.getBoundingClientRect().top
|
||||
const newScroll = scrollingElement.scrollTop + currentTop - top
|
||||
if (newScroll >= 0) {
|
||||
scrollingElement.scrollTop = newScroll
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
export default function typeObserver (events) {
|
||||
this._mutualExclude(() => {
|
||||
const scrollRef = findScrollReference(this.scrollingElement)
|
||||
events.forEach(event => {
|
||||
const yxml = event.target
|
||||
const dom = this.typeToDom.get(yxml)
|
||||
if (dom !== undefined && dom !== false) {
|
||||
if (yxml.constructor === YXmlText) {
|
||||
dom.nodeValue = yxml.toString()
|
||||
// TODO: use hasOwnProperty instead of === undefined check
|
||||
} else if (event.attributesChanged !== undefined) {
|
||||
// update attributes
|
||||
event.attributesChanged.forEach(attributeName => {
|
||||
const value = yxml.getAttribute(attributeName)
|
||||
if (value === undefined) {
|
||||
dom.removeAttribute(attributeName)
|
||||
} else {
|
||||
dom.setAttribute(attributeName, value)
|
||||
}
|
||||
})
|
||||
/*
|
||||
* TODO: instead of hard-checking the types, it would be best to
|
||||
* specify the type's features. E.g.
|
||||
* - _yxmlHasAttributes
|
||||
* - _yxmlHasChildren
|
||||
* Furthermore, the features shouldn't be encoded in the types,
|
||||
* only in the attributes (above)
|
||||
*/
|
||||
if (event.childListChanged && yxml.constructor !== YXmlHook) {
|
||||
let currentChild = dom.firstChild
|
||||
yxml.forEach(childType => {
|
||||
const childNode = this.typeToDom.get(childType)
|
||||
switch (childNode) {
|
||||
case undefined:
|
||||
// Does not exist. Create it.
|
||||
const node = childType.toDom(this.opts.document, this.opts.hooks, this)
|
||||
dom.insertBefore(node, currentChild)
|
||||
break
|
||||
case false:
|
||||
// nop
|
||||
break
|
||||
default:
|
||||
// Is already attached to the dom.
|
||||
// Find it and remove all dom nodes in-between.
|
||||
removeDomChildrenUntilElementFound(dom, currentChild, childNode)
|
||||
currentChild = childNode.nextSibling
|
||||
break
|
||||
}
|
||||
})
|
||||
removeDomChildrenUntilElementFound(dom, currentChild, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
fixScroll(this.scrollingElement, scrollRef)
|
||||
})
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
|
||||
import domToType from './domToType.js'
|
||||
|
||||
/**
|
||||
* Iterates items until an undeleted item is found.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
export function iterateUntilUndeleted (item) {
|
||||
while (item !== null && item._deleted) {
|
||||
item = item._right
|
||||
}
|
||||
return item
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an association (the information that a DOM element belongs to a
|
||||
* type).
|
||||
*
|
||||
* @param {DomBinding} domBinding The binding object
|
||||
* @param {Element} dom The dom that is to be associated with type
|
||||
* @param {YXmlElement|YXmlHook} type The type that is to be associated with dom
|
||||
*
|
||||
*/
|
||||
export function removeAssociation (domBinding, dom, type) {
|
||||
domBinding.domToType.delete(dom)
|
||||
domBinding.typeToDom.delete(type)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an association (the information that a DOM element belongs to a
|
||||
* type).
|
||||
*
|
||||
* @param {DomBinding} domBinding The binding object
|
||||
* @param {Element} dom The dom that is to be associated with type
|
||||
* @param {YXmlElement|YXmlHook} type The type that is to be associated with dom
|
||||
*
|
||||
*/
|
||||
export function createAssociation (domBinding, dom, type) {
|
||||
if (domBinding !== undefined) {
|
||||
domBinding.domToType.set(dom, type)
|
||||
domBinding.typeToDom.set(type, dom)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If oldDom is associated with a type, associate newDom with the type and
|
||||
* forget about oldDom. If oldDom is not associated with any type, nothing happens.
|
||||
*
|
||||
* @param {DomBinding} domBinding The binding object
|
||||
* @param {Element} oldDom The existing dom
|
||||
* @param {Element} newDom The new dom object
|
||||
*/
|
||||
export function switchAssociation (domBinding, oldDom, newDom) {
|
||||
if (domBinding !== undefined) {
|
||||
const type = domBinding.domToType.get(oldDom)
|
||||
if (type !== undefined) {
|
||||
removeAssociation(domBinding, oldDom, type)
|
||||
createAssociation(domBinding, newDom, type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert Dom Elements after one of the children of this YXmlFragment.
|
||||
* The Dom elements will be bound to a new YXmlElement and inserted at the
|
||||
* specified position.
|
||||
*
|
||||
* @param {YXmlElement} type The type in which to insert DOM elements.
|
||||
* @param {YXmlElement|null} prev The reference node. New YxmlElements are
|
||||
* inserted after this node. Set null to insert at
|
||||
* the beginning.
|
||||
* @param {Array<Element>} doms The Dom elements to insert.
|
||||
* @param {?Document} _document Optional. Provide the global document object.
|
||||
* @param {DomBinding} binding The dom binding
|
||||
* @return {Array<YXmlElement>} The YxmlElements that are inserted.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
export function insertDomElementsAfter (type, prev, doms, _document, binding) {
|
||||
const types = domsToTypes(doms, _document, binding.opts.hooks, binding.filter, binding)
|
||||
return type.insertAfter(prev, types)
|
||||
}
|
||||
|
||||
export function domsToTypes (doms, _document, hooks, filter, binding) {
|
||||
const types = []
|
||||
for (let dom of doms) {
|
||||
const t = domToType(dom, _document, hooks, filter, binding)
|
||||
if (t !== false) {
|
||||
types.push(t)
|
||||
}
|
||||
}
|
||||
return types
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
export function insertNodeHelper (yxml, prevExpectedNode, child, _document, binding) {
|
||||
let insertedNodes = insertDomElementsAfter(yxml, prevExpectedNode, [child], _document, binding)
|
||||
if (insertedNodes.length > 0) {
|
||||
return insertedNodes[0]
|
||||
} else {
|
||||
return prevExpectedNode
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove children until `elem` is found.
|
||||
*
|
||||
* @param {Element} parent The parent of `elem` and `currentChild`.
|
||||
* @param {Element} currentChild Start removing elements with `currentChild`. If
|
||||
* `currentChild` is `elem` it won't be removed.
|
||||
* @param {Element|null} elem The elemnt to look for.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
export function removeDomChildrenUntilElementFound (parent, currentChild, elem) {
|
||||
while (currentChild !== elem) {
|
||||
const del = currentChild
|
||||
currentChild = currentChild.nextSibling
|
||||
parent.removeChild(del)
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
import Binding from '../Binding.js'
|
||||
|
||||
function typeObserver (event) {
|
||||
const quill = this.target
|
||||
// Force flush Quill changes.
|
||||
quill.update('yjs')
|
||||
this._mutualExclude(function () {
|
||||
// Apply computed delta.
|
||||
quill.updateContents(event.delta, 'yjs')
|
||||
// Force flush Quill changes. Ignore applied changes.
|
||||
quill.update('yjs')
|
||||
})
|
||||
}
|
||||
|
||||
function quillObserver (delta) {
|
||||
this._mutualExclude(() => {
|
||||
this.type.applyDelta(delta.ops)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* A Binding that binds a YText type to a Quill editor.
|
||||
*
|
||||
* @example
|
||||
* const quill = new Quill(document.createElement('div'))
|
||||
* const type = y.define('quill', Y.Text)
|
||||
* const binding = new Y.QuillBinding(quill, type)
|
||||
* // Now modifications on the DOM will be reflected in the Type, and the other
|
||||
* // way around!
|
||||
*/
|
||||
export default class QuillBinding extends Binding {
|
||||
/**
|
||||
* @param {YText} textType
|
||||
* @param {Quill} quill
|
||||
*/
|
||||
constructor (textType, quill) {
|
||||
// Binding handles textType as this.type and quill as this.target.
|
||||
super(textType, quill)
|
||||
// Set initial value.
|
||||
quill.setContents(textType.toDelta(), 'yjs')
|
||||
// Observers are handled by this class.
|
||||
this._typeObserver = typeObserver.bind(this)
|
||||
this._quillObserver = quillObserver.bind(this)
|
||||
textType.observe(this._typeObserver)
|
||||
quill.on('text-change', this._quillObserver)
|
||||
}
|
||||
destroy () {
|
||||
// Remove everything that is handled by this class.
|
||||
this.type.unobserve(this._typeObserver)
|
||||
this.target.off('text-change', this._quillObserver)
|
||||
super.destroy()
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
|
||||
import Binding from '../Binding.js'
|
||||
import simpleDiff from '../../Util/simpleDiff.js'
|
||||
import { getRelativePosition, fromRelativePosition } from '../../Util/relativePosition.js'
|
||||
|
||||
function typeObserver () {
|
||||
this._mutualExclude(() => {
|
||||
const textarea = this.target
|
||||
const textType = this.type
|
||||
const relativeStart = getRelativePosition(textType, textarea.selectionStart)
|
||||
const relativeEnd = getRelativePosition(textType, textarea.selectionEnd)
|
||||
textarea.value = textType.toString()
|
||||
const start = fromRelativePosition(textType._y, relativeStart)
|
||||
const end = fromRelativePosition(textType._y, relativeEnd)
|
||||
textarea.setSelectionRange(start, end)
|
||||
})
|
||||
}
|
||||
|
||||
function domObserver () {
|
||||
this._mutualExclude(() => {
|
||||
let diff = simpleDiff(this.type.toString(), this.target.value)
|
||||
this.type.delete(diff.pos, diff.remove)
|
||||
this.type.insert(diff.pos, diff.insert)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* A binding that binds a YText to a dom textarea.
|
||||
*
|
||||
* This binding is automatically destroyed when its parent is deleted.
|
||||
*
|
||||
* @example
|
||||
* const textare = document.createElement('textarea')
|
||||
* const type = y.define('textarea', Y.Text)
|
||||
* const binding = new Y.QuillBinding(type, textarea)
|
||||
*
|
||||
*/
|
||||
export default class TextareaBinding extends Binding {
|
||||
constructor (textType, domTextarea) {
|
||||
// Binding handles textType as this.type and domTextarea as this.target
|
||||
super(textType, domTextarea)
|
||||
// set initial value
|
||||
domTextarea.value = textType.toString()
|
||||
// Observers are handled by this class
|
||||
this._typeObserver = typeObserver.bind(this)
|
||||
this._domObserver = domObserver.bind(this)
|
||||
textType.observe(this._typeObserver)
|
||||
domTextarea.addEventListener('input', this._domObserver)
|
||||
}
|
||||
destroy () {
|
||||
// Remove everything that is handled by this class
|
||||
this.type.unobserve(this._typeObserver)
|
||||
this.target.unobserve(this._domObserver)
|
||||
super.destroy()
|
||||
}
|
||||
}
|
||||
297
src/Connector.js
297
src/Connector.js
@@ -1,297 +0,0 @@
|
||||
import BinaryEncoder from './Util/Binary/Encoder.js'
|
||||
import BinaryDecoder from './Util/Binary/Decoder.js'
|
||||
|
||||
import { sendSyncStep1, readSyncStep1 } from './MessageHandler/syncStep1.js'
|
||||
import { readSyncStep2 } from './MessageHandler/syncStep2.js'
|
||||
import { integrateRemoteStructs } from './MessageHandler/integrateRemoteStructs.js'
|
||||
|
||||
import debug from 'debug'
|
||||
|
||||
// TODO: rename Connector
|
||||
|
||||
export default class AbstractConnector {
|
||||
constructor (y, opts) {
|
||||
this.y = y
|
||||
this.opts = opts
|
||||
if (opts.role == null || opts.role === 'master') {
|
||||
this.role = 'master'
|
||||
} else if (opts.role === 'slave') {
|
||||
this.role = 'slave'
|
||||
} else {
|
||||
throw new Error("Role must be either 'master' or 'slave'!")
|
||||
}
|
||||
this.log = debug('y:connector')
|
||||
this.logMessage = debug('y:connector-message')
|
||||
this._forwardAppliedStructs = opts.forwardAppliedOperations || false // TODO: rename
|
||||
this.role = opts.role
|
||||
this.connections = new Map()
|
||||
this.isSynced = false
|
||||
this.userEventListeners = []
|
||||
this.whenSyncedListeners = []
|
||||
this.currentSyncTarget = null
|
||||
this.debug = opts.debug === true
|
||||
this.broadcastBuffer = new BinaryEncoder()
|
||||
this.broadcastBufferSize = 0
|
||||
this.protocolVersion = 11
|
||||
this.authInfo = opts.auth || null
|
||||
this.checkAuth = opts.checkAuth || function () { return Promise.resolve('write') } // default is everyone has write access
|
||||
if (opts.maxBufferLength == null) {
|
||||
this.maxBufferLength = -1
|
||||
} else {
|
||||
this.maxBufferLength = opts.maxBufferLength
|
||||
}
|
||||
}
|
||||
|
||||
reconnect () {
|
||||
this.log('reconnecting..')
|
||||
}
|
||||
|
||||
disconnect () {
|
||||
this.log('discronnecting..')
|
||||
this.connections = new Map()
|
||||
this.isSynced = false
|
||||
this.currentSyncTarget = null
|
||||
this.whenSyncedListeners = []
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
onUserEvent (f) {
|
||||
this.userEventListeners.push(f)
|
||||
}
|
||||
|
||||
removeUserEventListener (f) {
|
||||
this.userEventListeners = this.userEventListeners.filter(g => f !== g)
|
||||
}
|
||||
|
||||
userLeft (user) {
|
||||
if (this.connections.has(user)) {
|
||||
this.log('%s: User left %s', this.y.userID, user)
|
||||
this.connections.delete(user)
|
||||
// check if isSynced event can be sent now
|
||||
this._setSyncedWith(null)
|
||||
for (var f of this.userEventListeners) {
|
||||
f({
|
||||
action: 'userLeft',
|
||||
user: user
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
userJoined (user, role, auth) {
|
||||
if (role == null) {
|
||||
throw new Error('You must specify the role of the joined user!')
|
||||
}
|
||||
if (this.connections.has(user)) {
|
||||
throw new Error('This user already joined!')
|
||||
}
|
||||
this.log('%s: User joined %s', this.y.userID, user)
|
||||
this.connections.set(user, {
|
||||
uid: user,
|
||||
isSynced: false,
|
||||
role: role,
|
||||
processAfterAuth: [],
|
||||
processAfterSync: [],
|
||||
auth: auth || null,
|
||||
receivedSyncStep2: false
|
||||
})
|
||||
let defer = {}
|
||||
defer.promise = new Promise(function (resolve) { defer.resolve = resolve })
|
||||
this.connections.get(user).syncStep2 = defer
|
||||
for (var f of this.userEventListeners) {
|
||||
f({
|
||||
action: 'userJoined',
|
||||
user: user,
|
||||
role: role
|
||||
})
|
||||
}
|
||||
this._syncWithUser(user)
|
||||
}
|
||||
|
||||
// Execute a function _when_ we are connected.
|
||||
// If not connected, wait until connected
|
||||
whenSynced (f) {
|
||||
if (this.isSynced) {
|
||||
f()
|
||||
} else {
|
||||
this.whenSyncedListeners.push(f)
|
||||
}
|
||||
}
|
||||
|
||||
_syncWithUser (userID) {
|
||||
if (this.role === 'slave') {
|
||||
return // "The current sync has not finished or this is controlled by a master!"
|
||||
}
|
||||
sendSyncStep1(this, userID)
|
||||
}
|
||||
|
||||
_fireIsSyncedListeners () {
|
||||
if (!this.isSynced) {
|
||||
this.isSynced = true
|
||||
// It is safer to remove this!
|
||||
// call whensynced listeners
|
||||
for (var f of this.whenSyncedListeners) {
|
||||
f()
|
||||
}
|
||||
this.whenSyncedListeners = []
|
||||
this.y._setContentReady()
|
||||
this.y.emit('synced')
|
||||
}
|
||||
}
|
||||
|
||||
send (uid, buffer) {
|
||||
const y = this.y
|
||||
if (!(buffer instanceof ArrayBuffer || buffer instanceof Uint8Array)) {
|
||||
throw new Error('Expected Message to be an ArrayBuffer or Uint8Array - don\'t use this method to send custom messages')
|
||||
}
|
||||
this.log('User%s to User%s: Send \'%y\'', y.userID, uid, buffer)
|
||||
this.logMessage('User%s to User%s: Send %Y', y.userID, uid, [y, buffer])
|
||||
}
|
||||
|
||||
broadcast (buffer) {
|
||||
const y = this.y
|
||||
if (!(buffer instanceof ArrayBuffer || buffer instanceof Uint8Array)) {
|
||||
throw new Error('Expected Message to be an ArrayBuffer or Uint8Array - don\'t use this method to send custom messages')
|
||||
}
|
||||
this.log('User%s: Broadcast \'%y\'', y.userID, buffer)
|
||||
this.logMessage('User%s: Broadcast: %Y', y.userID, [y, buffer])
|
||||
}
|
||||
|
||||
/*
|
||||
Buffer operations, and broadcast them when ready.
|
||||
*/
|
||||
broadcastStruct (struct) {
|
||||
const firstContent = this.broadcastBuffer.length === 0
|
||||
if (firstContent) {
|
||||
this.broadcastBuffer.writeVarString(this.y.room)
|
||||
this.broadcastBuffer.writeVarString('update')
|
||||
this.broadcastBufferSize = 0
|
||||
this.broadcastBufferSizePos = this.broadcastBuffer.pos
|
||||
this.broadcastBuffer.writeUint32(0)
|
||||
}
|
||||
this.broadcastBufferSize++
|
||||
struct._toBinary(this.broadcastBuffer)
|
||||
if (this.maxBufferLength > 0 && this.broadcastBuffer.length > this.maxBufferLength) {
|
||||
// it is necessary to send the buffer now
|
||||
// cache the buffer and check if server is responsive
|
||||
const buffer = this.broadcastBuffer
|
||||
buffer.setUint32(this.broadcastBufferSizePos, this.broadcastBufferSize)
|
||||
this.broadcastBuffer = new BinaryEncoder()
|
||||
this.whenRemoteResponsive().then(() => {
|
||||
this.broadcast(buffer.createBuffer())
|
||||
})
|
||||
} else if (firstContent) {
|
||||
// send the buffer when all transactions are finished
|
||||
// (or buffer exceeds maxBufferLength)
|
||||
setTimeout(() => {
|
||||
if (this.broadcastBuffer.length > 0) {
|
||||
const buffer = this.broadcastBuffer
|
||||
buffer.setUint32(this.broadcastBufferSizePos, this.broadcastBufferSize)
|
||||
this.broadcast(buffer.createBuffer())
|
||||
this.broadcastBuffer = new BinaryEncoder()
|
||||
}
|
||||
}, 0)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Somehow check the responsiveness of the remote clients/server
|
||||
* Default behavior:
|
||||
* Wait 100ms before broadcasting the next batch of operations
|
||||
*
|
||||
* Only used when maxBufferLength is set
|
||||
*
|
||||
*/
|
||||
whenRemoteResponsive () {
|
||||
return new Promise(function (resolve) {
|
||||
setTimeout(resolve, 100)
|
||||
})
|
||||
}
|
||||
|
||||
/*
|
||||
You received a raw message, and you know that it is intended for Yjs. Then call this function.
|
||||
*/
|
||||
receiveMessage (sender, buffer, skipAuth) {
|
||||
const y = this.y
|
||||
const userID = y.userID
|
||||
skipAuth = skipAuth || false
|
||||
if (!(buffer instanceof ArrayBuffer || buffer instanceof Uint8Array)) {
|
||||
return Promise.reject(new Error('Expected Message to be an ArrayBuffer or Uint8Array!'))
|
||||
}
|
||||
if (sender === userID) {
|
||||
return Promise.resolve()
|
||||
}
|
||||
let decoder = new BinaryDecoder(buffer)
|
||||
let encoder = new BinaryEncoder()
|
||||
let roomname = decoder.readVarString() // read room name
|
||||
encoder.writeVarString(roomname)
|
||||
let messageType = decoder.readVarString()
|
||||
let senderConn = this.connections.get(sender)
|
||||
this.log('User%s from User%s: Receive \'%s\'', userID, sender, messageType)
|
||||
this.logMessage('User%s from User%s: Receive %Y', userID, sender, [y, buffer])
|
||||
if (senderConn == null && !skipAuth) {
|
||||
throw new Error('Received message from unknown peer!')
|
||||
}
|
||||
if (messageType === 'sync step 1' || messageType === 'sync step 2') {
|
||||
let auth = decoder.readVarUint()
|
||||
if (senderConn.auth == null) {
|
||||
senderConn.processAfterAuth.push([messageType, senderConn, decoder, encoder, sender])
|
||||
// check auth
|
||||
return this.checkAuth(auth, y, sender).then(authPermissions => {
|
||||
if (senderConn.auth == null) {
|
||||
senderConn.auth = authPermissions
|
||||
y.emit('userAuthenticated', {
|
||||
user: senderConn.uid,
|
||||
auth: authPermissions
|
||||
})
|
||||
}
|
||||
let messages = senderConn.processAfterAuth
|
||||
senderConn.processAfterAuth = []
|
||||
|
||||
messages.forEach(m =>
|
||||
this.computeMessage(m[0], m[1], m[2], m[3], m[4])
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
if ((skipAuth || senderConn.auth != null) && (messageType !== 'update' || senderConn.isSynced)) {
|
||||
this.computeMessage(messageType, senderConn, decoder, encoder, sender, skipAuth)
|
||||
} else {
|
||||
senderConn.processAfterSync.push([messageType, senderConn, decoder, encoder, sender, false])
|
||||
}
|
||||
}
|
||||
|
||||
computeMessage (messageType, senderConn, decoder, encoder, sender, skipAuth) {
|
||||
if (messageType === 'sync step 1' && (senderConn.auth === 'write' || senderConn.auth === 'read')) {
|
||||
// cannot wait for sync step 1 to finish, because we may wait for sync step 2 in sync step 1 (->lock)
|
||||
readSyncStep1(decoder, encoder, this.y, senderConn, sender)
|
||||
} else {
|
||||
const y = this.y
|
||||
y.transact(function () {
|
||||
if (messageType === 'sync step 2' && senderConn.auth === 'write') {
|
||||
readSyncStep2(decoder, encoder, y, senderConn, sender)
|
||||
} else if (messageType === 'update' && (skipAuth || senderConn.auth === 'write')) {
|
||||
integrateRemoteStructs(y, decoder)
|
||||
} else {
|
||||
throw new Error('Unable to receive message')
|
||||
}
|
||||
}, true)
|
||||
}
|
||||
}
|
||||
|
||||
_setSyncedWith (user) {
|
||||
if (user != null) {
|
||||
const userConn = this.connections.get(user)
|
||||
userConn.isSynced = true
|
||||
const messages = userConn.processAfterSync
|
||||
userConn.processAfterSync = []
|
||||
messages.forEach(m => {
|
||||
this.computeMessage(m[0], m[1], m[2], m[3], m[4])
|
||||
})
|
||||
}
|
||||
const conns = Array.from(this.connections.values())
|
||||
if (conns.length > 0 && conns.every(u => u.isSynced)) {
|
||||
this._fireIsSyncedListeners()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
|
||||
import { writeStructs } from './syncStep1.js'
|
||||
import { integrateRemoteStructs } from './integrateRemoteStructs.js'
|
||||
import { readDeleteSet, writeDeleteSet } from './deleteSet.js'
|
||||
import BinaryEncoder from '../Util/Binary/Encoder.js'
|
||||
|
||||
/**
|
||||
* Read the Decoder and fill the Yjs instance with data in the decoder.
|
||||
*
|
||||
* @param {Y} y The Yjs instance
|
||||
* @param {BinaryDecoder} decoder The BinaryDecoder to read from.
|
||||
*/
|
||||
export function fromBinary (y, decoder) {
|
||||
y.transact(function () {
|
||||
integrateRemoteStructs(y, decoder)
|
||||
readDeleteSet(y, decoder)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode the Yjs model to binary format.
|
||||
*
|
||||
* @param {Y} y The Yjs instance
|
||||
* @return {BinaryEncoder} The encoder instance that can be transformed
|
||||
* to ArrayBuffer or Buffer.
|
||||
*/
|
||||
export function toBinary (y) {
|
||||
let encoder = new BinaryEncoder()
|
||||
writeStructs(y, encoder, new Map())
|
||||
writeDeleteSet(y, encoder)
|
||||
return encoder
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
import { deleteItemRange } from '../Struct/Delete.js'
|
||||
import ID from '../Util/ID/ID.js'
|
||||
|
||||
export function stringifyDeleteSet (y, decoder, strBuilder) {
|
||||
let dsLength = decoder.readUint32()
|
||||
for (let i = 0; i < dsLength; i++) {
|
||||
let user = decoder.readVarUint()
|
||||
strBuilder.push(' -' + user + ':')
|
||||
let dvLength = decoder.readVarUint()
|
||||
for (let j = 0; j < dvLength; j++) {
|
||||
let from = decoder.readVarUint()
|
||||
let len = decoder.readVarUint()
|
||||
let gc = decoder.readUint8() === 1
|
||||
strBuilder.push(`clock: ${from}, length: ${len}, gc: ${gc}`)
|
||||
}
|
||||
}
|
||||
return strBuilder
|
||||
}
|
||||
|
||||
export function writeDeleteSet (y, encoder) {
|
||||
let currentUser = null
|
||||
let currentLength
|
||||
let lastLenPos
|
||||
|
||||
let numberOfUsers = 0
|
||||
let laterDSLenPus = encoder.pos
|
||||
encoder.writeUint32(0)
|
||||
|
||||
y.ds.iterate(null, null, function (n) {
|
||||
var user = n._id.user
|
||||
var clock = n._id.clock
|
||||
var len = n.len
|
||||
var gc = n.gc
|
||||
if (currentUser !== user) {
|
||||
numberOfUsers++
|
||||
// a new user was found
|
||||
if (currentUser !== null) { // happens on first iteration
|
||||
encoder.setUint32(lastLenPos, currentLength)
|
||||
}
|
||||
currentUser = user
|
||||
encoder.writeVarUint(user)
|
||||
// pseudo-fill pos
|
||||
lastLenPos = encoder.pos
|
||||
encoder.writeUint32(0)
|
||||
currentLength = 0
|
||||
}
|
||||
encoder.writeVarUint(clock)
|
||||
encoder.writeVarUint(len)
|
||||
encoder.writeUint8(gc ? 1 : 0)
|
||||
currentLength++
|
||||
})
|
||||
if (currentUser !== null) { // happens on first iteration
|
||||
encoder.setUint32(lastLenPos, currentLength)
|
||||
}
|
||||
encoder.setUint32(laterDSLenPus, numberOfUsers)
|
||||
}
|
||||
|
||||
export function readDeleteSet (y, decoder) {
|
||||
let dsLength = decoder.readUint32()
|
||||
for (let i = 0; i < dsLength; i++) {
|
||||
let user = decoder.readVarUint()
|
||||
let dv = []
|
||||
let dvLength = decoder.readUint32()
|
||||
for (let j = 0; j < dvLength; j++) {
|
||||
let from = decoder.readVarUint()
|
||||
let len = decoder.readVarUint()
|
||||
let gc = decoder.readUint8() === 1
|
||||
dv.push([from, len, gc])
|
||||
}
|
||||
if (dvLength > 0) {
|
||||
let pos = 0
|
||||
let d = dv[pos]
|
||||
let deletions = []
|
||||
y.ds.iterate(new ID(user, 0), new ID(user, Number.MAX_VALUE), function (n) {
|
||||
// cases:
|
||||
// 1. d deletes something to the right of n
|
||||
// => go to next n (break)
|
||||
// 2. d deletes something to the left of n
|
||||
// => create deletions
|
||||
// => reset d accordingly
|
||||
// *)=> if d doesn't delete anything anymore, go to next d (continue)
|
||||
// 3. not 2) and d deletes something that also n deletes
|
||||
// => reset d so that it doesn't contain n's deletion
|
||||
// *)=> if d does not delete anything anymore, go to next d (continue)
|
||||
while (d != null) {
|
||||
var diff = 0 // describe the diff of length in 1) and 2)
|
||||
if (n._id.clock + n.len <= d[0]) {
|
||||
// 1)
|
||||
break
|
||||
} else if (d[0] < n._id.clock) {
|
||||
// 2)
|
||||
// delete maximum the len of d
|
||||
// else delete as much as possible
|
||||
diff = Math.min(n._id.clock - d[0], d[1])
|
||||
// deleteItemRange(y, user, d[0], diff, true)
|
||||
deletions.push([user, d[0], diff])
|
||||
} else {
|
||||
// 3)
|
||||
diff = n._id.clock + n.len - d[0] // never null (see 1)
|
||||
if (d[2] && !n.gc) {
|
||||
// d marks as gc'd but n does not
|
||||
// then delete either way
|
||||
// deleteItemRange(y, user, d[0], Math.min(diff, d[1]), true)
|
||||
deletions.push([user, d[0], Math.min(diff, d[1])])
|
||||
}
|
||||
}
|
||||
if (d[1] <= diff) {
|
||||
// d doesn't delete anything anymore
|
||||
d = dv[++pos]
|
||||
} else {
|
||||
d[0] = d[0] + diff // reset pos
|
||||
d[1] = d[1] - diff // reset length
|
||||
}
|
||||
}
|
||||
})
|
||||
// TODO: It would be more performant to apply the deletes in the above loop
|
||||
// Adapt the Tree implementation to support delete while iterating
|
||||
for (let i = deletions.length - 1; i >= 0; i--) {
|
||||
const del = deletions[i]
|
||||
deleteItemRange(y, del[0], del[1], del[2], true)
|
||||
}
|
||||
// for the rest.. just apply it
|
||||
for (; pos < dv.length; pos++) {
|
||||
d = dv[pos]
|
||||
deleteItemRange(y, user, d[0], d[1], true)
|
||||
// deletions.push([user, d[0], d[1], d[2]])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
import { getStruct } from '../Util/structReferences.js'
|
||||
import BinaryDecoder from '../Util/Binary/Decoder.js'
|
||||
import { logID } from './messageToString.js'
|
||||
import GC from '../Struct/GC.js'
|
||||
|
||||
class MissingEntry {
|
||||
constructor (decoder, missing, struct) {
|
||||
this.decoder = decoder
|
||||
this.missing = missing.length
|
||||
this.struct = struct
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Integrate remote struct
|
||||
* When a remote struct is integrated, other structs might be ready to ready to
|
||||
* integrate.
|
||||
*/
|
||||
function _integrateRemoteStructHelper (y, struct) {
|
||||
const id = struct._id
|
||||
if (id === undefined) {
|
||||
struct._integrate(y)
|
||||
} else {
|
||||
if (y.ss.getState(id.user) > id.clock) {
|
||||
return
|
||||
}
|
||||
if (!y.gcEnabled || struct.constructor === GC || (struct._parent.constructor !== GC && struct._parent._deleted === false)) {
|
||||
// Is either a GC or Item with an undeleted parent
|
||||
// save to integrate
|
||||
struct._integrate(y)
|
||||
} else {
|
||||
// Is an Item. parent was deleted.
|
||||
struct._gc(y)
|
||||
}
|
||||
let msu = y._missingStructs.get(id.user)
|
||||
if (msu != null) {
|
||||
let clock = id.clock
|
||||
const finalClock = clock + struct._length
|
||||
for (;clock < finalClock; clock++) {
|
||||
const missingStructs = msu.get(clock)
|
||||
if (missingStructs !== undefined) {
|
||||
missingStructs.forEach(missingDef => {
|
||||
missingDef.missing--
|
||||
if (missingDef.missing === 0) {
|
||||
const decoder = missingDef.decoder
|
||||
let oldPos = decoder.pos
|
||||
let missing = missingDef.struct._fromBinary(y, decoder)
|
||||
decoder.pos = oldPos
|
||||
if (missing.length === 0) {
|
||||
y._readyToIntegrate.push(missingDef.struct)
|
||||
}
|
||||
}
|
||||
})
|
||||
msu.delete(clock)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function stringifyStructs (y, decoder, strBuilder) {
|
||||
const len = decoder.readUint32()
|
||||
for (let i = 0; i < len; i++) {
|
||||
let reference = decoder.readVarUint()
|
||||
let Constr = getStruct(reference)
|
||||
let struct = new Constr()
|
||||
let missing = struct._fromBinary(y, decoder)
|
||||
let logMessage = ' ' + struct._logString()
|
||||
if (missing.length > 0) {
|
||||
logMessage += ' .. missing: ' + missing.map(logID).join(', ')
|
||||
}
|
||||
strBuilder.push(logMessage)
|
||||
}
|
||||
}
|
||||
|
||||
export function integrateRemoteStructs (y, decoder) {
|
||||
const len = decoder.readUint32()
|
||||
for (let i = 0; i < len; i++) {
|
||||
let reference = decoder.readVarUint()
|
||||
let Constr = getStruct(reference)
|
||||
let struct = new Constr()
|
||||
let decoderPos = decoder.pos
|
||||
let missing = struct._fromBinary(y, decoder)
|
||||
if (missing.length === 0) {
|
||||
while (struct != null) {
|
||||
_integrateRemoteStructHelper(y, struct)
|
||||
struct = y._readyToIntegrate.shift()
|
||||
}
|
||||
} else {
|
||||
let _decoder = new BinaryDecoder(decoder.uint8arr)
|
||||
_decoder.pos = decoderPos
|
||||
let missingEntry = new MissingEntry(_decoder, missing, struct)
|
||||
let missingStructs = y._missingStructs
|
||||
for (let i = missing.length - 1; i >= 0; i--) {
|
||||
let m = missing[i]
|
||||
if (!missingStructs.has(m.user)) {
|
||||
missingStructs.set(m.user, new Map())
|
||||
}
|
||||
let msu = missingStructs.get(m.user)
|
||||
if (!msu.has(m.clock)) {
|
||||
msu.set(m.clock, [])
|
||||
}
|
||||
let mArray = msu = msu.get(m.clock)
|
||||
mArray.push(missingEntry)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
import BinaryDecoder from '../Util/Binary/Decoder.js'
|
||||
import { stringifyStructs } from './integrateRemoteStructs.js'
|
||||
import { stringifySyncStep1 } from './syncStep1.js'
|
||||
import { stringifySyncStep2 } from './syncStep2.js'
|
||||
import ID from '../Util/ID/ID.js'
|
||||
import RootID from '../Util/ID/RootID.js'
|
||||
import Y from '../Y.js'
|
||||
|
||||
export function messageToString ([y, buffer]) {
|
||||
let decoder = new BinaryDecoder(buffer)
|
||||
decoder.readVarString() // read roomname
|
||||
let type = decoder.readVarString()
|
||||
let strBuilder = []
|
||||
strBuilder.push('\n === ' + type + ' ===')
|
||||
if (type === 'update') {
|
||||
stringifyStructs(y, decoder, strBuilder)
|
||||
} else if (type === 'sync step 1') {
|
||||
stringifySyncStep1(y, decoder, strBuilder)
|
||||
} else if (type === 'sync step 2') {
|
||||
stringifySyncStep2(y, decoder, strBuilder)
|
||||
} else {
|
||||
strBuilder.push('-- Unknown message type - probably an encoding issue!!!')
|
||||
}
|
||||
return strBuilder.join('\n')
|
||||
}
|
||||
|
||||
export function messageToRoomname (buffer) {
|
||||
let decoder = new BinaryDecoder(buffer)
|
||||
decoder.readVarString() // roomname
|
||||
return decoder.readVarString() // messageType
|
||||
}
|
||||
|
||||
export function logID (id) {
|
||||
if (id !== null && id._id != null) {
|
||||
id = id._id
|
||||
}
|
||||
if (id === null) {
|
||||
return '()'
|
||||
} else if (id instanceof ID) {
|
||||
return `(${id.user},${id.clock})`
|
||||
} else if (id instanceof RootID) {
|
||||
return `(${id.name},${id.type})`
|
||||
} else if (id.constructor === Y) {
|
||||
return `y`
|
||||
} else {
|
||||
throw new Error('This is not a valid ID!')
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper utility to convert an item to a readable format.
|
||||
*
|
||||
* @param {String} name The name of the item class (YText, ItemString, ..).
|
||||
* @param {Item} item The item instance.
|
||||
* @param {String} [append] Additional information to append to the returned
|
||||
* string.
|
||||
* @return {String} A readable string that represents the item object.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
export function logItemHelper (name, item, append) {
|
||||
const left = item._left !== null ? item._left._lastId : null
|
||||
const origin = item._origin !== null ? item._origin._lastId : null
|
||||
return `${name}(id:${logID(item._id)},start:${logID(item._start)},left:${logID(left)},origin:${logID(origin)},right:${logID(item._right)},parent:${logID(item._parent)},parentSub:${item._parentSub}${append !== undefined ? ' - ' + append : ''})`
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
|
||||
export function readStateSet (decoder) {
|
||||
let ss = new Map()
|
||||
let ssLength = decoder.readUint32()
|
||||
for (let i = 0; i < ssLength; i++) {
|
||||
let user = decoder.readVarUint()
|
||||
let clock = decoder.readVarUint()
|
||||
ss.set(user, clock)
|
||||
}
|
||||
return ss
|
||||
}
|
||||
|
||||
export function writeStateSet (y, encoder) {
|
||||
let lenPosition = encoder.pos
|
||||
let len = 0
|
||||
encoder.writeUint32(0)
|
||||
for (let [user, clock] of y.ss.state) {
|
||||
encoder.writeVarUint(user)
|
||||
encoder.writeVarUint(clock)
|
||||
len++
|
||||
}
|
||||
encoder.setUint32(lenPosition, len)
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
import BinaryEncoder from '../Util/Binary/Encoder.js'
|
||||
import { readStateSet, writeStateSet } from './stateSet.js'
|
||||
import { writeDeleteSet } from './deleteSet.js'
|
||||
import ID from '../Util/ID/ID.js'
|
||||
import { RootFakeUserID } from '../Util/ID/RootID.js'
|
||||
|
||||
export function stringifySyncStep1 (y, decoder, strBuilder) {
|
||||
let auth = decoder.readVarString()
|
||||
let protocolVersion = decoder.readVarUint()
|
||||
strBuilder.push(` - auth: "${auth}"`)
|
||||
strBuilder.push(` - protocolVersion: ${protocolVersion}`)
|
||||
// write SS
|
||||
let ssBuilder = []
|
||||
let len = decoder.readUint32()
|
||||
for (let i = 0; i < len; i++) {
|
||||
let user = decoder.readVarUint()
|
||||
let clock = decoder.readVarUint()
|
||||
ssBuilder.push(`(${user}:${clock})`)
|
||||
}
|
||||
strBuilder.push(' == SS: ' + ssBuilder.join(','))
|
||||
}
|
||||
|
||||
export function sendSyncStep1 (connector, syncUser) {
|
||||
let encoder = new BinaryEncoder()
|
||||
encoder.writeVarString(connector.y.room)
|
||||
encoder.writeVarString('sync step 1')
|
||||
encoder.writeVarString(connector.authInfo || '')
|
||||
encoder.writeVarUint(connector.protocolVersion)
|
||||
writeStateSet(connector.y, encoder)
|
||||
connector.send(syncUser, encoder.createBuffer())
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Write all Items that are not not included in ss to
|
||||
* the encoder object.
|
||||
*/
|
||||
export function writeStructs (y, encoder, ss) {
|
||||
const lenPos = encoder.pos
|
||||
encoder.writeUint32(0)
|
||||
let len = 0
|
||||
for (let user of y.ss.state.keys()) {
|
||||
let clock = ss.get(user) || 0
|
||||
if (user !== RootFakeUserID) {
|
||||
const minBound = new ID(user, clock)
|
||||
const overlappingLeft = y.os.findPrev(minBound)
|
||||
const rightID = overlappingLeft === null ? null : overlappingLeft._id
|
||||
if (rightID !== null && rightID.user === user && rightID.clock + overlappingLeft._length > clock) {
|
||||
const struct = overlappingLeft._clonePartial(clock - rightID.clock)
|
||||
struct._toBinary(encoder)
|
||||
len++
|
||||
}
|
||||
y.os.iterate(minBound, new ID(user, Number.MAX_VALUE), function (struct) {
|
||||
struct._toBinary(encoder)
|
||||
len++
|
||||
})
|
||||
}
|
||||
}
|
||||
encoder.setUint32(lenPos, len)
|
||||
}
|
||||
|
||||
export function readSyncStep1 (decoder, encoder, y, senderConn, sender) {
|
||||
let protocolVersion = decoder.readVarUint()
|
||||
// check protocol version
|
||||
if (protocolVersion !== y.connector.protocolVersion) {
|
||||
console.warn(
|
||||
`You tried to sync with a Yjs instance that has a different protocol version
|
||||
(You: ${protocolVersion}, Client: ${protocolVersion}).
|
||||
`)
|
||||
y.destroy()
|
||||
}
|
||||
// write sync step 2
|
||||
encoder.writeVarString('sync step 2')
|
||||
encoder.writeVarString(y.connector.authInfo || '')
|
||||
const ss = readStateSet(decoder)
|
||||
writeStructs(y, encoder, ss)
|
||||
writeDeleteSet(y, encoder)
|
||||
y.connector.send(senderConn.uid, encoder.createBuffer())
|
||||
senderConn.receivedSyncStep2 = true
|
||||
if (y.connector.role === 'slave') {
|
||||
sendSyncStep1(y.connector, sender)
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
import { stringifyStructs, integrateRemoteStructs } from './integrateRemoteStructs.js'
|
||||
import { readDeleteSet } from './deleteSet.js'
|
||||
|
||||
export function stringifySyncStep2 (y, decoder, strBuilder) {
|
||||
strBuilder.push(' - auth: ' + decoder.readVarString())
|
||||
strBuilder.push(' == OS:')
|
||||
stringifyStructs(y, decoder, strBuilder)
|
||||
// write DS to string
|
||||
strBuilder.push(' == DS:')
|
||||
let len = decoder.readUint32()
|
||||
for (let i = 0; i < len; i++) {
|
||||
let user = decoder.readVarUint()
|
||||
strBuilder.push(` User: ${user}: `)
|
||||
let len2 = decoder.readUint32()
|
||||
for (let j = 0; j < len2; j++) {
|
||||
let from = decoder.readVarUint()
|
||||
let to = decoder.readVarUint()
|
||||
let gc = decoder.readUint8() === 1
|
||||
strBuilder.push(`[${from}, ${to}, ${gc}]`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function readSyncStep2 (decoder, encoder, y, senderConn, sender) {
|
||||
integrateRemoteStructs(y, decoder)
|
||||
readDeleteSet(y, decoder)
|
||||
y.connector._setSyncedWith(sender)
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
import BinaryEncoder from './Util/Binary/Encoder.js'
|
||||
import BinaryDecoder from './Util/Binary/Decoder.js'
|
||||
import { toBinary, fromBinary } from './MessageHandler/binaryEncode.js'
|
||||
import { integrateRemoteStructs } from './MessageHandler/integrateRemoteStructs.js'
|
||||
import { createMutualExclude } from './Util/mutualExclude.js'
|
||||
|
||||
function getFreshCnf () {
|
||||
let buffer = new BinaryEncoder()
|
||||
buffer.writeUint32(0)
|
||||
return {
|
||||
len: 0,
|
||||
buffer
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract persistence class.
|
||||
*/
|
||||
export default class AbstractPersistence {
|
||||
constructor (opts) {
|
||||
this.opts = opts
|
||||
this.ys = new Map()
|
||||
}
|
||||
|
||||
_init (y) {
|
||||
let cnf = this.ys.get(y)
|
||||
if (cnf === undefined) {
|
||||
cnf = getFreshCnf()
|
||||
cnf.mutualExclude = createMutualExclude()
|
||||
this.ys.set(y, cnf)
|
||||
return this.init(y).then(() => {
|
||||
y.on('afterTransaction', (y, transaction) => {
|
||||
let cnf = this.ys.get(y)
|
||||
if (cnf.len > 0) {
|
||||
cnf.buffer.setUint32(0, cnf.len)
|
||||
this.saveUpdate(y, cnf.buffer.createBuffer(), transaction)
|
||||
let _cnf = getFreshCnf()
|
||||
for (let key in _cnf) {
|
||||
cnf[key] = _cnf[key]
|
||||
}
|
||||
}
|
||||
})
|
||||
return this.retrieve(y)
|
||||
}).then(function () {
|
||||
return Promise.resolve(cnf)
|
||||
})
|
||||
} else {
|
||||
return Promise.resolve(cnf)
|
||||
}
|
||||
}
|
||||
deinit (y) {
|
||||
this.ys.delete(y)
|
||||
y.persistence = null
|
||||
}
|
||||
|
||||
destroy () {
|
||||
this.ys = null
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all persisted data that belongs to a room.
|
||||
* Automatically destroys all Yjs all Yjs instances that persist to
|
||||
* the room. If `destroyYjsInstances = false` the persistence functionality
|
||||
* will be removed from the Yjs instances.
|
||||
*
|
||||
* ** Must be overwritten! **
|
||||
*/
|
||||
removePersistedData (room, destroyYjsInstances = true) {
|
||||
this.ys.forEach((cnf, y) => {
|
||||
if (y.room === room) {
|
||||
if (destroyYjsInstances) {
|
||||
y.destroy()
|
||||
} else {
|
||||
this.deinit(y)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/* overwrite */
|
||||
saveUpdate (buffer) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Save struct to update buffer.
|
||||
* saveUpdate is called when transaction ends
|
||||
*/
|
||||
saveStruct (y, struct) {
|
||||
let cnf = this.ys.get(y)
|
||||
if (cnf !== undefined) {
|
||||
cnf.mutualExclude(function () {
|
||||
struct._toBinary(cnf.buffer)
|
||||
cnf.len++
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/* overwrite */
|
||||
retrieve (y, model, updates) {
|
||||
let cnf = this.ys.get(y)
|
||||
if (cnf !== undefined) {
|
||||
cnf.mutualExclude(function () {
|
||||
y.transact(function () {
|
||||
if (model != null) {
|
||||
fromBinary(y, new BinaryDecoder(new Uint8Array(model)))
|
||||
}
|
||||
if (updates != null) {
|
||||
for (let i = 0; i < updates.length; i++) {
|
||||
integrateRemoteStructs(y, new BinaryDecoder(new Uint8Array(updates[i])))
|
||||
}
|
||||
}
|
||||
})
|
||||
y.emit('persistenceReady')
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/* overwrite */
|
||||
persist (y) {
|
||||
return toBinary(y).createBuffer()
|
||||
}
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
|
||||
import Tree from '../Util/Tree.js'
|
||||
import ID from '../Util/ID/ID.js'
|
||||
|
||||
class DSNode {
|
||||
constructor (id, len, gc) {
|
||||
this._id = id
|
||||
this.len = len
|
||||
this.gc = gc
|
||||
}
|
||||
clone () {
|
||||
return new DSNode(this._id, this.len, this.gc)
|
||||
}
|
||||
}
|
||||
|
||||
export default class DeleteStore extends Tree {
|
||||
logTable () {
|
||||
const deletes = []
|
||||
this.iterate(null, null, function (n) {
|
||||
deletes.push({
|
||||
user: n._id.user,
|
||||
clock: n._id.clock,
|
||||
len: n.len,
|
||||
gc: n.gc
|
||||
})
|
||||
})
|
||||
console.table(deletes)
|
||||
}
|
||||
isDeleted (id) {
|
||||
var n = this.findWithUpperBound(id)
|
||||
return n !== null && n._id.user === id.user && id.clock < n._id.clock + n.len
|
||||
}
|
||||
mark (id, length, gc) {
|
||||
if (length === 0) return
|
||||
// Step 1. Unmark range
|
||||
const leftD = this.findWithUpperBound(new ID(id.user, id.clock - 1))
|
||||
// Resize left DSNode if necessary
|
||||
if (leftD !== null && leftD._id.user === id.user) {
|
||||
if (leftD._id.clock < id.clock && id.clock < leftD._id.clock + leftD.len) {
|
||||
// node is overlapping. need to resize
|
||||
if (id.clock + length < leftD._id.clock + leftD.len) {
|
||||
// overlaps new mark range and some more
|
||||
// create another DSNode to the right of new mark
|
||||
this.put(new DSNode(new ID(id.user, id.clock + length), leftD._id.clock + leftD.len - id.clock - length, leftD.gc))
|
||||
}
|
||||
// resize left DSNode
|
||||
leftD.len = id.clock - leftD._id.clock
|
||||
} // Otherwise there is no overlapping
|
||||
}
|
||||
// Resize right DSNode if necessary
|
||||
const upper = new ID(id.user, id.clock + length - 1)
|
||||
const rightD = this.findWithUpperBound(upper)
|
||||
if (rightD !== null && rightD._id.user === id.user) {
|
||||
if (rightD._id.clock < id.clock + length && id.clock <= rightD._id.clock && id.clock + length < rightD._id.clock + rightD.len) { // we only consider the case where we resize the node
|
||||
const d = id.clock + length - rightD._id.clock
|
||||
rightD._id = new ID(rightD._id.user, rightD._id.clock + d)
|
||||
rightD.len -= d
|
||||
}
|
||||
}
|
||||
// Now we only have to delete all inner marks
|
||||
const deleteNodeIds = []
|
||||
this.iterate(id, upper, m => {
|
||||
deleteNodeIds.push(m._id)
|
||||
})
|
||||
for (let i = deleteNodeIds.length - 1; i >= 0; i--) {
|
||||
this.delete(deleteNodeIds[i])
|
||||
}
|
||||
let newMark = new DSNode(id, length, gc)
|
||||
// Step 2. Check if we can extend left or right
|
||||
if (leftD !== null && leftD._id.user === id.user && leftD._id.clock + leftD.len === id.clock && leftD.gc === gc) {
|
||||
// We can extend left
|
||||
leftD.len += length
|
||||
newMark = leftD
|
||||
}
|
||||
const rightNext = this.find(new ID(id.user, id.clock + length))
|
||||
if (rightNext !== null && rightNext._id.user === id.user && id.clock + length === rightNext._id.clock && gc === rightNext.gc) {
|
||||
// We can merge newMark and rightNext
|
||||
newMark.len += rightNext.len
|
||||
this.delete(rightNext._id)
|
||||
}
|
||||
if (leftD !== newMark) {
|
||||
// only put if we didn't extend left
|
||||
this.put(newMark)
|
||||
}
|
||||
}
|
||||
// TODO: exchange markDeleted for mark()
|
||||
markDeleted (id, length) {
|
||||
this.mark(id, length, false)
|
||||
}
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
import Tree from '../Util/Tree.js'
|
||||
import RootID from '../Util/ID/RootID.js'
|
||||
import { getStruct } from '../Util/structReferences.js'
|
||||
import { logID } from '../MessageHandler/messageToString.js'
|
||||
import GC from '../Struct/GC.js'
|
||||
|
||||
export default class OperationStore extends Tree {
|
||||
constructor (y) {
|
||||
super()
|
||||
this.y = y
|
||||
}
|
||||
logTable () {
|
||||
const items = []
|
||||
this.iterate(null, null, function (item) {
|
||||
if (item.constructor === GC) {
|
||||
items.push({
|
||||
id: logID(item),
|
||||
content: item._length,
|
||||
deleted: 'GC'
|
||||
})
|
||||
} else {
|
||||
items.push({
|
||||
id: logID(item),
|
||||
origin: logID(item._origin === null ? null : item._origin._lastId),
|
||||
left: logID(item._left === null ? null : item._left._lastId),
|
||||
right: logID(item._right),
|
||||
right_origin: logID(item._right_origin),
|
||||
parent: logID(item._parent),
|
||||
parentSub: item._parentSub,
|
||||
deleted: item._deleted,
|
||||
content: JSON.stringify(item._content)
|
||||
})
|
||||
}
|
||||
})
|
||||
console.table(items)
|
||||
}
|
||||
get (id) {
|
||||
let struct = this.find(id)
|
||||
if (struct === null && id instanceof RootID) {
|
||||
const Constr = getStruct(id.type)
|
||||
const y = this.y
|
||||
struct = new Constr()
|
||||
struct._id = id
|
||||
struct._parent = y
|
||||
y.transact(() => {
|
||||
struct._integrate(y)
|
||||
})
|
||||
this.put(struct)
|
||||
}
|
||||
return struct
|
||||
}
|
||||
// Use getItem for structs with _length > 1
|
||||
getItem (id) {
|
||||
var item = this.findWithUpperBound(id)
|
||||
if (item === null) {
|
||||
return null
|
||||
}
|
||||
const itemID = item._id
|
||||
if (id.user === itemID.user && id.clock < itemID.clock + item._length) {
|
||||
return item
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
}
|
||||
// Return an insertion such that id is the first element of content
|
||||
// This function manipulates an item, if necessary
|
||||
getItemCleanStart (id) {
|
||||
var ins = this.getItem(id)
|
||||
if (ins === null || ins._length === 1) {
|
||||
return ins
|
||||
}
|
||||
const insID = ins._id
|
||||
if (insID.clock === id.clock) {
|
||||
return ins
|
||||
} else {
|
||||
return ins._splitAt(this.y, id.clock - insID.clock)
|
||||
}
|
||||
}
|
||||
// Return an insertion such that id is the last element of content
|
||||
// This function manipulates an operation, if necessary
|
||||
getItemCleanEnd (id) {
|
||||
var ins = this.getItem(id)
|
||||
if (ins === null || ins._length === 1) {
|
||||
return ins
|
||||
}
|
||||
const insID = ins._id
|
||||
if (insID.clock + ins._length - 1 === id.clock) {
|
||||
return ins
|
||||
} else {
|
||||
ins._splitAt(this.y, id.clock - insID.clock + 1)
|
||||
return ins
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
import ID from '../Util/ID/ID.js'
|
||||
|
||||
export default class StateStore {
|
||||
constructor (y) {
|
||||
this.y = y
|
||||
this.state = new Map()
|
||||
}
|
||||
logTable () {
|
||||
const entries = []
|
||||
for (let [user, state] of this.state) {
|
||||
entries.push({
|
||||
user, state
|
||||
})
|
||||
}
|
||||
console.table(entries)
|
||||
}
|
||||
getNextID (len) {
|
||||
const user = this.y.userID
|
||||
const state = this.getState(user)
|
||||
this.setState(user, state + len)
|
||||
return new ID(user, state)
|
||||
}
|
||||
updateRemoteState (struct) {
|
||||
let user = struct._id.user
|
||||
let userState = this.state.get(user)
|
||||
while (struct !== null && struct._id.clock === userState) {
|
||||
userState += struct._length
|
||||
struct = this.y.os.get(new ID(user, userState))
|
||||
}
|
||||
this.state.set(user, userState)
|
||||
}
|
||||
getState (user) {
|
||||
let state = this.state.get(user)
|
||||
if (state == null) {
|
||||
return 0
|
||||
}
|
||||
return state
|
||||
}
|
||||
setState (user, state) {
|
||||
// TODO: modify missingi structs here
|
||||
const beforeState = this.y._transaction.beforeState
|
||||
if (!beforeState.has(user)) {
|
||||
beforeState.set(user, this.getState(user))
|
||||
}
|
||||
this.state.set(user, state)
|
||||
}
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
import { getStructReference } from '../Util/structReferences.js'
|
||||
import ID from '../Util/ID/ID.js'
|
||||
import { logID } from '../MessageHandler/messageToString.js'
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Delete all items in an ID-range
|
||||
* TODO: implement getItemCleanStartNode for better performance (only one lookup)
|
||||
*/
|
||||
export function deleteItemRange (y, user, clock, range, gcChildren) {
|
||||
const createDelete = y.connector !== null && y.connector._forwardAppliedStructs
|
||||
let item = y.os.getItemCleanStart(new ID(user, clock))
|
||||
if (item !== null) {
|
||||
if (!item._deleted) {
|
||||
item._splitAt(y, range)
|
||||
item._delete(y, createDelete, true)
|
||||
}
|
||||
let itemLen = item._length
|
||||
range -= itemLen
|
||||
clock += itemLen
|
||||
if (range > 0) {
|
||||
let node = y.os.findNode(new ID(user, clock))
|
||||
while (node !== null && node.val !== null && range > 0 && node.val._id.equals(new ID(user, clock))) {
|
||||
const nodeVal = node.val
|
||||
if (!nodeVal._deleted) {
|
||||
nodeVal._splitAt(y, range)
|
||||
nodeVal._delete(y, createDelete, gcChildren)
|
||||
}
|
||||
const nodeLen = nodeVal._length
|
||||
range -= nodeLen
|
||||
clock += nodeLen
|
||||
node = node.next()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* A Delete change is not a real Item, but it provides the same interface as an
|
||||
* Item. The only difference is that it will not be saved in the ItemStore
|
||||
* (OperationStore), but instead it is safed in the DeleteStore.
|
||||
*/
|
||||
export default class Delete {
|
||||
constructor () {
|
||||
this._target = null
|
||||
this._length = null
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Read the next Item in a Decoder and fill this Item with the read data.
|
||||
*
|
||||
* This is called when data is received from a remote peer.
|
||||
*
|
||||
* @param {Y} y The Yjs instance that this Item belongs to.
|
||||
* @param {BinaryDecoder} decoder The decoder object to read data from.
|
||||
*/
|
||||
_fromBinary (y, decoder) {
|
||||
// TODO: set target, and add it to missing if not found
|
||||
// There is an edge case in p2p networks!
|
||||
const targetID = decoder.readID()
|
||||
this._targetID = targetID
|
||||
this._length = decoder.readVarUint()
|
||||
if (y.os.getItem(targetID) === null) {
|
||||
return [targetID]
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Transform the properties of this type to binary and write it to an
|
||||
* BinaryEncoder.
|
||||
*
|
||||
* This is called when this Item is sent to a remote peer.
|
||||
*
|
||||
* @param {BinaryEncoder} encoder The encoder to write data to.
|
||||
*/
|
||||
_toBinary (encoder) {
|
||||
encoder.writeUint8(getStructReference(this.constructor))
|
||||
encoder.writeID(this._targetID)
|
||||
encoder.writeVarUint(this._length)
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Integrates this Item into the shared structure.
|
||||
*
|
||||
* This method actually applies the change to the Yjs instance. In the case of
|
||||
* Delete it marks the delete target as deleted.
|
||||
*
|
||||
* * If created remotely (a remote user deleted something),
|
||||
* this Delete is applied to all structs in id-range.
|
||||
* * If created lokally (e.g. when y-array deletes a range of elements),
|
||||
* this struct is broadcasted only (it is already executed)
|
||||
*/
|
||||
_integrate (y, locallyCreated = false) {
|
||||
if (!locallyCreated) {
|
||||
// from remote
|
||||
const id = this._targetID
|
||||
deleteItemRange(y, id.user, id.clock, this._length, false)
|
||||
} else if (y.connector !== null) {
|
||||
// from local
|
||||
y.connector.broadcastStruct(this)
|
||||
}
|
||||
if (y.persistence !== null) {
|
||||
y.persistence.saveStruct(y, this)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform this YXml Type to a readable format.
|
||||
* Useful for logging as all Items and Delete implement this method.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_logString () {
|
||||
return `Delete - target: ${logID(this._targetID)}, len: ${this._length}`
|
||||
}
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
import { getStructReference } from '../Util/structReferences.js'
|
||||
import { RootFakeUserID } from '../Util/ID/RootID.js'
|
||||
import ID from '../Util/ID/ID.js'
|
||||
|
||||
// TODO should have the same base class as Item
|
||||
export default class GC {
|
||||
constructor () {
|
||||
this._id = null
|
||||
this._length = 0
|
||||
}
|
||||
|
||||
get _deleted () {
|
||||
return true
|
||||
}
|
||||
|
||||
_integrate (y) {
|
||||
const id = this._id
|
||||
const userState = y.ss.getState(id.user)
|
||||
if (id.clock === userState) {
|
||||
y.ss.setState(id.user, id.clock + this._length)
|
||||
}
|
||||
y.ds.mark(this._id, this._length, true)
|
||||
let n = y.os.put(this)
|
||||
const prev = n.prev().val
|
||||
if (prev !== null && prev.constructor === GC && prev._id.user === n.val._id.user && prev._id.clock + prev._length === n.val._id.clock) {
|
||||
// TODO: do merging for all items!
|
||||
prev._length += n.val._length
|
||||
y.os.delete(n.val._id)
|
||||
n = prev
|
||||
}
|
||||
if (n.val) {
|
||||
n = n.val
|
||||
}
|
||||
const next = y.os.findNext(n._id)
|
||||
if (next !== null && next.constructor === GC && next._id.user === n._id.user && next._id.clock === n._id.clock + n._length) {
|
||||
n._length += next._length
|
||||
y.os.delete(next._id)
|
||||
}
|
||||
if (id.user !== RootFakeUserID) {
|
||||
if (y.connector !== null && (y.connector._forwardAppliedStructs || id.user === y.userID)) {
|
||||
y.connector.broadcastStruct(this)
|
||||
}
|
||||
if (y.persistence !== null) {
|
||||
y.persistence.saveStruct(y, this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the properties of this type to binary and write it to an
|
||||
* BinaryEncoder.
|
||||
*
|
||||
* This is called when this Item is sent to a remote peer.
|
||||
*
|
||||
* @param {BinaryEncoder} encoder The encoder to write data to.
|
||||
* @private
|
||||
*/
|
||||
_toBinary (encoder) {
|
||||
encoder.writeUint8(getStructReference(this.constructor))
|
||||
encoder.writeID(this._id)
|
||||
encoder.writeVarUint(this._length)
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the next Item in a Decoder and fill this Item with the read data.
|
||||
*
|
||||
* This is called when data is received from a remote peer.
|
||||
*
|
||||
* @param {Y} y The Yjs instance that this Item belongs to.
|
||||
* @param {BinaryDecoder} decoder The decoder object to read data from.
|
||||
* @private
|
||||
*/
|
||||
_fromBinary (y, decoder) {
|
||||
const id = decoder.readID()
|
||||
this._id = id
|
||||
this._length = decoder.readVarUint()
|
||||
const missing = []
|
||||
if (y.ss.getState(id.user) < id.clock) {
|
||||
missing.push(new ID(id.user, id.clock - 1))
|
||||
}
|
||||
return missing
|
||||
}
|
||||
|
||||
_splitAt () {
|
||||
return this
|
||||
}
|
||||
|
||||
_clonePartial (diff) {
|
||||
const gc = new GC()
|
||||
gc._id = new ID(this._id.user, this._id.clock + diff)
|
||||
gc._length = this._length - diff
|
||||
return gc
|
||||
}
|
||||
}
|
||||
@@ -1,527 +0,0 @@
|
||||
import { getStructReference } from '../Util/structReferences.js'
|
||||
import ID from '../Util/ID/ID.js'
|
||||
import { default as RootID, RootFakeUserID } from '../Util/ID/RootID.js'
|
||||
import Delete from './Delete.js'
|
||||
import { transactionTypeChanged } from '../Transaction.js'
|
||||
import GC from './GC.js'
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Helper utility to split an Item (see {@link Item#_splitAt})
|
||||
* - copies all properties from a to b
|
||||
* - connects a to b
|
||||
* - assigns the correct _id
|
||||
* - saves b to os
|
||||
*/
|
||||
export function splitHelper (y, a, b, diff) {
|
||||
const aID = a._id
|
||||
b._id = new ID(aID.user, aID.clock + diff)
|
||||
b._origin = a
|
||||
b._left = a
|
||||
b._right = a._right
|
||||
if (b._right !== null) {
|
||||
b._right._left = b
|
||||
}
|
||||
b._right_origin = a._right_origin
|
||||
// do not set a._right_origin, as this will lead to problems when syncing
|
||||
a._right = b
|
||||
b._parent = a._parent
|
||||
b._parentSub = a._parentSub
|
||||
b._deleted = a._deleted
|
||||
// now search all relevant items to the right and update origin
|
||||
// if origin is not it foundOrigins, we don't have to search any longer
|
||||
let foundOrigins = new Set()
|
||||
foundOrigins.add(a)
|
||||
let o = b._right
|
||||
while (o !== null && foundOrigins.has(o._origin)) {
|
||||
if (o._origin === a) {
|
||||
o._origin = b
|
||||
}
|
||||
foundOrigins.add(o)
|
||||
o = o._right
|
||||
}
|
||||
y.os.put(b)
|
||||
if (y._transaction.newTypes.has(a)) {
|
||||
y._transaction.newTypes.add(b)
|
||||
} else if (y._transaction.deletedStructs.has(a)) {
|
||||
y._transaction.deletedStructs.add(b)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract class that represents any content.
|
||||
*/
|
||||
export default class Item {
|
||||
constructor () {
|
||||
/**
|
||||
* The uniqe identifier of this type.
|
||||
* @type {ID}
|
||||
*/
|
||||
this._id = null
|
||||
/**
|
||||
* The item that was originally to the left of this item.
|
||||
* @type {Item}
|
||||
*/
|
||||
this._origin = null
|
||||
/**
|
||||
* The item that is currently to the left of this item.
|
||||
* @type {Item}
|
||||
*/
|
||||
this._left = null
|
||||
/**
|
||||
* The item that is currently to the right of this item.
|
||||
* @type {Item}
|
||||
*/
|
||||
this._right = null
|
||||
/**
|
||||
* The item that was originally to the right of this item.
|
||||
* @type {Item}
|
||||
*/
|
||||
this._right_origin = null
|
||||
/**
|
||||
* The parent type.
|
||||
* @type {Y|YType}
|
||||
*/
|
||||
this._parent = null
|
||||
/**
|
||||
* If the parent refers to this item with some kind of key (e.g. YMap, the
|
||||
* key is specified here. The key is then used to refer to the list in which
|
||||
* to insert this item. If `parentSub = null` type._start is the list in
|
||||
* which to insert to. Otherwise it is `parent._start`.
|
||||
* @type {String}
|
||||
*/
|
||||
this._parentSub = null
|
||||
/**
|
||||
* Whether this item was deleted or not.
|
||||
* @type {Boolean}
|
||||
*/
|
||||
this._deleted = false
|
||||
/**
|
||||
* If this type's effect is reundone this type refers to the type that undid
|
||||
* this operation.
|
||||
* @type {Item}
|
||||
*/
|
||||
this._redone = null
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an Item with the same effect as this Item (without position effect)
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_copy () {
|
||||
return new this.constructor()
|
||||
}
|
||||
|
||||
/**
|
||||
* Redoes the effect of this operation.
|
||||
*
|
||||
* @param {Y} y The Yjs instance.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_redo (y) {
|
||||
if (this._redone !== null) {
|
||||
return this._redone
|
||||
}
|
||||
let struct = this._copy()
|
||||
let left = this._left
|
||||
let right = this
|
||||
let parent = this._parent
|
||||
// make sure that parent is redone
|
||||
if (parent._deleted === true && parent._redone === null) {
|
||||
parent._redo(y)
|
||||
}
|
||||
if (parent._redone !== null) {
|
||||
parent = parent._redone
|
||||
// find next cloned items
|
||||
while (left !== null) {
|
||||
if (left._redone !== null && left._redone._parent === parent) {
|
||||
left = left._redone
|
||||
break
|
||||
}
|
||||
left = left._left
|
||||
}
|
||||
while (right !== null) {
|
||||
if (right._redone !== null && right._redone._parent === parent) {
|
||||
right = right._redone
|
||||
}
|
||||
right = right._right
|
||||
}
|
||||
}
|
||||
struct._origin = left
|
||||
struct._left = left
|
||||
struct._right = right
|
||||
struct._right_origin = right
|
||||
struct._parent = parent
|
||||
struct._parentSub = this._parentSub
|
||||
struct._integrate(y)
|
||||
this._redone = struct
|
||||
return struct
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the last content address of this Item.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
get _lastId () {
|
||||
return new ID(this._id.user, this._id.clock + this._length - 1)
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the length of this Item.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
get _length () {
|
||||
return 1
|
||||
}
|
||||
|
||||
/**
|
||||
* Should return false if this Item is some kind of meta information
|
||||
* (e.g. format information).
|
||||
*
|
||||
* * Whether this Item should be addressable via `yarray.get(i)`
|
||||
* * Whether this Item should be counted when computing yarray.length
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
get _countable () {
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits this Item so that another Items can be inserted in-between.
|
||||
* This must be overwritten if _length > 1
|
||||
* Returns right part after split
|
||||
* * diff === 0 => this
|
||||
* * diff === length => this._right
|
||||
* * otherwise => split _content and return right part of split
|
||||
* (see {@link ItemJSON}/{@link ItemString} for implementation)
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_splitAt (y, diff) {
|
||||
if (diff === 0) {
|
||||
return this
|
||||
}
|
||||
return this._right
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark this Item as deleted.
|
||||
*
|
||||
* @param {Y} y The Yjs instance
|
||||
* @param {boolean} createDelete Whether to propagate a message that this
|
||||
* Type was deleted.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_delete (y, createDelete = true) {
|
||||
if (!this._deleted) {
|
||||
this._deleted = true
|
||||
y.ds.mark(this._id, this._length, false)
|
||||
let del = new Delete()
|
||||
del._targetID = this._id
|
||||
del._length = this._length
|
||||
if (createDelete) {
|
||||
// broadcast and persists Delete
|
||||
del._integrate(y, true)
|
||||
} else if (y.persistence !== null) {
|
||||
// only persist Delete
|
||||
y.persistence.saveStruct(y, del)
|
||||
}
|
||||
transactionTypeChanged(y, this._parent, this._parentSub)
|
||||
y._transaction.deletedStructs.add(this)
|
||||
}
|
||||
}
|
||||
|
||||
_gcChildren (y) {}
|
||||
|
||||
_gc (y) {
|
||||
const gc = new GC()
|
||||
gc._id = this._id
|
||||
gc._length = this._length
|
||||
y.os.delete(this._id)
|
||||
gc._integrate(y)
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called right before this Item receives any children.
|
||||
* It can be overwritten to apply pending changes before applying remote changes
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_beforeChange () {
|
||||
// nop
|
||||
}
|
||||
|
||||
/**
|
||||
* Integrates this Item into the shared structure.
|
||||
*
|
||||
* This method actually applies the change to the Yjs instance. In case of
|
||||
* Item it connects _left and _right to this Item and calls the
|
||||
* {@link Item#beforeChange} method.
|
||||
*
|
||||
* * Integrate the struct so that other types/structs can see it
|
||||
* * Add this struct to y.os
|
||||
* * Check if this is struct deleted
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_integrate (y) {
|
||||
y._transaction.newTypes.add(this)
|
||||
const parent = this._parent
|
||||
const selfID = this._id
|
||||
const user = selfID === null ? y.userID : selfID.user
|
||||
const userState = y.ss.getState(user)
|
||||
if (selfID === null) {
|
||||
this._id = y.ss.getNextID(this._length)
|
||||
} else if (selfID.user === RootFakeUserID) {
|
||||
// nop
|
||||
} else if (selfID.clock < userState) {
|
||||
// already applied..
|
||||
return []
|
||||
} else if (selfID.clock === userState) {
|
||||
y.ss.setState(selfID.user, userState + this._length)
|
||||
} else {
|
||||
// missing content from user
|
||||
throw new Error('Can not apply yet!')
|
||||
}
|
||||
if (!parent._deleted && !y._transaction.changedTypes.has(parent) && !y._transaction.newTypes.has(parent)) {
|
||||
// this is the first time parent is updated
|
||||
// or this types is new
|
||||
this._parent._beforeChange()
|
||||
}
|
||||
|
||||
/*
|
||||
# $this has to find a unique position between origin and the next known character
|
||||
# case 1: $origin equals $o.origin: the $creator parameter decides if left or right
|
||||
# let $OL= [o1,o2,o3,o4], whereby $this is to be inserted between o1 and o4
|
||||
# o2,o3 and o4 origin is 1 (the position of o2)
|
||||
# there is the case that $this.creator < o2.creator, but o3.creator < $this.creator
|
||||
# then o2 knows o3. Since on another client $OL could be [o1,o3,o4] the problem is complex
|
||||
# therefore $this would be always to the right of o3
|
||||
# case 2: $origin < $o.origin
|
||||
# if current $this insert_position > $o origin: $this ins
|
||||
# else $insert_position will not change
|
||||
# (maybe we encounter case 1 later, then this will be to the right of $o)
|
||||
# case 3: $origin > $o.origin
|
||||
# $this insert_position is to the left of $o (forever!)
|
||||
*/
|
||||
// handle conflicts
|
||||
let o
|
||||
// set o to the first conflicting item
|
||||
if (this._left !== null) {
|
||||
o = this._left._right
|
||||
} else if (this._parentSub !== null) {
|
||||
o = this._parent._map.get(this._parentSub) || null
|
||||
} else {
|
||||
o = this._parent._start
|
||||
}
|
||||
let conflictingItems = new Set()
|
||||
let itemsBeforeOrigin = new Set()
|
||||
// Let c in conflictingItems, b in itemsBeforeOrigin
|
||||
// ***{origin}bbbb{this}{c,b}{c,b}{o}***
|
||||
// Note that conflictingItems is a subset of itemsBeforeOrigin
|
||||
while (o !== null && o !== this._right) {
|
||||
itemsBeforeOrigin.add(o)
|
||||
conflictingItems.add(o)
|
||||
if (this._origin === o._origin) {
|
||||
// case 1
|
||||
if (o._id.user < this._id.user) {
|
||||
this._left = o
|
||||
conflictingItems.clear()
|
||||
}
|
||||
} else if (itemsBeforeOrigin.has(o._origin)) {
|
||||
// case 2
|
||||
if (!conflictingItems.has(o._origin)) {
|
||||
this._left = o
|
||||
conflictingItems.clear()
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
// TODO: try to use right_origin instead.
|
||||
// Then you could basically omit conflictingItems!
|
||||
// Note: you probably can't use right_origin in every case.. only when setting _left
|
||||
o = o._right
|
||||
}
|
||||
// reconnect left/right + update parent map/start if necessary
|
||||
const parentSub = this._parentSub
|
||||
if (this._left === null) {
|
||||
let right
|
||||
if (parentSub !== null) {
|
||||
const pmap = parent._map
|
||||
right = pmap.get(parentSub) || null
|
||||
pmap.set(parentSub, this)
|
||||
} else {
|
||||
right = parent._start
|
||||
parent._start = this
|
||||
}
|
||||
this._right = right
|
||||
if (right !== null) {
|
||||
right._left = this
|
||||
}
|
||||
} else {
|
||||
const left = this._left
|
||||
const right = left._right
|
||||
this._right = right
|
||||
left._right = this
|
||||
if (right !== null) {
|
||||
right._left = this
|
||||
}
|
||||
}
|
||||
if (parent._deleted) {
|
||||
this._delete(y, false)
|
||||
}
|
||||
y.os.put(this)
|
||||
transactionTypeChanged(y, parent, parentSub)
|
||||
if (this._id.user !== RootFakeUserID) {
|
||||
if (y.connector !== null && (y.connector._forwardAppliedStructs || this._id.user === y.userID)) {
|
||||
y.connector.broadcastStruct(this)
|
||||
}
|
||||
if (y.persistence !== null) {
|
||||
y.persistence.saveStruct(y, this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the properties of this type to binary and write it to an
|
||||
* BinaryEncoder.
|
||||
*
|
||||
* This is called when this Item is sent to a remote peer.
|
||||
*
|
||||
* @param {BinaryEncoder} encoder The encoder to write data to.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_toBinary (encoder) {
|
||||
encoder.writeUint8(getStructReference(this.constructor))
|
||||
let info = 0
|
||||
if (this._origin !== null) {
|
||||
info += 0b1 // origin is defined
|
||||
}
|
||||
// TODO: remove
|
||||
/* no longer send _left
|
||||
if (this._left !== this._origin) {
|
||||
info += 0b10 // do not copy origin to left
|
||||
}
|
||||
*/
|
||||
if (this._right_origin !== null) {
|
||||
info += 0b100
|
||||
}
|
||||
if (this._parentSub !== null) {
|
||||
info += 0b1000
|
||||
}
|
||||
encoder.writeUint8(info)
|
||||
encoder.writeID(this._id)
|
||||
if (info & 0b1) {
|
||||
encoder.writeID(this._origin._lastId)
|
||||
}
|
||||
// TODO: remove
|
||||
/* see above
|
||||
if (info & 0b10) {
|
||||
encoder.writeID(this._left._lastId)
|
||||
}
|
||||
*/
|
||||
if (info & 0b100) {
|
||||
encoder.writeID(this._right_origin._id)
|
||||
}
|
||||
if ((info & 0b101) === 0) {
|
||||
// neither origin nor right is defined
|
||||
encoder.writeID(this._parent._id)
|
||||
}
|
||||
if (info & 0b1000) {
|
||||
encoder.writeVarString(JSON.stringify(this._parentSub))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the next Item in a Decoder and fill this Item with the read data.
|
||||
*
|
||||
* This is called when data is received from a remote peer.
|
||||
*
|
||||
* @param {Y} y The Yjs instance that this Item belongs to.
|
||||
* @param {BinaryDecoder} decoder The decoder object to read data from.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_fromBinary (y, decoder) {
|
||||
let missing = []
|
||||
const info = decoder.readUint8()
|
||||
const id = decoder.readID()
|
||||
this._id = id
|
||||
// read origin
|
||||
if (info & 0b1) {
|
||||
// origin != null
|
||||
const originID = decoder.readID()
|
||||
// we have to query for left again because it might have been split/merged..
|
||||
const origin = y.os.getItemCleanEnd(originID)
|
||||
if (origin === null) {
|
||||
missing.push(originID)
|
||||
} else {
|
||||
this._origin = origin
|
||||
this._left = this._origin
|
||||
}
|
||||
}
|
||||
// read right
|
||||
if (info & 0b100) {
|
||||
// right != null
|
||||
const rightID = decoder.readID()
|
||||
// we have to query for right again because it might have been split/merged..
|
||||
const right = y.os.getItemCleanStart(rightID)
|
||||
if (right === null) {
|
||||
missing.push(rightID)
|
||||
} else {
|
||||
this._right = right
|
||||
this._right_origin = right
|
||||
}
|
||||
}
|
||||
// read parent
|
||||
if ((info & 0b101) === 0) {
|
||||
// neither origin nor right is defined
|
||||
const parentID = decoder.readID()
|
||||
// parent does not change, so we don't have to search for it again
|
||||
if (this._parent === null) {
|
||||
let parent
|
||||
if (parentID.constructor === RootID) {
|
||||
parent = y.os.get(parentID)
|
||||
} else {
|
||||
parent = y.os.getItem(parentID)
|
||||
}
|
||||
if (parent === null) {
|
||||
missing.push(parentID)
|
||||
} else {
|
||||
this._parent = parent
|
||||
}
|
||||
}
|
||||
} else if (this._parent === null) {
|
||||
if (this._origin !== null) {
|
||||
if (this._origin.constructor === GC) {
|
||||
// if origin is a gc, set parent also gc'd
|
||||
this._parent = this._origin
|
||||
} else {
|
||||
this._parent = this._origin._parent
|
||||
}
|
||||
} else if (this._right_origin !== null) {
|
||||
// if origin is a gc, set parent also gc'd
|
||||
if (this._right_origin.constructor === GC) {
|
||||
this._parent = this._right_origin
|
||||
} else {
|
||||
this._parent = this._right_origin._parent
|
||||
}
|
||||
}
|
||||
}
|
||||
if (info & 0b1000) {
|
||||
// TODO: maybe put this in read parent condition (you can also read parentsub from left/right)
|
||||
this._parentSub = JSON.parse(decoder.readVarString())
|
||||
}
|
||||
if (y.ss.getState(id.user) < id.clock) {
|
||||
missing.push(new ID(id.user, id.clock - 1))
|
||||
}
|
||||
return missing
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
import { default as Item } from './Item.js'
|
||||
import { logItemHelper } from '../MessageHandler/messageToString.js'
|
||||
|
||||
export default class ItemEmbed extends Item {
|
||||
constructor () {
|
||||
super()
|
||||
this.embed = null
|
||||
}
|
||||
_copy (undeleteChildren, copyPosition) {
|
||||
let struct = super._copy(undeleteChildren, copyPosition)
|
||||
struct.embed = this.embed
|
||||
return struct
|
||||
}
|
||||
get _length () {
|
||||
return 1
|
||||
}
|
||||
_fromBinary (y, decoder) {
|
||||
const missing = super._fromBinary(y, decoder)
|
||||
this.embed = JSON.parse(decoder.readVarString())
|
||||
return missing
|
||||
}
|
||||
_toBinary (encoder) {
|
||||
super._toBinary(encoder)
|
||||
encoder.writeVarString(JSON.stringify(this.embed))
|
||||
}
|
||||
/**
|
||||
* Transform this YXml Type to a readable format.
|
||||
* Useful for logging as all Items and Delete implement this method.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_logString () {
|
||||
return logItemHelper('ItemEmbed', this, `embed:${JSON.stringify(this.embed)}`)
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
import { default as Item } from './Item.js'
|
||||
import { logItemHelper } from '../MessageHandler/messageToString.js'
|
||||
|
||||
export default class ItemFormat extends Item {
|
||||
constructor () {
|
||||
super()
|
||||
this.key = null
|
||||
this.value = null
|
||||
}
|
||||
_copy (undeleteChildren, copyPosition) {
|
||||
let struct = super._copy(undeleteChildren, copyPosition)
|
||||
struct.key = this.key
|
||||
struct.value = this.value
|
||||
return struct
|
||||
}
|
||||
get _length () {
|
||||
return 1
|
||||
}
|
||||
get _countable () {
|
||||
return false
|
||||
}
|
||||
_fromBinary (y, decoder) {
|
||||
const missing = super._fromBinary(y, decoder)
|
||||
this.key = decoder.readVarString()
|
||||
this.value = JSON.parse(decoder.readVarString())
|
||||
return missing
|
||||
}
|
||||
_toBinary (encoder) {
|
||||
super._toBinary(encoder)
|
||||
encoder.writeVarString(this.key)
|
||||
encoder.writeVarString(JSON.stringify(this.value))
|
||||
}
|
||||
/**
|
||||
* Transform this YXml Type to a readable format.
|
||||
* Useful for logging as all Items and Delete implement this method.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_logString () {
|
||||
return logItemHelper('ItemFormat', this, `key:${JSON.stringify(this.key)},value:${JSON.stringify(this.value)}`)
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
import { splitHelper, default as Item } from './Item.js'
|
||||
import { logItemHelper } from '../MessageHandler/messageToString.js'
|
||||
|
||||
export default class ItemJSON extends Item {
|
||||
constructor () {
|
||||
super()
|
||||
this._content = null
|
||||
}
|
||||
_copy () {
|
||||
let struct = super._copy()
|
||||
struct._content = this._content
|
||||
return struct
|
||||
}
|
||||
get _length () {
|
||||
return this._content.length
|
||||
}
|
||||
_fromBinary (y, decoder) {
|
||||
let missing = super._fromBinary(y, decoder)
|
||||
let len = decoder.readVarUint()
|
||||
this._content = new Array(len)
|
||||
for (let i = 0; i < len; i++) {
|
||||
const ctnt = decoder.readVarString()
|
||||
let parsed
|
||||
if (ctnt === 'undefined') {
|
||||
parsed = undefined
|
||||
} else {
|
||||
parsed = JSON.parse(ctnt)
|
||||
}
|
||||
this._content[i] = parsed
|
||||
}
|
||||
return missing
|
||||
}
|
||||
_toBinary (encoder) {
|
||||
super._toBinary(encoder)
|
||||
let len = this._content.length
|
||||
encoder.writeVarUint(len)
|
||||
for (let i = 0; i < len; i++) {
|
||||
let encoded
|
||||
let content = this._content[i]
|
||||
if (content === undefined) {
|
||||
encoded = 'undefined'
|
||||
} else {
|
||||
encoded = JSON.stringify(content)
|
||||
}
|
||||
encoder.writeVarString(encoded)
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Transform this YXml Type to a readable format.
|
||||
* Useful for logging as all Items and Delete implement this method.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_logString () {
|
||||
return logItemHelper('ItemJSON', this, `content:${JSON.stringify(this._content)}`)
|
||||
}
|
||||
_splitAt (y, diff) {
|
||||
if (diff === 0) {
|
||||
return this
|
||||
} else if (diff >= this._length) {
|
||||
return this._right
|
||||
}
|
||||
let item = new ItemJSON()
|
||||
item._content = this._content.splice(diff)
|
||||
splitHelper(y, this, item, diff)
|
||||
return item
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
import { splitHelper, default as Item } from './Item.js'
|
||||
import { logItemHelper } from '../MessageHandler/messageToString.js'
|
||||
|
||||
export default class ItemString extends Item {
|
||||
constructor () {
|
||||
super()
|
||||
this._content = null
|
||||
}
|
||||
_copy () {
|
||||
let struct = super._copy()
|
||||
struct._content = this._content
|
||||
return struct
|
||||
}
|
||||
get _length () {
|
||||
return this._content.length
|
||||
}
|
||||
_fromBinary (y, decoder) {
|
||||
let missing = super._fromBinary(y, decoder)
|
||||
this._content = decoder.readVarString()
|
||||
return missing
|
||||
}
|
||||
_toBinary (encoder) {
|
||||
super._toBinary(encoder)
|
||||
encoder.writeVarString(this._content)
|
||||
}
|
||||
/**
|
||||
* Transform this YXml Type to a readable format.
|
||||
* Useful for logging as all Items and Delete implement this method.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_logString () {
|
||||
return logItemHelper('ItemString', this, `content:"${this._content}"`)
|
||||
}
|
||||
_splitAt (y, diff) {
|
||||
if (diff === 0) {
|
||||
return this
|
||||
} else if (diff >= this._length) {
|
||||
return this._right
|
||||
}
|
||||
let item = new ItemString()
|
||||
item._content = this._content.slice(diff)
|
||||
this._content = this._content.slice(0, diff)
|
||||
splitHelper(y, this, item, diff)
|
||||
return item
|
||||
}
|
||||
}
|
||||
@@ -1,243 +0,0 @@
|
||||
import Item from './Item.js'
|
||||
import EventHandler from '../Util/EventHandler.js'
|
||||
import ID from '../Util/ID/ID.js'
|
||||
|
||||
// restructure children as if they were inserted one after another
|
||||
function integrateChildren (y, start) {
|
||||
let right
|
||||
do {
|
||||
right = start._right
|
||||
start._right = null
|
||||
start._right_origin = null
|
||||
start._origin = start._left
|
||||
start._integrate(y)
|
||||
start = right
|
||||
} while (right !== null)
|
||||
}
|
||||
|
||||
export function getListItemIDByPosition (type, i) {
|
||||
let pos = 0
|
||||
let n = type._start
|
||||
while (n !== null) {
|
||||
if (!n._deleted) {
|
||||
if (pos <= i && i < pos + n._length) {
|
||||
const id = n._id
|
||||
return new ID(id.user, id.clock + i - pos)
|
||||
}
|
||||
pos++
|
||||
}
|
||||
n = n._right
|
||||
}
|
||||
}
|
||||
|
||||
function gcChildren (y, item) {
|
||||
while (item !== null) {
|
||||
item._delete(y, false, true)
|
||||
item._gc(y)
|
||||
item = item._right
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract Yjs Type class
|
||||
*/
|
||||
export default class Type extends Item {
|
||||
constructor () {
|
||||
super()
|
||||
this._map = new Map()
|
||||
this._start = null
|
||||
this._y = null
|
||||
this._eventHandler = new EventHandler()
|
||||
this._deepEventHandler = new EventHandler()
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the path from this type to the specified target.
|
||||
*
|
||||
* @example
|
||||
* It should be accessible via `this.get(result[0]).get(result[1])..`
|
||||
* const path = type.getPathTo(child)
|
||||
* // assuming `type instanceof YArray`
|
||||
* console.log(path) // might look like => [2, 'key1']
|
||||
* child === type.get(path[0]).get(path[1])
|
||||
*
|
||||
* @param {YType} type Type target
|
||||
* @return {Array<string>} Path to the target
|
||||
*/
|
||||
getPathTo (type) {
|
||||
if (type === this) {
|
||||
return []
|
||||
}
|
||||
const path = []
|
||||
const y = this._y
|
||||
while (type !== this && type !== y) {
|
||||
let parent = type._parent
|
||||
if (type._parentSub !== null) {
|
||||
path.unshift(type._parentSub)
|
||||
} else {
|
||||
// parent is array-ish
|
||||
for (let [i, child] of parent) {
|
||||
if (child === type) {
|
||||
path.unshift(i)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
type = parent
|
||||
}
|
||||
if (type !== this) {
|
||||
throw new Error('The type is not a child of this node')
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Call event listeners with an event. This will also add an event to all
|
||||
* parents (for `.observeDeep` handlers).
|
||||
*/
|
||||
_callEventHandler (transaction, event) {
|
||||
const changedParentTypes = transaction.changedParentTypes
|
||||
this._eventHandler.callEventListeners(transaction, event)
|
||||
let type = this
|
||||
while (type !== this._y) {
|
||||
let events = changedParentTypes.get(type)
|
||||
if (events === undefined) {
|
||||
events = []
|
||||
changedParentTypes.set(type, events)
|
||||
}
|
||||
events.push(event)
|
||||
type = type._parent
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Helper method to transact if the y instance is available.
|
||||
*
|
||||
* TODO: Currently event handlers are not thrown when a type is not registered
|
||||
* with a Yjs instance.
|
||||
*/
|
||||
_transact (f) {
|
||||
const y = this._y
|
||||
if (y !== null) {
|
||||
y.transact(f)
|
||||
} else {
|
||||
f(y)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Observe all events that are created on this type.
|
||||
*
|
||||
* @param {Function} f Observer function
|
||||
*/
|
||||
observe (f) {
|
||||
this._eventHandler.addEventListener(f)
|
||||
}
|
||||
|
||||
/**
|
||||
* Observe all events that are created by this type and its children.
|
||||
*
|
||||
* @param {Function} f Observer function
|
||||
*/
|
||||
observeDeep (f) {
|
||||
this._deepEventHandler.addEventListener(f)
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister an observer function.
|
||||
*
|
||||
* @param {Function} f Observer function
|
||||
*/
|
||||
unobserve (f) {
|
||||
this._eventHandler.removeEventListener(f)
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister an observer function.
|
||||
*
|
||||
* @param {Function} f Observer function
|
||||
*/
|
||||
unobserveDeep (f) {
|
||||
this._deepEventHandler.removeEventListener(f)
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Integrate this type into the Yjs instance.
|
||||
*
|
||||
* * Save this struct in the os
|
||||
* * This type is sent to other client
|
||||
* * Observer functions are fired
|
||||
*
|
||||
* @param {Y} y The Yjs instance
|
||||
*/
|
||||
_integrate (y) {
|
||||
super._integrate(y)
|
||||
this._y = y
|
||||
// when integrating children we must make sure to
|
||||
// integrate start
|
||||
const start = this._start
|
||||
if (start !== null) {
|
||||
this._start = null
|
||||
integrateChildren(y, start)
|
||||
}
|
||||
// integrate map children
|
||||
const map = this._map
|
||||
this._map = new Map()
|
||||
for (let t of map.values()) {
|
||||
// TODO make sure that right elements are deleted!
|
||||
integrateChildren(y, t)
|
||||
}
|
||||
}
|
||||
|
||||
_gcChildren (y) {
|
||||
gcChildren(y, this._start)
|
||||
this._start = null
|
||||
this._map.forEach(item => {
|
||||
gcChildren(y, item)
|
||||
})
|
||||
this._map = new Map()
|
||||
}
|
||||
|
||||
_gc (y) {
|
||||
this._gcChildren(y)
|
||||
super._gc(y)
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Mark this Item as deleted.
|
||||
*
|
||||
* @param {Y} y The Yjs instance
|
||||
* @param {boolean} createDelete Whether to propagate a message that this
|
||||
* Type was deleted.
|
||||
* @param {boolean} [gcChildren=y._hasUndoManager===false] Whether to garbage
|
||||
* collect the children of this type.
|
||||
*/
|
||||
_delete (y, createDelete, gcChildren) {
|
||||
if (gcChildren === undefined || !y.gcEnabled) {
|
||||
gcChildren = y._hasUndoManager === false && y.gcEnabled
|
||||
}
|
||||
super._delete(y, createDelete, gcChildren)
|
||||
y._transaction.changedTypes.delete(this)
|
||||
// delete map types
|
||||
for (let value of this._map.values()) {
|
||||
if (value instanceof Item && !value._deleted) {
|
||||
value._delete(y, false, gcChildren)
|
||||
}
|
||||
}
|
||||
// delete array types
|
||||
let t = this._start
|
||||
while (t !== null) {
|
||||
if (!t._deleted) {
|
||||
t._delete(y, false, gcChildren)
|
||||
}
|
||||
t = t._right
|
||||
}
|
||||
if (gcChildren) {
|
||||
this._gcChildren(y)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
|
||||
/**
|
||||
* A transaction is created for every change on the Yjs model. It is possible
|
||||
* to bundle changes on the Yjs model in a single transaction to
|
||||
* minimize the number on messages sent and the number of observer calls.
|
||||
* If possible the user of this library should bundle as many changes as
|
||||
* possible. Here is an example to illustrate the advantages of bundling:
|
||||
*
|
||||
* @example
|
||||
* const map = y.define('map', YMap)
|
||||
* // Log content when change is triggered
|
||||
* map.observe(function () {
|
||||
* console.log('change triggered')
|
||||
* })
|
||||
* // Each change on the map type triggers a log message:
|
||||
* map.set('a', 0) // => "change triggered"
|
||||
* map.set('b', 0) // => "change triggered"
|
||||
* // When put in a transaction, it will trigger the log after the transaction:
|
||||
* y.transact(function () {
|
||||
* map.set('a', 1)
|
||||
* map.set('b', 1)
|
||||
* }) // => "change triggered"
|
||||
*
|
||||
*/
|
||||
export default class Transaction {
|
||||
constructor (y) {
|
||||
/**
|
||||
* @type {Y} The Yjs instance.
|
||||
*/
|
||||
this.y = y
|
||||
/**
|
||||
* All new types that are added during a transaction.
|
||||
* @type {Set<Item>}
|
||||
*/
|
||||
this.newTypes = new Set()
|
||||
/**
|
||||
* All types that were directly modified (property added or child
|
||||
* inserted/deleted). New types are not included in this Set.
|
||||
* Maps from type to parentSubs (`item._parentSub = null` for YArray)
|
||||
* @type {Set<YType,String>}
|
||||
*/
|
||||
this.changedTypes = new Map()
|
||||
// TODO: rename deletedTypes
|
||||
/**
|
||||
* Set of all deleted Types and Structs.
|
||||
* @type {Set<Item>}
|
||||
*/
|
||||
this.deletedStructs = new Set()
|
||||
/**
|
||||
* Saves the old state set of the Yjs instance. If a state was modified,
|
||||
* the original value is saved here.
|
||||
* @type {Map<Number,Number>}
|
||||
*/
|
||||
this.beforeState = new Map()
|
||||
/**
|
||||
* Stores the events for the types that observe also child elements.
|
||||
* It is mainly used by `observeDeep`.
|
||||
* @type {Map<YType,Array<YEvent>>}
|
||||
*/
|
||||
this.changedParentTypes = new Map()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
export function transactionTypeChanged (y, type, sub) {
|
||||
if (type !== y && !type._deleted && !y._transaction.newTypes.has(type)) {
|
||||
const changedTypes = y._transaction.changedTypes
|
||||
let subs = changedTypes.get(type)
|
||||
if (subs === undefined) {
|
||||
// create if it doesn't exist yet
|
||||
subs = new Set()
|
||||
changedTypes.set(type, subs)
|
||||
}
|
||||
subs.add(sub)
|
||||
}
|
||||
}
|
||||
@@ -1,378 +0,0 @@
|
||||
import Type from '../../Struct/Type.js'
|
||||
import ItemJSON from '../../Struct/ItemJSON.js'
|
||||
import ItemString from '../../Struct/ItemString.js'
|
||||
import { logID, logItemHelper } from '../../MessageHandler/messageToString.js'
|
||||
import YEvent from '../../Util/YEvent.js'
|
||||
|
||||
/**
|
||||
* Event that describes the changes on a YArray
|
||||
*
|
||||
* @param {YArray} yarray The changed type
|
||||
* @param {Boolean} remote Whether the changed was caused by a remote peer
|
||||
* @param {Transaction} transaction The transaction object
|
||||
*/
|
||||
export class YArrayEvent extends YEvent {
|
||||
constructor (yarray, remote, transaction) {
|
||||
super(yarray)
|
||||
this.remote = remote
|
||||
this._transaction = transaction
|
||||
this._addedElements = null
|
||||
this._removedElements = null
|
||||
}
|
||||
|
||||
/**
|
||||
* Child elements that were added in this transaction.
|
||||
*
|
||||
* @return {Set}
|
||||
*/
|
||||
get addedElements () {
|
||||
if (this._addedElements === null) {
|
||||
const target = this.target
|
||||
const transaction = this._transaction
|
||||
const addedElements = new Set()
|
||||
transaction.newTypes.forEach(function (type) {
|
||||
if (type._parent === target && !transaction.deletedStructs.has(type)) {
|
||||
addedElements.add(type)
|
||||
}
|
||||
})
|
||||
this._addedElements = addedElements
|
||||
}
|
||||
return this._addedElements
|
||||
}
|
||||
|
||||
/**
|
||||
* Child elements that were removed in this transaction.
|
||||
*
|
||||
* @return {Set}
|
||||
*/
|
||||
get removedElements () {
|
||||
if (this._removedElements === null) {
|
||||
const target = this.target
|
||||
const transaction = this._transaction
|
||||
const removedElements = new Set()
|
||||
transaction.deletedStructs.forEach(function (struct) {
|
||||
if (struct._parent === target && !transaction.newTypes.has(struct)) {
|
||||
removedElements.add(struct)
|
||||
}
|
||||
})
|
||||
this._removedElements = removedElements
|
||||
}
|
||||
return this._removedElements
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A shared Array implementation.
|
||||
*/
|
||||
export default class YArray extends Type {
|
||||
/**
|
||||
* @private
|
||||
* Creates YArray Event and calls observers.
|
||||
*/
|
||||
_callObserver (transaction, parentSubs, remote) {
|
||||
this._callEventHandler(transaction, new YArrayEvent(this, remote, transaction))
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the i-th element from a YArray.
|
||||
*
|
||||
* @param {Integer} index The index of the element to return from the YArray
|
||||
*/
|
||||
get (index) {
|
||||
let n = this._start
|
||||
while (n !== null) {
|
||||
if (!n._deleted && n._countable) {
|
||||
if (index < n._length) {
|
||||
if (n.constructor === ItemJSON || n.constructor === ItemString) {
|
||||
return n._content[index]
|
||||
} else {
|
||||
return n
|
||||
}
|
||||
}
|
||||
index -= n._length
|
||||
}
|
||||
n = n._right
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms this YArray to a JavaScript Array.
|
||||
*
|
||||
* @return {Array}
|
||||
*/
|
||||
toArray () {
|
||||
return this.map(c => c)
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms this Shared Type to a JSON object.
|
||||
*
|
||||
* @return {Array}
|
||||
*/
|
||||
toJSON () {
|
||||
return this.map(c => {
|
||||
if (c instanceof Type) {
|
||||
if (c.toJSON !== null) {
|
||||
return c.toJSON()
|
||||
} else {
|
||||
return c.toString()
|
||||
}
|
||||
}
|
||||
return c
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an Array with the result of calling a provided function on every
|
||||
* element of this YArray.
|
||||
*
|
||||
* @param {Function} f Function that produces an element of the new Array
|
||||
* @return {Array} A new array with each element being the result of the
|
||||
* callback function
|
||||
*/
|
||||
map (f) {
|
||||
const res = []
|
||||
this.forEach((c, i) => {
|
||||
res.push(f(c, i, this))
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a provided function on once on overy element of this YArray.
|
||||
*
|
||||
* @param {Function} f A function to execute on every element of this YArray.
|
||||
*/
|
||||
forEach (f) {
|
||||
let index = 0
|
||||
let n = this._start
|
||||
while (n !== null) {
|
||||
if (!n._deleted && n._countable) {
|
||||
if (n instanceof Type) {
|
||||
f(n, index++, this)
|
||||
} else {
|
||||
const content = n._content
|
||||
const contentLen = content.length
|
||||
for (let i = 0; i < contentLen; i++) {
|
||||
index++
|
||||
f(content[i], index, this)
|
||||
}
|
||||
}
|
||||
}
|
||||
n = n._right
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the length of this YArray.
|
||||
*/
|
||||
get length () {
|
||||
let length = 0
|
||||
let n = this._start
|
||||
while (n !== null) {
|
||||
if (!n._deleted && n._countable) {
|
||||
length += n._length
|
||||
}
|
||||
n = n._right
|
||||
}
|
||||
return length
|
||||
}
|
||||
|
||||
[Symbol.iterator] () {
|
||||
return {
|
||||
next: function () {
|
||||
while (this._item !== null && (this._item._deleted || this._item._length <= this._itemElement)) {
|
||||
// item is deleted or itemElement does not exist (is deleted)
|
||||
this._item = this._item._right
|
||||
this._itemElement = 0
|
||||
}
|
||||
if (this._item === null) {
|
||||
return {
|
||||
done: true
|
||||
}
|
||||
}
|
||||
let content
|
||||
if (this._item instanceof Type) {
|
||||
content = this._item
|
||||
} else {
|
||||
content = this._item._content[this._itemElement++]
|
||||
}
|
||||
return {
|
||||
value: content,
|
||||
done: false
|
||||
}
|
||||
},
|
||||
_item: this._start,
|
||||
_itemElement: 0,
|
||||
_count: 0
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes elements starting from an index.
|
||||
*
|
||||
* @param {Integer} index Index at which to start deleting elements
|
||||
* @param {Integer} length The number of elements to remove. Defaults to 1.
|
||||
*/
|
||||
delete (index, length = 1) {
|
||||
this._y.transact(() => {
|
||||
let item = this._start
|
||||
let count = 0
|
||||
while (item !== null && length > 0) {
|
||||
if (!item._deleted && item._countable) {
|
||||
if (count <= index && index < count + item._length) {
|
||||
const diffDel = index - count
|
||||
item = item._splitAt(this._y, diffDel)
|
||||
item._splitAt(this._y, length)
|
||||
length -= item._length
|
||||
item._delete(this._y)
|
||||
count += diffDel
|
||||
} else {
|
||||
count += item._length
|
||||
}
|
||||
}
|
||||
item = item._right
|
||||
}
|
||||
})
|
||||
if (length > 0) {
|
||||
throw new Error('Delete exceeds the range of the YArray')
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Inserts content after an element container.
|
||||
*
|
||||
* @param {Item} left The element container to use as a reference.
|
||||
* @param {Array} content The Array of content to insert (see {@see insert})
|
||||
*/
|
||||
insertAfter (left, content) {
|
||||
this._transact(y => {
|
||||
let right
|
||||
if (left === null) {
|
||||
right = this._start
|
||||
} else {
|
||||
right = left._right
|
||||
}
|
||||
let prevJsonIns = null
|
||||
for (let i = 0; i < content.length; i++) {
|
||||
let c = content[i]
|
||||
if (typeof c === 'function') {
|
||||
c = new c() // eslint-disable-line new-cap
|
||||
}
|
||||
if (c instanceof Type) {
|
||||
if (prevJsonIns !== null) {
|
||||
if (y !== null) {
|
||||
prevJsonIns._integrate(y)
|
||||
}
|
||||
left = prevJsonIns
|
||||
prevJsonIns = null
|
||||
}
|
||||
c._origin = left
|
||||
c._left = left
|
||||
c._right = right
|
||||
c._right_origin = right
|
||||
c._parent = this
|
||||
if (y !== null) {
|
||||
c._integrate(y)
|
||||
} else if (left === null) {
|
||||
this._start = c
|
||||
} else {
|
||||
left._right = c
|
||||
}
|
||||
left = c
|
||||
} else {
|
||||
if (prevJsonIns === null) {
|
||||
prevJsonIns = new ItemJSON()
|
||||
prevJsonIns._origin = left
|
||||
prevJsonIns._left = left
|
||||
prevJsonIns._right = right
|
||||
prevJsonIns._right_origin = right
|
||||
prevJsonIns._parent = this
|
||||
prevJsonIns._content = []
|
||||
}
|
||||
prevJsonIns._content.push(c)
|
||||
}
|
||||
}
|
||||
if (prevJsonIns !== null) {
|
||||
if (y !== null) {
|
||||
prevJsonIns._integrate(y)
|
||||
} else if (prevJsonIns._left === null) {
|
||||
this._start = prevJsonIns
|
||||
}
|
||||
}
|
||||
})
|
||||
return content
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts new content at an index.
|
||||
*
|
||||
* Important: This function expects an array of content. Not just a content
|
||||
* object. The reason for this "weirdness" is that inserting several elements
|
||||
* is very efficient when it is done as a single operation.
|
||||
*
|
||||
* @example
|
||||
* // Insert character 'a' at position 0
|
||||
* yarray.insert(0, ['a'])
|
||||
* // Insert numbers 1, 2 at position 1
|
||||
* yarray.insert(2, [1, 2])
|
||||
*
|
||||
* @param {Integer} index The index to insert content at.
|
||||
* @param {Array} content The array of content
|
||||
*/
|
||||
insert (index, content) {
|
||||
this._transact(() => {
|
||||
let left = null
|
||||
let right = this._start
|
||||
let count = 0
|
||||
const y = this._y
|
||||
while (right !== null) {
|
||||
const rightLen = right._deleted ? 0 : (right._length - 1)
|
||||
if (count <= index && index <= count + rightLen) {
|
||||
const splitDiff = index - count
|
||||
right = right._splitAt(y, splitDiff)
|
||||
left = right._left
|
||||
count += splitDiff
|
||||
break
|
||||
}
|
||||
if (!right._deleted) {
|
||||
count += right._length
|
||||
}
|
||||
left = right
|
||||
right = right._right
|
||||
}
|
||||
if (index > count) {
|
||||
throw new Error('Index exceeds array range!')
|
||||
}
|
||||
this.insertAfter(left, content)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends content to this YArray.
|
||||
*
|
||||
* @param {Array} content Array of content to append.
|
||||
*/
|
||||
push (content) {
|
||||
let n = this._start
|
||||
let lastUndeleted = null
|
||||
while (n !== null) {
|
||||
if (!n._deleted) {
|
||||
lastUndeleted = n
|
||||
}
|
||||
n = n._right
|
||||
}
|
||||
this.insertAfter(lastUndeleted, content)
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform this YXml Type to a readable format.
|
||||
* Useful for logging as all Items and Delete implement this method.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_logString () {
|
||||
return logItemHelper('YArray', this, `start:${logID(this._start)}"`)
|
||||
}
|
||||
}
|
||||
@@ -1,175 +0,0 @@
|
||||
import Type from '../../Struct/Type.js'
|
||||
import Item from '../../Struct/Item.js'
|
||||
import ItemJSON from '../../Struct/ItemJSON.js'
|
||||
import { logItemHelper } from '../../MessageHandler/messageToString.js'
|
||||
import YEvent from '../../Util/YEvent.js'
|
||||
|
||||
/**
|
||||
* Event that describes the changes on a YMap.
|
||||
*
|
||||
* @param {YMap} ymap The YArray that changed.
|
||||
* @param {Set<any>} subs The keys that changed.
|
||||
* @param {boolean} remote Whether the change was created by a remote peer.
|
||||
*/
|
||||
export class YMapEvent extends YEvent {
|
||||
constructor (ymap, subs, remote) {
|
||||
super(ymap)
|
||||
this.keysChanged = subs
|
||||
this.remote = remote
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A shared Map implementation.
|
||||
*/
|
||||
export default class YMap extends Type {
|
||||
/**
|
||||
* @private
|
||||
* Creates YMap Event and calls observers.
|
||||
*/
|
||||
_callObserver (transaction, parentSubs, remote) {
|
||||
this._callEventHandler(transaction, new YMapEvent(this, parentSubs, remote))
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms this Shared Type to a JSON object.
|
||||
*
|
||||
* @return {Object}
|
||||
*/
|
||||
toJSON () {
|
||||
const map = {}
|
||||
for (let [key, item] of this._map) {
|
||||
if (!item._deleted) {
|
||||
let res
|
||||
if (item instanceof Type) {
|
||||
if (item.toJSON !== undefined) {
|
||||
res = item.toJSON()
|
||||
} else {
|
||||
res = item.toString()
|
||||
}
|
||||
} else {
|
||||
res = item._content[0]
|
||||
}
|
||||
map[key] = res
|
||||
}
|
||||
}
|
||||
return map
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the keys for each element in the YMap Type.
|
||||
*
|
||||
* @return {Array}
|
||||
*/
|
||||
keys () {
|
||||
// TODO: Should return either Iterator or Set!
|
||||
let keys = []
|
||||
for (let [key, value] of this._map) {
|
||||
if (!value._deleted) {
|
||||
keys.push(key)
|
||||
}
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a specified element from this YMap.
|
||||
*
|
||||
* @param {encodable} key The key of the element to remove.
|
||||
*/
|
||||
delete (key) {
|
||||
this._transact((y) => {
|
||||
let c = this._map.get(key)
|
||||
if (y !== null && c !== undefined) {
|
||||
c._delete(y)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds or updates an element with a specified key and value.
|
||||
*
|
||||
* @param {encodable} key The key of the element to add to this YMap.
|
||||
* @param {encodable | YType} value The value of the element to add to this
|
||||
* YMap.
|
||||
*/
|
||||
set (key, value) {
|
||||
this._transact(y => {
|
||||
const old = this._map.get(key) || null
|
||||
if (old !== null) {
|
||||
if (
|
||||
old.constructor === ItemJSON &&
|
||||
!old._deleted && old._content[0] === value
|
||||
) {
|
||||
// Trying to overwrite with same value
|
||||
// break here
|
||||
return value
|
||||
}
|
||||
if (y !== null) {
|
||||
old._delete(y)
|
||||
}
|
||||
}
|
||||
let v
|
||||
if (typeof value === 'function') {
|
||||
v = new value() // eslint-disable-line new-cap
|
||||
value = v
|
||||
} else if (value instanceof Item) {
|
||||
v = value
|
||||
} else {
|
||||
v = new ItemJSON()
|
||||
v._content = [value]
|
||||
}
|
||||
v._right = old
|
||||
v._right_origin = old
|
||||
v._parent = this
|
||||
v._parentSub = key
|
||||
if (y !== null) {
|
||||
v._integrate(y)
|
||||
} else {
|
||||
this._map.set(key, v)
|
||||
}
|
||||
})
|
||||
return value
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a specified element from this YMap.
|
||||
*
|
||||
* @param {encodable} key The key of the element to return.
|
||||
*/
|
||||
get (key) {
|
||||
let v = this._map.get(key)
|
||||
if (v === undefined || v._deleted) {
|
||||
return undefined
|
||||
}
|
||||
if (v instanceof Type) {
|
||||
return v
|
||||
} else {
|
||||
return v._content[v._content.length - 1]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a boolean indicating whether the specified key exists or not.
|
||||
*
|
||||
* @param {encodable} key The key to test.
|
||||
*/
|
||||
has (key) {
|
||||
let v = this._map.get(key)
|
||||
if (v === undefined || v._deleted) {
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform this YXml Type to a readable format.
|
||||
* Useful for logging as all Items and Delete implement this method.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_logString () {
|
||||
return logItemHelper('YMap', this, `mapSize:${this._map.size}`)
|
||||
}
|
||||
}
|
||||
@@ -1,654 +0,0 @@
|
||||
import ItemString from '../../Struct/ItemString.js'
|
||||
import ItemEmbed from '../../Struct/ItemEmbed.js'
|
||||
import ItemFormat from '../../Struct/ItemFormat.js'
|
||||
import { logItemHelper } from '../../MessageHandler/messageToString.js'
|
||||
import { YArrayEvent, default as YArray } from '../YArray/YArray.js'
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
function integrateItem (item, parent, y, left, right) {
|
||||
item._origin = left
|
||||
item._left = left
|
||||
item._right = right
|
||||
item._right_origin = right
|
||||
item._parent = parent
|
||||
if (y !== null) {
|
||||
item._integrate(y)
|
||||
} else if (left === null) {
|
||||
parent._start = item
|
||||
} else {
|
||||
left._right = item
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
function findNextPosition (currentAttributes, parent, left, right, count) {
|
||||
while (right !== null && count > 0) {
|
||||
switch (right.constructor) {
|
||||
case ItemEmbed:
|
||||
case ItemString:
|
||||
const rightLen = right._deleted ? 0 : (right._length - 1)
|
||||
if (count <= rightLen) {
|
||||
right = right._splitAt(parent._y, count)
|
||||
left = right._left
|
||||
return [left, right, currentAttributes]
|
||||
}
|
||||
if (right._deleted === false) {
|
||||
count -= right._length
|
||||
}
|
||||
break
|
||||
case ItemFormat:
|
||||
if (right._deleted === false) {
|
||||
updateCurrentAttributes(currentAttributes, right)
|
||||
}
|
||||
break
|
||||
}
|
||||
left = right
|
||||
right = right._right
|
||||
}
|
||||
return [left, right, currentAttributes]
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
function findPosition (parent, index) {
|
||||
let currentAttributes = new Map()
|
||||
let left = null
|
||||
let right = parent._start
|
||||
return findNextPosition(currentAttributes, parent, left, right, index)
|
||||
}
|
||||
|
||||
/**
|
||||
* Negate applied formats
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
function insertNegatedAttributes (y, parent, left, right, negatedAttributes) {
|
||||
// check if we really need to remove attributes
|
||||
while (
|
||||
right !== null && (
|
||||
right._deleted === true || (
|
||||
right.constructor === ItemFormat &&
|
||||
(negatedAttributes.get(right.key) === right.value)
|
||||
)
|
||||
)
|
||||
) {
|
||||
if (right._deleted === false) {
|
||||
negatedAttributes.delete(right.key)
|
||||
}
|
||||
left = right
|
||||
right = right._right
|
||||
}
|
||||
for (let [key, val] of negatedAttributes) {
|
||||
let format = new ItemFormat()
|
||||
format.key = key
|
||||
format.value = val
|
||||
integrateItem(format, parent, y, left, right)
|
||||
left = format
|
||||
}
|
||||
return [left, right]
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
function updateCurrentAttributes (currentAttributes, item) {
|
||||
const value = item.value
|
||||
const key = item.key
|
||||
if (value === null) {
|
||||
currentAttributes.delete(key)
|
||||
} else {
|
||||
currentAttributes.set(key, value)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
function minimizeAttributeChanges (left, right, currentAttributes, attributes) {
|
||||
// go right while attributes[right.key] === right.value (or right is deleted)
|
||||
while (true) {
|
||||
if (right === null) {
|
||||
break
|
||||
} else if (right._deleted === true) {
|
||||
// continue
|
||||
} else if (right.constructor === ItemFormat && (attributes[right.key] || null) === right.value) {
|
||||
// found a format, update currentAttributes and continue
|
||||
updateCurrentAttributes(currentAttributes, right)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
left = right
|
||||
right = right._right
|
||||
}
|
||||
return [left, right]
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
function insertAttributes (y, parent, left, right, attributes, currentAttributes) {
|
||||
const negatedAttributes = new Map()
|
||||
// insert format-start items
|
||||
for (let key in attributes) {
|
||||
const val = attributes[key]
|
||||
const currentVal = currentAttributes.get(key)
|
||||
if (currentVal !== val) {
|
||||
// save negated attribute (set null if currentVal undefined)
|
||||
negatedAttributes.set(key, currentVal || null)
|
||||
let format = new ItemFormat()
|
||||
format.key = key
|
||||
format.value = val
|
||||
integrateItem(format, parent, y, left, right)
|
||||
left = format
|
||||
}
|
||||
}
|
||||
return [left, right, negatedAttributes]
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
function insertText (y, text, parent, left, right, currentAttributes, attributes) {
|
||||
for (let [key] of currentAttributes) {
|
||||
if (attributes.hasOwnProperty(key) === false) {
|
||||
attributes[key] = null
|
||||
}
|
||||
}
|
||||
[left, right] = minimizeAttributeChanges(left, right, currentAttributes, attributes)
|
||||
let negatedAttributes
|
||||
[left, right, negatedAttributes] = insertAttributes(y, parent, left, right, attributes, currentAttributes)
|
||||
// insert content
|
||||
let item
|
||||
if (text.constructor === String) {
|
||||
item = new ItemString()
|
||||
item._content = text
|
||||
} else {
|
||||
item = new ItemEmbed()
|
||||
item.embed = text
|
||||
}
|
||||
integrateItem(item, parent, y, left, right)
|
||||
left = item
|
||||
return insertNegatedAttributes(y, parent, left, right, negatedAttributes)
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
function formatText (y, length, parent, left, right, currentAttributes, attributes) {
|
||||
[left, right] = minimizeAttributeChanges(left, right, currentAttributes, attributes)
|
||||
let negatedAttributes
|
||||
[left, right, negatedAttributes] = insertAttributes(y, parent, left, right, attributes, currentAttributes)
|
||||
// iterate until first non-format or null is found
|
||||
// delete all formats with attributes[format.key] != null
|
||||
while (length > 0 && right !== null) {
|
||||
if (right._deleted === false) {
|
||||
switch (right.constructor) {
|
||||
case ItemFormat:
|
||||
if (attributes.hasOwnProperty(right.key)) {
|
||||
if (attributes[right.key] === right.value) {
|
||||
negatedAttributes.delete(right.key)
|
||||
} else {
|
||||
negatedAttributes.set(right.key, right.value)
|
||||
}
|
||||
right._delete(y)
|
||||
}
|
||||
updateCurrentAttributes(currentAttributes, right)
|
||||
break
|
||||
case ItemEmbed:
|
||||
case ItemString:
|
||||
right._splitAt(y, length)
|
||||
length -= right._length
|
||||
break
|
||||
}
|
||||
}
|
||||
left = right
|
||||
right = right._right
|
||||
}
|
||||
return insertNegatedAttributes(y, parent, left, right, negatedAttributes)
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
function deleteText (y, length, parent, left, right, currentAttributes) {
|
||||
while (length > 0 && right !== null) {
|
||||
if (right._deleted === false) {
|
||||
switch (right.constructor) {
|
||||
case ItemFormat:
|
||||
updateCurrentAttributes(currentAttributes, right)
|
||||
break
|
||||
case ItemEmbed:
|
||||
case ItemString:
|
||||
right._splitAt(y, length)
|
||||
length -= right._length
|
||||
right._delete(y)
|
||||
break
|
||||
}
|
||||
}
|
||||
left = right
|
||||
right = right._right
|
||||
}
|
||||
return [left, right]
|
||||
}
|
||||
|
||||
// TODO: In the quill delta representation we should also use the format {ops:[..]}
|
||||
/**
|
||||
* The Quill Delta format represents changes on a text document with
|
||||
* formatting information. For mor information visit {@link https://quilljs.com/docs/delta/|Quill Delta}
|
||||
*
|
||||
* @example
|
||||
* {
|
||||
* ops: [
|
||||
* { insert: 'Gandalf', attributes: { bold: true } },
|
||||
* { insert: ' the ' },
|
||||
* { insert: 'Grey', attributes: { color: '#cccccc' } }
|
||||
* ]
|
||||
* }
|
||||
*
|
||||
* @typedef {Array<Object>} Delta
|
||||
*/
|
||||
|
||||
/**
|
||||
* Attributes that can be assigned to a selection of text.
|
||||
*
|
||||
* @example
|
||||
* {
|
||||
* bold: true,
|
||||
* font-size: '40px'
|
||||
* }
|
||||
*
|
||||
* @typedef {Object} TextAttributes
|
||||
*/
|
||||
|
||||
/**
|
||||
* Event that describes the changes on a YText type.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
class YTextEvent extends YArrayEvent {
|
||||
constructor (ytext, remote, transaction) {
|
||||
super(ytext, remote, transaction)
|
||||
this._delta = null
|
||||
}
|
||||
// TODO: Should put this in a separate function. toDelta shouldn't be included
|
||||
// in every Yjs distribution
|
||||
/**
|
||||
* Compute the changes in the delta format.
|
||||
*
|
||||
* @return {Delta} A {@link https://quilljs.com/docs/delta/|Quill Delta}) that
|
||||
* represents the changes on the document.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
get delta () {
|
||||
if (this._delta === null) {
|
||||
const y = this.target._y
|
||||
y.transact(() => {
|
||||
let item = this.target._start
|
||||
const delta = []
|
||||
const added = this.addedElements
|
||||
const removed = this.removedElements
|
||||
this._delta = delta
|
||||
let action = null
|
||||
let attributes = {} // counts added or removed new attributes for retain
|
||||
const currentAttributes = new Map() // saves all current attributes for insert
|
||||
const oldAttributes = new Map()
|
||||
let insert = ''
|
||||
let retain = 0
|
||||
let deleteLen = 0
|
||||
const addOp = function addOp () {
|
||||
if (action !== null) {
|
||||
let op
|
||||
switch (action) {
|
||||
case 'delete':
|
||||
op = { delete: deleteLen }
|
||||
deleteLen = 0
|
||||
break
|
||||
case 'insert':
|
||||
op = { insert }
|
||||
if (currentAttributes.size > 0) {
|
||||
op.attributes = {}
|
||||
for (let [key, value] of currentAttributes) {
|
||||
if (value !== null) {
|
||||
op.attributes[key] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
insert = ''
|
||||
break
|
||||
case 'retain':
|
||||
op = { retain }
|
||||
if (Object.keys(attributes).length > 0) {
|
||||
op.attributes = {}
|
||||
for (let key in attributes) {
|
||||
op.attributes[key] = attributes[key]
|
||||
}
|
||||
}
|
||||
retain = 0
|
||||
break
|
||||
}
|
||||
delta.push(op)
|
||||
action = null
|
||||
}
|
||||
}
|
||||
while (item !== null) {
|
||||
switch (item.constructor) {
|
||||
case ItemEmbed:
|
||||
if (added.has(item)) {
|
||||
addOp()
|
||||
action = 'insert'
|
||||
insert = item.embed
|
||||
addOp()
|
||||
} else if (removed.has(item)) {
|
||||
if (action !== 'delete') {
|
||||
addOp()
|
||||
action = 'delete'
|
||||
}
|
||||
deleteLen += 1
|
||||
} else if (item._deleted === false) {
|
||||
if (action !== 'retain') {
|
||||
addOp()
|
||||
action = 'retain'
|
||||
}
|
||||
retain += 1
|
||||
}
|
||||
break
|
||||
case ItemString:
|
||||
if (added.has(item)) {
|
||||
if (action !== 'insert') {
|
||||
addOp()
|
||||
action = 'insert'
|
||||
}
|
||||
insert += item._content
|
||||
} else if (removed.has(item)) {
|
||||
if (action !== 'delete') {
|
||||
addOp()
|
||||
action = 'delete'
|
||||
}
|
||||
deleteLen += item._length
|
||||
} else if (item._deleted === false) {
|
||||
if (action !== 'retain') {
|
||||
addOp()
|
||||
action = 'retain'
|
||||
}
|
||||
retain += item._length
|
||||
}
|
||||
break
|
||||
case ItemFormat:
|
||||
if (added.has(item)) {
|
||||
const curVal = currentAttributes.get(item.key) || null
|
||||
if (curVal !== item.value) {
|
||||
if (action === 'retain') {
|
||||
addOp()
|
||||
}
|
||||
if (item.value === (oldAttributes.get(item.key) || null)) {
|
||||
delete attributes[item.key]
|
||||
} else {
|
||||
attributes[item.key] = item.value
|
||||
}
|
||||
} else {
|
||||
item._delete(y)
|
||||
}
|
||||
} else if (removed.has(item)) {
|
||||
oldAttributes.set(item.key, item.value)
|
||||
const curVal = currentAttributes.get(item.key) || null
|
||||
if (curVal !== item.value) {
|
||||
if (action === 'retain') {
|
||||
addOp()
|
||||
}
|
||||
attributes[item.key] = curVal
|
||||
}
|
||||
} else if (item._deleted === false) {
|
||||
oldAttributes.set(item.key, item.value)
|
||||
if (attributes.hasOwnProperty(item.key)) {
|
||||
if (attributes[item.key] !== item.value) {
|
||||
if (action === 'retain') {
|
||||
addOp()
|
||||
}
|
||||
if (item.value === null) {
|
||||
attributes[item.key] = item.value
|
||||
} else {
|
||||
delete attributes[item.key]
|
||||
}
|
||||
} else {
|
||||
item._delete(y)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (item._deleted === false) {
|
||||
if (action === 'insert') {
|
||||
addOp()
|
||||
}
|
||||
updateCurrentAttributes(currentAttributes, item)
|
||||
}
|
||||
break
|
||||
}
|
||||
item = item._right
|
||||
}
|
||||
addOp()
|
||||
while (this._delta.length > 0) {
|
||||
let lastOp = this._delta[this._delta.length - 1]
|
||||
if (lastOp.hasOwnProperty('retain') && !lastOp.hasOwnProperty('attributes')) {
|
||||
// retain delta's if they don't assign attributes
|
||||
this._delta.pop()
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
return this._delta
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Type that represents text with formatting information.
|
||||
*
|
||||
* This type replaces y-richtext as this implementation is able to handle
|
||||
* block formats (format information on a paragraph), embeds (complex elements
|
||||
* like pictures and videos), and text formats (**bold**, *italic*).
|
||||
*
|
||||
* @param {String} string The initial value of the YText.
|
||||
*/
|
||||
export default class YText extends YArray {
|
||||
constructor (string) {
|
||||
super()
|
||||
if (typeof string === 'string') {
|
||||
const start = new ItemString()
|
||||
start._parent = this
|
||||
start._content = string
|
||||
this._start = start
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Creates YMap Event and calls observers.
|
||||
*/
|
||||
_callObserver (transaction, parentSubs, remote) {
|
||||
this._callEventHandler(transaction, new YTextEvent(this, remote, transaction))
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unformatted string representation of this YText type.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
toString () {
|
||||
let str = ''
|
||||
let n = this._start
|
||||
while (n !== null) {
|
||||
if (!n._deleted && n._countable) {
|
||||
str += n._content
|
||||
}
|
||||
n = n._right
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a {@link Delta} on this shared YText type.
|
||||
*
|
||||
* @param {Delta} delta The changes to apply on this element.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
applyDelta (delta) {
|
||||
this._transact(y => {
|
||||
let left = null
|
||||
let right = this._start
|
||||
const currentAttributes = new Map()
|
||||
for (let i = 0; i < delta.length; i++) {
|
||||
let op = delta[i]
|
||||
if (op.hasOwnProperty('insert')) {
|
||||
;[left, right] = insertText(y, op.insert, this, left, right, currentAttributes, op.attributes || {})
|
||||
} else if (op.hasOwnProperty('retain')) {
|
||||
;[left, right] = formatText(y, op.retain, this, left, right, currentAttributes, op.attributes || {})
|
||||
} else if (op.hasOwnProperty('delete')) {
|
||||
;[left, right] = deleteText(y, op.delete, this, left, right, currentAttributes)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Delta representation of this YText type.
|
||||
*
|
||||
* @return {Delta} The Delta representation of this type.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
toDelta () {
|
||||
let ops = []
|
||||
let currentAttributes = new Map()
|
||||
let str = ''
|
||||
let n = this._start
|
||||
function packStr () {
|
||||
if (str.length > 0) {
|
||||
// pack str with attributes to ops
|
||||
let attributes = {}
|
||||
let addAttributes = false
|
||||
for (let [key, value] of currentAttributes) {
|
||||
addAttributes = true
|
||||
attributes[key] = value
|
||||
}
|
||||
let op = { insert: str }
|
||||
if (addAttributes) {
|
||||
op.attributes = attributes
|
||||
}
|
||||
ops.push(op)
|
||||
str = ''
|
||||
}
|
||||
}
|
||||
while (n !== null) {
|
||||
if (!n._deleted) {
|
||||
switch (n.constructor) {
|
||||
case ItemString:
|
||||
str += n._content
|
||||
break
|
||||
case ItemFormat:
|
||||
packStr()
|
||||
updateCurrentAttributes(currentAttributes, n)
|
||||
break
|
||||
}
|
||||
}
|
||||
n = n._right
|
||||
}
|
||||
packStr()
|
||||
return ops
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert text at a given index.
|
||||
*
|
||||
* @param {Integer} index The index at which to start inserting.
|
||||
* @param {String} text The text to insert at the specified position.
|
||||
* @param {TextAttributes} attributes Optionally define some formatting
|
||||
* information to apply on the inserted
|
||||
* Text.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
insert (index, text, attributes = {}) {
|
||||
if (text.length <= 0) {
|
||||
return
|
||||
}
|
||||
this._transact(y => {
|
||||
let [left, right, currentAttributes] = findPosition(this, index)
|
||||
insertText(y, text, this, left, right, currentAttributes, attributes)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts an embed at a index.
|
||||
*
|
||||
* @param {Integer} index The index to insert the embed at.
|
||||
* @param {Object} embed The Object that represents the embed.
|
||||
* @param {TextAttributes} attributes Attribute information to apply on the
|
||||
* embed
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
insertEmbed (index, embed, attributes = {}) {
|
||||
if (embed.constructor !== Object) {
|
||||
throw new Error('Embed must be an Object')
|
||||
}
|
||||
this._transact(y => {
|
||||
let [left, right, currentAttributes] = findPosition(this, index)
|
||||
insertText(y, embed, this, left, right, currentAttributes, attributes)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes text starting from an index.
|
||||
*
|
||||
* @param {Integer} index Index at which to start deleting.
|
||||
* @param {Integer} length The number of characters to remove. Defaults to 1.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
delete (index, length) {
|
||||
if (length === 0) {
|
||||
return
|
||||
}
|
||||
this._transact(y => {
|
||||
let [left, right, currentAttributes] = findPosition(this, index)
|
||||
deleteText(y, length, this, left, right, currentAttributes)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns properties to a range of text.
|
||||
*
|
||||
* @param {Integer} index The position where to start formatting.
|
||||
* @param {Integer} length The amount of characters to assign properties to.
|
||||
* @param {TextAttributes} attributes Attribute information to apply on the
|
||||
* text.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
format (index, length, attributes) {
|
||||
this._transact(y => {
|
||||
let [left, right, currentAttributes] = findPosition(this, index)
|
||||
if (right === null) {
|
||||
return
|
||||
}
|
||||
formatText(y, length, this, left, right, currentAttributes, attributes)
|
||||
})
|
||||
}
|
||||
// TODO: De-duplicate code. The following code is in every type.
|
||||
/**
|
||||
* Transform this YText to a readable format.
|
||||
* Useful for logging as all Items implement this method.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_logString () {
|
||||
return logItemHelper('YText', this)
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
|
||||
import YXmlFragment from './YXmlFragment.js'
|
||||
import YXmlElement from './YXmlElement.js'
|
||||
import YXmlHook from './YXmlHook.js'
|
||||
|
||||
export { default as YXmlFragment } from './YXmlFragment.js'
|
||||
export { default as YXmlElement } from './YXmlElement.js'
|
||||
export { default as YXmlText } from './YXmlText.js'
|
||||
export { default as YXmlHook } from './YXmlHook.js'
|
||||
|
||||
YXmlFragment._YXmlElement = YXmlElement
|
||||
YXmlFragment._YXmlHook = YXmlHook
|
||||
@@ -1,188 +0,0 @@
|
||||
import YMap from '../YMap/YMap.js'
|
||||
import { YXmlFragment } from './YXml.js'
|
||||
import { createAssociation } from '../../Bindings/DomBinding/util.js'
|
||||
|
||||
/**
|
||||
* An YXmlElement imitates the behavior of a
|
||||
* {@link https://developer.mozilla.org/en-US/docs/Web/API/Element|Dom Element}.
|
||||
*
|
||||
* * An YXmlElement has attributes (key value pairs)
|
||||
* * An YXmlElement has childElements that must inherit from YXmlElement
|
||||
*
|
||||
* @param {String} nodeName Node name
|
||||
*/
|
||||
export default class YXmlElement extends YXmlFragment {
|
||||
constructor (nodeName = 'UNDEFINED') {
|
||||
super()
|
||||
this.nodeName = nodeName.toUpperCase()
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Creates an Item with the same effect as this Item (without position effect)
|
||||
*/
|
||||
_copy () {
|
||||
let struct = super._copy()
|
||||
struct.nodeName = this.nodeName
|
||||
return struct
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Read the next Item in a Decoder and fill this Item with the read data.
|
||||
*
|
||||
* This is called when data is received from a remote peer.
|
||||
*
|
||||
* @param {Y} y The Yjs instance that this Item belongs to.
|
||||
* @param {BinaryDecoder} decoder The decoder object to read data from.
|
||||
*/
|
||||
_fromBinary (y, decoder) {
|
||||
const missing = super._fromBinary(y, decoder)
|
||||
this.nodeName = decoder.readVarString()
|
||||
return missing
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the properties of this type to binary and write it to an
|
||||
* BinaryEncoder.
|
||||
*
|
||||
* This is called when this Item is sent to a remote peer.
|
||||
*
|
||||
* @param {BinaryEncoder} encoder The encoder to write data to.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_toBinary (encoder) {
|
||||
super._toBinary(encoder)
|
||||
encoder.writeVarString(this.nodeName)
|
||||
}
|
||||
|
||||
/**
|
||||
* Integrates this Item into the shared structure.
|
||||
*
|
||||
* This method actually applies the change to the Yjs instance. In case of
|
||||
* Item it connects _left and _right to this Item and calls the
|
||||
* {@link Item#beforeChange} method.
|
||||
*
|
||||
* * Checks for nodeName
|
||||
* * Sets domFilter
|
||||
*
|
||||
* @param {Y} y The Yjs instance
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_integrate (y) {
|
||||
if (this.nodeName === null) {
|
||||
throw new Error('nodeName must be defined!')
|
||||
}
|
||||
super._integrate(y)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the string representation of this YXmlElement.
|
||||
* The attributes are ordered by attribute-name, so you can easily use this
|
||||
* method to compare YXmlElements
|
||||
*
|
||||
* @return {String} The string representation of this type.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
toString () {
|
||||
const attrs = this.getAttributes()
|
||||
const stringBuilder = []
|
||||
const keys = []
|
||||
for (let key in attrs) {
|
||||
keys.push(key)
|
||||
}
|
||||
keys.sort()
|
||||
const keysLen = keys.length
|
||||
for (let i = 0; i < keysLen; i++) {
|
||||
const key = keys[i]
|
||||
stringBuilder.push(key + '="' + attrs[key] + '"')
|
||||
}
|
||||
const nodeName = this.nodeName.toLocaleLowerCase()
|
||||
const attrsString = stringBuilder.length > 0 ? ' ' + stringBuilder.join(' ') : ''
|
||||
return `<${nodeName}${attrsString}>${super.toString()}</${nodeName}>`
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an attribute from this YXmlElement.
|
||||
*
|
||||
* @param {String} attributeName The attribute name that is to be removed.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
removeAttribute (attributeName) {
|
||||
return YMap.prototype.delete.call(this, attributeName)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets or updates an attribute.
|
||||
*
|
||||
* @param {String} attributeName The attribute name that is to be set.
|
||||
* @param {String} attributeValue The attribute value that is to be set.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
setAttribute (attributeName, attributeValue) {
|
||||
return YMap.prototype.set.call(this, attributeName, attributeValue)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an attribute value that belongs to the attribute name.
|
||||
*
|
||||
* @param {String} attributeName The attribute name that identifies the
|
||||
* queried value.
|
||||
* @return {String} The queried attribute value.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
getAttribute (attributeName) {
|
||||
return YMap.prototype.get.call(this, attributeName)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all attribute name/value pairs in a JSON Object.
|
||||
*
|
||||
* @return {Object} A JSON Object that describes the attributes.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
getAttributes () {
|
||||
const obj = {}
|
||||
for (let [key, value] of this._map) {
|
||||
if (!value._deleted) {
|
||||
obj[key] = value._content[0]
|
||||
}
|
||||
}
|
||||
return obj
|
||||
}
|
||||
// TODO: outsource the binding property.
|
||||
/**
|
||||
* Creates a Dom Element that mirrors this YXmlElement.
|
||||
*
|
||||
* @param {Document} [_document=document] The document object (you must define
|
||||
* this when calling this method in
|
||||
* nodejs)
|
||||
* @param {Object<key:hookDefinition>} [hooks={}] Optional property to customize how hooks
|
||||
* are presented in the DOM
|
||||
* @param {DomBinding} [binding] You should not set this property. This is
|
||||
* used if DomBinding wants to create a
|
||||
* association to the created DOM type.
|
||||
* @return {Element} The {@link https://developer.mozilla.org/en-US/docs/Web/API/Element|Dom Element}
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
toDom (_document = document, hooks = {}, binding) {
|
||||
const dom = _document.createElement(this.nodeName)
|
||||
let attrs = this.getAttributes()
|
||||
for (let key in attrs) {
|
||||
dom.setAttribute(key, attrs[key])
|
||||
}
|
||||
this.forEach(yxml => {
|
||||
dom.appendChild(yxml.toDom(_document, hooks, binding))
|
||||
})
|
||||
createAssociation(binding, dom, this)
|
||||
return dom
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
import YEvent from '../../Util/YEvent.js'
|
||||
|
||||
/**
|
||||
* An Event that describes changes on a YXml Element or Yxml Fragment
|
||||
*
|
||||
* @protected
|
||||
*/
|
||||
export default class YXmlEvent extends YEvent {
|
||||
/**
|
||||
* @param {YType} target The target on which the event is created.
|
||||
* @param {Set} subs The set of changed attributes. `null` is included if the
|
||||
* child list changed.
|
||||
* @param {Boolean} remote Whether this change was created by a remote peer.
|
||||
* @param {Transaction} transaction The transaction instance with wich the
|
||||
* change was created.
|
||||
*/
|
||||
constructor (target, subs, remote, transaction) {
|
||||
super(target)
|
||||
/**
|
||||
* The transaction instance for the computed change.
|
||||
* @type {Transaction}
|
||||
*/
|
||||
this._transaction = transaction
|
||||
/**
|
||||
* Whether the children changed.
|
||||
* @type {Boolean}
|
||||
*/
|
||||
this.childListChanged = false
|
||||
/**
|
||||
* Set of all changed attributes.
|
||||
* @type {Set}
|
||||
*/
|
||||
this.attributesChanged = new Set()
|
||||
/**
|
||||
* Whether this change was created by a remote peer.
|
||||
* @type {Boolean}
|
||||
*/
|
||||
this.remote = remote
|
||||
subs.forEach((sub) => {
|
||||
if (sub === null) {
|
||||
this.childListChanged = true
|
||||
} else {
|
||||
this.attributesChanged.add(sub)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,167 +0,0 @@
|
||||
import { createAssociation } from '../../Bindings/DomBinding/util.js'
|
||||
import YXmlTreeWalker from './YXmlTreeWalker.js'
|
||||
|
||||
import YArray from '../YArray/YArray.js'
|
||||
import YXmlEvent from './YXmlEvent.js'
|
||||
import { logItemHelper } from '../../MessageHandler/messageToString.js'
|
||||
|
||||
/**
|
||||
* Dom filter function.
|
||||
*
|
||||
* @callback domFilter
|
||||
* @param {string} nodeName The nodeName of the element
|
||||
* @param {Map} attributes The map of attributes.
|
||||
* @return {boolean} Whether to include the Dom node in the YXmlElement.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Define the elements to which a set of CSS queries apply.
|
||||
* {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors|CSS_Selectors}
|
||||
*
|
||||
* @example
|
||||
* query = '.classSelector'
|
||||
* query = 'nodeSelector'
|
||||
* query = '#idSelector'
|
||||
*
|
||||
* @typedef {string} CSS_Selector
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents a list of {@link YXmlElement}.and {@link YXmlText} types.
|
||||
* A YxmlFragment is similar to a {@link YXmlElement}, but it does not have a
|
||||
* nodeName and it does not have attributes. Though it can be bound to a DOM
|
||||
* element - in this case the attributes and the nodeName are not shared.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export default class YXmlFragment extends YArray {
|
||||
/**
|
||||
* Create a subtree of childNodes.
|
||||
*
|
||||
* @example
|
||||
* const walker = elem.createTreeWalker(dom => dom.nodeName === 'div')
|
||||
* for (let node in walker) {
|
||||
* // `node` is a div node
|
||||
* nop(node)
|
||||
* }
|
||||
*
|
||||
* @param {Function} filter Function that is called on each child element and
|
||||
* returns a Boolean indicating whether the child
|
||||
* is to be included in the subtree.
|
||||
* @return {TreeWalker} A subtree and a position within it.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
createTreeWalker (filter) {
|
||||
return new YXmlTreeWalker(this, filter)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first YXmlElement that matches the query.
|
||||
* Similar to DOM's {@link querySelector}.
|
||||
*
|
||||
* Query support:
|
||||
* - tagname
|
||||
* TODO:
|
||||
* - id
|
||||
* - attribute
|
||||
*
|
||||
* @param {CSS_Selector} query The query on the children.
|
||||
* @return {?YXmlElement} The first element that matches the query or null.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
querySelector (query) {
|
||||
query = query.toUpperCase()
|
||||
const iterator = new YXmlTreeWalker(this, element => element.nodeName === query)
|
||||
const next = iterator.next()
|
||||
if (next.done) {
|
||||
return null
|
||||
} else {
|
||||
return next.value
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all YXmlElements that match the query.
|
||||
* Similar to Dom's {@link querySelectorAll}.
|
||||
*
|
||||
* TODO: Does not yet support all queries. Currently only query by tagName.
|
||||
*
|
||||
* @param {CSS_Selector} query The query on the children
|
||||
* @return {Array<YXmlElement>} The elements that match this query.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
querySelectorAll (query) {
|
||||
query = query.toUpperCase()
|
||||
return Array.from(new YXmlTreeWalker(this, element => element.nodeName === query))
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates YArray Event and calls observers.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_callObserver (transaction, parentSubs, remote) {
|
||||
this._callEventHandler(transaction, new YXmlEvent(this, parentSubs, remote, transaction))
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the string representation of all the children of this YXmlFragment.
|
||||
*
|
||||
* @return {string} The string representation of all children.
|
||||
*/
|
||||
toString () {
|
||||
return this.map(xml => xml.toString()).join('')
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Unbind from Dom and mark this Item as deleted.
|
||||
*
|
||||
* @param {Y} y The Yjs instance
|
||||
* @param {boolean} createDelete Whether to propagate a message that this
|
||||
* Type was deleted.
|
||||
* @param {boolean} [gcChildren=y._hasUndoManager===false] Whether to garbage
|
||||
* collect the children of this type.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_delete (y, createDelete, gcChildren) {
|
||||
super._delete(y, createDelete, gcChildren)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Dom Element that mirrors this YXmlElement.
|
||||
*
|
||||
* @param {Document} [_document=document] The document object (you must define
|
||||
* this when calling this method in
|
||||
* nodejs)
|
||||
* @param {Object<key:hookDefinition>} [hooks={}] Optional property to customize how hooks
|
||||
* are presented in the DOM
|
||||
* @param {DomBinding} [binding] You should not set this property. This is
|
||||
* used if DomBinding wants to create a
|
||||
* association to the created DOM type
|
||||
* @return {Element} The {@link https://developer.mozilla.org/en-US/docs/Web/API/Element|Dom Element}
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
toDom (_document = document, hooks = {}, binding) {
|
||||
const fragment = _document.createDocumentFragment()
|
||||
createAssociation(binding, fragment, this)
|
||||
this.forEach(xmlType => {
|
||||
fragment.insertBefore(xmlType.toDom(_document, hooks, binding), null)
|
||||
})
|
||||
return fragment
|
||||
}
|
||||
/**
|
||||
* Transform this YXml Type to a readable format.
|
||||
* Useful for logging as all Items and Delete implement this method.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_logString () {
|
||||
return logItemHelper('YXml', this)
|
||||
}
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
import YMap from '../YMap/YMap.js'
|
||||
import { createAssociation } from '../../Bindings/DomBinding/util.js'
|
||||
|
||||
/**
|
||||
* You can manage binding to a custom type with YXmlHook.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export default class YXmlHook extends YMap {
|
||||
/**
|
||||
* @param {String} hookName nodeName of the Dom Node.
|
||||
*/
|
||||
constructor (hookName) {
|
||||
super()
|
||||
this.hookName = null
|
||||
if (hookName !== undefined) {
|
||||
this.hookName = hookName
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an Item with the same effect as this Item (without position effect)
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_copy () {
|
||||
const struct = super._copy()
|
||||
struct.hookName = this.hookName
|
||||
return struct
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Dom Element that mirrors this YXmlElement.
|
||||
*
|
||||
* @param {Document} [_document=document] The document object (you must define
|
||||
* this when calling this method in
|
||||
* nodejs)
|
||||
* @param {Object<key:hookDefinition>} [hooks] Optional property to customize how hooks
|
||||
* are presented in the DOM
|
||||
* @param {DomBinding} [binding] You should not set this property. This is
|
||||
* used if DomBinding wants to create a
|
||||
* association to the created DOM type
|
||||
* @return {Element} The {@link https://developer.mozilla.org/en-US/docs/Web/API/Element|Dom Element}
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
toDom (_document = document, hooks = {}, binding) {
|
||||
const hook = hooks[this.hookName]
|
||||
let dom
|
||||
if (hook !== undefined) {
|
||||
dom = hook.createDom(this)
|
||||
} else {
|
||||
dom = document.createElement(this.hookName)
|
||||
}
|
||||
dom.setAttribute('data-yjs-hook', this.hookName)
|
||||
createAssociation(binding, dom, this)
|
||||
return dom
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the next Item in a Decoder and fill this Item with the read data.
|
||||
*
|
||||
* This is called when data is received from a remote peer.
|
||||
*
|
||||
* @param {Y} y The Yjs instance that this Item belongs to.
|
||||
* @param {BinaryDecoder} decoder The decoder object to read data from.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_fromBinary (y, decoder) {
|
||||
const missing = super._fromBinary(y, decoder)
|
||||
this.hookName = decoder.readVarString()
|
||||
return missing
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the properties of this type to binary and write it to an
|
||||
* BinaryEncoder.
|
||||
*
|
||||
* This is called when this Item is sent to a remote peer.
|
||||
*
|
||||
* @param {BinaryEncoder} encoder The encoder to write data to.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_toBinary (encoder) {
|
||||
super._toBinary(encoder)
|
||||
encoder.writeVarString(this.hookName)
|
||||
}
|
||||
|
||||
/**
|
||||
* Integrate this type into the Yjs instance.
|
||||
*
|
||||
* * Save this struct in the os
|
||||
* * This type is sent to other client
|
||||
* * Observer functions are fired
|
||||
*
|
||||
* @param {Y} y The Yjs instance
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_integrate (y) {
|
||||
if (this.hookName === null) {
|
||||
throw new Error('hookName must be defined!')
|
||||
}
|
||||
super._integrate(y)
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
import YText from '../YText/YText.js'
|
||||
import { createAssociation } from '../../Bindings/DomBinding/util.js'
|
||||
|
||||
/**
|
||||
* Represents text in a Dom Element. In the future this type will also handle
|
||||
* simple formatting information like bold and italic.
|
||||
*
|
||||
* @param {String} arg1 Initial value.
|
||||
*/
|
||||
export default class YXmlText extends YText {
|
||||
/**
|
||||
* Creates a Dom Element that mirrors this YXmlText.
|
||||
*
|
||||
* @param {Document} [_document=document] The document object (you must define
|
||||
* this when calling this method in
|
||||
* nodejs)
|
||||
* @param {Object<key:hookDefinition>} [hooks] Optional property to customize how hooks
|
||||
* are presented in the DOM
|
||||
* @param {DomBinding} [binding] You should not set this property. This is
|
||||
* used if DomBinding wants to create a
|
||||
* association to the created DOM type.
|
||||
* @return {Element} The {@link https://developer.mozilla.org/en-US/docs/Web/API/Element|Dom Element}
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
toDom (_document = document, hooks, binding) {
|
||||
const dom = _document.createTextNode(this.toString())
|
||||
createAssociation(binding, dom, this)
|
||||
return dom
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark this Item as deleted.
|
||||
*
|
||||
* @param {Y} y The Yjs instance
|
||||
* @param {boolean} createDelete Whether to propagate a message that this
|
||||
* Type was deleted.
|
||||
* @param {boolean} [gcChildren=y._hasUndoManager===false] Whether to garbage
|
||||
* collect the children of this type.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_delete (y, createDelete, gcChildren) {
|
||||
super._delete(y, createDelete, gcChildren)
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
import YXmlFragment from './YXmlFragment.js'
|
||||
|
||||
/**
|
||||
* Define the elements to which a set of CSS queries apply.
|
||||
* {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors|CSS_Selectors}
|
||||
*
|
||||
* @example
|
||||
* query = '.classSelector'
|
||||
* query = 'nodeSelector'
|
||||
* query = '#idSelector'
|
||||
*
|
||||
* @typedef {string} CSS_Selector
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents a subset of the nodes of a YXmlElement / YXmlFragment and a
|
||||
* position within them.
|
||||
*
|
||||
* Can be created with {@link YXmlFragment#createTreeWalker}
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export default class YXmlTreeWalker {
|
||||
constructor (root, f) {
|
||||
this._filter = f || (() => true)
|
||||
this._root = root
|
||||
this._currentNode = root
|
||||
this._firstCall = true
|
||||
}
|
||||
[Symbol.iterator] () {
|
||||
return this
|
||||
}
|
||||
/**
|
||||
* Get the next node.
|
||||
*
|
||||
* @return {YXmlElement} The next node.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
next () {
|
||||
let n = this._currentNode
|
||||
if (this._firstCall) {
|
||||
this._firstCall = false
|
||||
if (!n._deleted && this._filter(n)) {
|
||||
return { value: n, done: false }
|
||||
}
|
||||
}
|
||||
do {
|
||||
if (!n._deleted && (n.constructor === YXmlFragment._YXmlElement || n.constructor === YXmlFragment) && n._start !== null) {
|
||||
// walk down in the tree
|
||||
n = n._start
|
||||
} else {
|
||||
// walk right or up in the tree
|
||||
while (n !== this._root) {
|
||||
if (n._right !== null) {
|
||||
n = n._right
|
||||
break
|
||||
}
|
||||
n = n._parent
|
||||
}
|
||||
if (n === this._root) {
|
||||
n = null
|
||||
}
|
||||
}
|
||||
if (n === this._root) {
|
||||
break
|
||||
}
|
||||
} while (n !== null && (n._deleted || !this._filter(n)))
|
||||
this._currentNode = n
|
||||
if (n === null) {
|
||||
return { done: true }
|
||||
} else {
|
||||
return { value: n, done: false }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,151 +0,0 @@
|
||||
import ID from '../ID/ID.js'
|
||||
import { default as RootID, RootFakeUserID } from '../ID/RootID.js'
|
||||
|
||||
/**
|
||||
* A BinaryDecoder handles the decoding of an ArrayBuffer.
|
||||
*/
|
||||
export default class BinaryDecoder {
|
||||
/**
|
||||
* @param {Uint8Array|Buffer} buffer The binary data that this instance
|
||||
* decodes.
|
||||
*/
|
||||
constructor (buffer) {
|
||||
if (buffer instanceof ArrayBuffer) {
|
||||
this.uint8arr = new Uint8Array(buffer)
|
||||
} else if (
|
||||
buffer instanceof Uint8Array ||
|
||||
(
|
||||
typeof Buffer !== 'undefined' && buffer instanceof Buffer
|
||||
)
|
||||
) {
|
||||
this.uint8arr = buffer
|
||||
} else {
|
||||
throw new Error('Expected an ArrayBuffer or Uint8Array!')
|
||||
}
|
||||
this.pos = 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone this decoder instance.
|
||||
* Optionally set a new position parameter.
|
||||
*/
|
||||
clone (newPos = this.pos) {
|
||||
let decoder = new BinaryDecoder(this.uint8arr)
|
||||
decoder.pos = newPos
|
||||
return decoder
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of bytes.
|
||||
*/
|
||||
get length () {
|
||||
return this.uint8arr.length
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip one byte, jump to the next position.
|
||||
*/
|
||||
skip8 () {
|
||||
this.pos++
|
||||
}
|
||||
|
||||
/**
|
||||
* Read one byte as unsigned integer.
|
||||
*/
|
||||
readUint8 () {
|
||||
return this.uint8arr[this.pos++]
|
||||
}
|
||||
|
||||
/**
|
||||
* Read 4 bytes as unsigned integer.
|
||||
*
|
||||
* @return {number} An unsigned integer.
|
||||
*/
|
||||
readUint32 () {
|
||||
let uint =
|
||||
this.uint8arr[this.pos] +
|
||||
(this.uint8arr[this.pos + 1] << 8) +
|
||||
(this.uint8arr[this.pos + 2] << 16) +
|
||||
(this.uint8arr[this.pos + 3] << 24)
|
||||
this.pos += 4
|
||||
return uint
|
||||
}
|
||||
|
||||
/**
|
||||
* Look ahead without incrementing position.
|
||||
* to the next byte and read it as unsigned integer.
|
||||
*
|
||||
* @return {number} An unsigned integer.
|
||||
*/
|
||||
peekUint8 () {
|
||||
return this.uint8arr[this.pos]
|
||||
}
|
||||
|
||||
/**
|
||||
* Read unsigned integer (32bit) with variable length.
|
||||
* 1/8th of the storage is used as encoding overhead.
|
||||
* * numbers < 2^7 is stored in one byte.
|
||||
* * numbers < 2^14 is stored in two bytes.
|
||||
*
|
||||
* @return {number} An unsigned integer.
|
||||
*/
|
||||
readVarUint () {
|
||||
let num = 0
|
||||
let len = 0
|
||||
while (true) {
|
||||
let r = this.uint8arr[this.pos++]
|
||||
num = num | ((r & 0b1111111) << len)
|
||||
len += 7
|
||||
if (r < 1 << 7) {
|
||||
return num >>> 0 // return unsigned number!
|
||||
}
|
||||
if (len > 35) {
|
||||
throw new Error('Integer out of range!')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read string of variable length
|
||||
* * varUint is used to store the length of the string
|
||||
*
|
||||
* @return {String} The read String.
|
||||
*/
|
||||
readVarString () {
|
||||
let len = this.readVarUint()
|
||||
let bytes = new Array(len)
|
||||
for (let i = 0; i < len; i++) {
|
||||
bytes[i] = this.uint8arr[this.pos++]
|
||||
}
|
||||
let encodedString = bytes.map(b => String.fromCodePoint(b)).join('')
|
||||
return decodeURIComponent(escape(encodedString))
|
||||
}
|
||||
|
||||
/**
|
||||
* Look ahead and read varString without incrementing position
|
||||
*/
|
||||
peekVarString () {
|
||||
let pos = this.pos
|
||||
let s = this.readVarString()
|
||||
this.pos = pos
|
||||
return s
|
||||
}
|
||||
|
||||
/**
|
||||
* Read ID.
|
||||
* * If first varUint read is 0xFFFFFF a RootID is returned.
|
||||
* * Otherwise an ID is returned.
|
||||
*
|
||||
* @return ID
|
||||
*/
|
||||
readID () {
|
||||
let user = this.readVarUint()
|
||||
if (user === RootFakeUserID) {
|
||||
// read property name and type id
|
||||
const rid = new RootID(this.readVarString(), null)
|
||||
rid.type = this.readVarUint()
|
||||
return rid
|
||||
}
|
||||
return new ID(user, this.readVarUint())
|
||||
}
|
||||
}
|
||||
@@ -1,145 +0,0 @@
|
||||
import { RootFakeUserID } from '../ID/RootID.js'
|
||||
|
||||
const bits7 = 0b1111111
|
||||
const bits8 = 0b11111111
|
||||
|
||||
/**
|
||||
* A BinaryEncoder handles the encoding to an ArrayBuffer.
|
||||
*/
|
||||
export default class BinaryEncoder {
|
||||
constructor () {
|
||||
// TODO: implement chained Uint8Array buffers instead of Array buffer
|
||||
// TODO: Rewrite all methods as functions!
|
||||
this.data = []
|
||||
}
|
||||
|
||||
/**
|
||||
* The current length of the encoded data.
|
||||
*/
|
||||
get length () {
|
||||
return this.data.length
|
||||
}
|
||||
|
||||
/**
|
||||
* The current write pointer (the same as {@link length}).
|
||||
*/
|
||||
get pos () {
|
||||
return this.data.length
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an ArrayBuffer.
|
||||
*
|
||||
* @return {Uint8Array} A Uint8Array that represents the written data.
|
||||
*/
|
||||
createBuffer () {
|
||||
return Uint8Array.from(this.data).buffer
|
||||
}
|
||||
|
||||
/**
|
||||
* Write one byte as an unsigned integer.
|
||||
*
|
||||
* @param {number} num The number that is to be encoded.
|
||||
*/
|
||||
writeUint8 (num) {
|
||||
this.data.push(num & bits8)
|
||||
}
|
||||
|
||||
/**
|
||||
* Write one byte as an unsigned Integer at a specific location.
|
||||
*
|
||||
* @param {number} pos The location where the data will be written.
|
||||
* @param {number} num The number that is to be encoded.
|
||||
*/
|
||||
setUint8 (pos, num) {
|
||||
this.data[pos] = num & bits8
|
||||
}
|
||||
|
||||
/**
|
||||
* Write two bytes as an unsigned integer.
|
||||
*
|
||||
* @param {number} num The number that is to be encoded.
|
||||
*/
|
||||
writeUint16 (num) {
|
||||
this.data.push(num & bits8, (num >>> 8) & bits8)
|
||||
}
|
||||
/**
|
||||
* Write two bytes as an unsigned integer at a specific location.
|
||||
*
|
||||
* @param {number} pos The location where the data will be written.
|
||||
* @param {number} num The number that is to be encoded.
|
||||
*/
|
||||
setUint16 (pos, num) {
|
||||
this.data[pos] = num & bits8
|
||||
this.data[pos + 1] = (num >>> 8) & bits8
|
||||
}
|
||||
|
||||
/**
|
||||
* Write two bytes as an unsigned integer
|
||||
*
|
||||
* @param {number} num The number that is to be encoded.
|
||||
*/
|
||||
writeUint32 (num) {
|
||||
for (let i = 0; i < 4; i++) {
|
||||
this.data.push(num & bits8)
|
||||
num >>>= 8
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write two bytes as an unsigned integer at a specific location.
|
||||
*
|
||||
* @param {number} pos The location where the data will be written.
|
||||
* @param {number} num The number that is to be encoded.
|
||||
*/
|
||||
setUint32 (pos, num) {
|
||||
for (let i = 0; i < 4; i++) {
|
||||
this.data[pos + i] = num & bits8
|
||||
num >>>= 8
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a variable length unsigned integer.
|
||||
*
|
||||
* @param {number} num The number that is to be encoded.
|
||||
*/
|
||||
writeVarUint (num) {
|
||||
while (num >= 0b10000000) {
|
||||
this.data.push(0b10000000 | (bits7 & num))
|
||||
num >>>= 7
|
||||
}
|
||||
this.data.push(bits7 & num)
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a variable length string.
|
||||
*
|
||||
* @param {String} str The string that is to be encoded.
|
||||
*/
|
||||
writeVarString (str) {
|
||||
let encodedString = unescape(encodeURIComponent(str))
|
||||
let bytes = encodedString.split('').map(c => c.codePointAt())
|
||||
let len = bytes.length
|
||||
this.writeVarUint(len)
|
||||
for (let i = 0; i < len; i++) {
|
||||
this.data.push(bytes[i])
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an ID at the current position.
|
||||
*
|
||||
* @param {ID} id The ID that is to be written.
|
||||
*/
|
||||
writeID (id) {
|
||||
const user = id.user
|
||||
this.writeVarUint(user)
|
||||
if (user !== RootFakeUserID) {
|
||||
this.writeVarUint(id.clock)
|
||||
} else {
|
||||
this.writeVarString(id.name)
|
||||
this.writeVarUint(id.type)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
|
||||
/**
|
||||
* General event handler implementation.
|
||||
*/
|
||||
export default class EventHandler {
|
||||
constructor () {
|
||||
this.eventListeners = []
|
||||
}
|
||||
|
||||
/**
|
||||
* To prevent memory leaks, call this method when the eventListeners won't be
|
||||
* used anymore.
|
||||
*/
|
||||
destroy () {
|
||||
this.eventListeners = null
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an event listener that is called when
|
||||
* {@link EventHandler#callEventListeners} is called.
|
||||
*
|
||||
* @param {Function} f The event handler.
|
||||
*/
|
||||
addEventListener (f) {
|
||||
this.eventListeners.push(f)
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an event listener.
|
||||
*
|
||||
* @param {Function} f The event handler that was added with
|
||||
* {@link EventHandler#addEventListener}
|
||||
*/
|
||||
removeEventListener (f) {
|
||||
this.eventListeners = this.eventListeners.filter(function (g) {
|
||||
return f !== g
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all event listeners.
|
||||
*/
|
||||
removeAllEventListeners () {
|
||||
this.eventListeners = []
|
||||
}
|
||||
|
||||
/**
|
||||
* Call all event listeners that were added via
|
||||
* {@link EventHandler#addEventListener}.
|
||||
*
|
||||
* @param {Transaction} transaction The transaction object // TODO: do we need this?
|
||||
* @param {YEvent} event An event object that describes the change on a type.
|
||||
*/
|
||||
callEventListeners (transaction, event) {
|
||||
for (var i = 0; i < this.eventListeners.length; i++) {
|
||||
try {
|
||||
const f = this.eventListeners[i]
|
||||
f(event)
|
||||
} catch (e) {
|
||||
/*
|
||||
Your observer threw an error. This error was caught so that Yjs
|
||||
can ensure data consistency! In order to debug this error you
|
||||
have to check "Pause On Caught Exceptions" in developer tools.
|
||||
*/
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
|
||||
export default class ID {
|
||||
constructor (user, clock) {
|
||||
this.user = user // TODO: rename to client
|
||||
this.clock = clock
|
||||
}
|
||||
clone () {
|
||||
return new ID(this.user, this.clock)
|
||||
}
|
||||
equals (id) {
|
||||
return id !== null && id.user === this.user && id.clock === this.clock
|
||||
}
|
||||
lessThan (id) {
|
||||
if (id.constructor === ID) {
|
||||
return this.user < id.user || (this.user === id.user && this.clock < id.clock)
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user