You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

10675 lines
344 KiB

3 years ago
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
  1. /* @license C3.js v0.6.8 | (c) C3 Team and other contributors | http://c3js.org/ */
  2. (function (global, factory) {
  3. typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
  4. typeof define === 'function' && define.amd ? define(factory) :
  5. (global.c3 = factory());
  6. }(this, (function () { 'use strict';
  7. function _typeof(obj) {
  8. if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
  9. _typeof = function (obj) {
  10. return typeof obj;
  11. };
  12. } else {
  13. _typeof = function (obj) {
  14. return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
  15. };
  16. }
  17. return _typeof(obj);
  18. }
  19. function _classCallCheck(instance, Constructor) {
  20. if (!(instance instanceof Constructor)) {
  21. throw new TypeError("Cannot call a class as a function");
  22. }
  23. }
  24. function _defineProperty(obj, key, value) {
  25. if (key in obj) {
  26. Object.defineProperty(obj, key, {
  27. value: value,
  28. enumerable: true,
  29. configurable: true,
  30. writable: true
  31. });
  32. } else {
  33. obj[key] = value;
  34. }
  35. return obj;
  36. }
  37. function ChartInternal(api) {
  38. var $$ = this;
  39. $$.d3 = window.d3 ? window.d3 : typeof require !== 'undefined' ? require("d3") : undefined;
  40. $$.api = api;
  41. $$.config = $$.getDefaultConfig();
  42. $$.data = {};
  43. $$.cache = {};
  44. $$.axes = {};
  45. }
  46. function Chart(config) {
  47. var $$ = this.internal = new ChartInternal(this);
  48. $$.loadConfig(config);
  49. $$.beforeInit(config);
  50. $$.init();
  51. $$.afterInit(config); // bind "this" to nested API
  52. (function bindThis(fn, target, argThis) {
  53. Object.keys(fn).forEach(function (key) {
  54. target[key] = fn[key].bind(argThis);
  55. if (Object.keys(fn[key]).length > 0) {
  56. bindThis(fn[key], target[key], argThis);
  57. }
  58. });
  59. })(Chart.prototype, this, this);
  60. }
  61. function AxisInternal(component, params) {
  62. var internal = this;
  63. internal.component = component;
  64. internal.params = params || {};
  65. internal.d3 = component.d3;
  66. internal.scale = internal.d3.scaleLinear();
  67. internal.range;
  68. internal.orient = "bottom";
  69. internal.innerTickSize = 6;
  70. internal.outerTickSize = this.params.withOuterTick ? 6 : 0;
  71. internal.tickPadding = 3;
  72. internal.tickValues = null;
  73. internal.tickFormat;
  74. internal.tickArguments;
  75. internal.tickOffset = 0;
  76. internal.tickCulling = true;
  77. internal.tickCentered;
  78. internal.tickTextCharSize;
  79. internal.tickTextRotate = internal.params.tickTextRotate;
  80. internal.tickLength;
  81. internal.axis = internal.generateAxis();
  82. }
  83. AxisInternal.prototype.axisX = function (selection, x, tickOffset) {
  84. selection.attr("transform", function (d) {
  85. return "translate(" + Math.ceil(x(d) + tickOffset) + ", 0)";
  86. });
  87. };
  88. AxisInternal.prototype.axisY = function (selection, y) {
  89. selection.attr("transform", function (d) {
  90. return "translate(0," + Math.ceil(y(d)) + ")";
  91. });
  92. };
  93. AxisInternal.prototype.scaleExtent = function (domain) {
  94. var start = domain[0],
  95. stop = domain[domain.length - 1];
  96. return start < stop ? [start, stop] : [stop, start];
  97. };
  98. AxisInternal.prototype.generateTicks = function (scale) {
  99. var internal = this;
  100. var i,
  101. domain,
  102. ticks = [];
  103. if (scale.ticks) {
  104. return scale.ticks.apply(scale, internal.tickArguments);
  105. }
  106. domain = scale.domain();
  107. for (i = Math.ceil(domain[0]); i < domain[1]; i++) {
  108. ticks.push(i);
  109. }
  110. if (ticks.length > 0 && ticks[0] > 0) {
  111. ticks.unshift(ticks[0] - (ticks[1] - ticks[0]));
  112. }
  113. return ticks;
  114. };
  115. AxisInternal.prototype.copyScale = function () {
  116. var internal = this;
  117. var newScale = internal.scale.copy(),
  118. domain;
  119. if (internal.params.isCategory) {
  120. domain = internal.scale.domain();
  121. newScale.domain([domain[0], domain[1] - 1]);
  122. }
  123. return newScale;
  124. };
  125. AxisInternal.prototype.textFormatted = function (v) {
  126. var internal = this,
  127. formatted = internal.tickFormat ? internal.tickFormat(v) : v;
  128. return typeof formatted !== 'undefined' ? formatted : '';
  129. };
  130. AxisInternal.prototype.updateRange = function () {
  131. var internal = this;
  132. internal.range = internal.scale.rangeExtent ? internal.scale.rangeExtent() : internal.scaleExtent(internal.scale.range());
  133. return internal.range;
  134. };
  135. AxisInternal.prototype.updateTickTextCharSize = function (tick) {
  136. var internal = this;
  137. if (internal.tickTextCharSize) {
  138. return internal.tickTextCharSize;
  139. }
  140. var size = {
  141. h: 11.5,
  142. w: 5.5
  143. };
  144. tick.select('text').text(function (d) {
  145. return internal.textFormatted(d);
  146. }).each(function (d) {
  147. var box = this.getBoundingClientRect(),
  148. text = internal.textFormatted(d),
  149. h = box.height,
  150. w = text ? box.width / text.length : undefined;
  151. if (h && w) {
  152. size.h = h;
  153. size.w = w;
  154. }
  155. }).text('');
  156. internal.tickTextCharSize = size;
  157. return size;
  158. };
  159. AxisInternal.prototype.isVertical = function () {
  160. return this.orient === 'left' || this.orient === 'right';
  161. };
  162. AxisInternal.prototype.tspanData = function (d, i, scale) {
  163. var internal = this;
  164. var splitted = internal.params.tickMultiline ? internal.splitTickText(d, scale) : [].concat(internal.textFormatted(d));
  165. if (internal.params.tickMultiline && internal.params.tickMultilineMax > 0) {
  166. splitted = internal.ellipsify(splitted, internal.params.tickMultilineMax);
  167. }
  168. return splitted.map(function (s) {
  169. return {
  170. index: i,
  171. splitted: s,
  172. length: splitted.length
  173. };
  174. });
  175. };
  176. AxisInternal.prototype.splitTickText = function (d, scale) {
  177. var internal = this,
  178. tickText = internal.textFormatted(d),
  179. maxWidth = internal.params.tickWidth,
  180. subtext,
  181. spaceIndex,
  182. textWidth,
  183. splitted = [];
  184. if (Object.prototype.toString.call(tickText) === "[object Array]") {
  185. return tickText;
  186. }
  187. if (!maxWidth || maxWidth <= 0) {
  188. maxWidth = internal.isVertical() ? 95 : internal.params.isCategory ? Math.ceil(scale(1) - scale(0)) - 12 : 110;
  189. }
  190. function split(splitted, text) {
  191. spaceIndex = undefined;
  192. for (var i = 1; i < text.length; i++) {
  193. if (text.charAt(i) === ' ') {
  194. spaceIndex = i;
  195. }
  196. subtext = text.substr(0, i + 1);
  197. textWidth = internal.tickTextCharSize.w * subtext.length; // if text width gets over tick width, split by space index or crrent index
  198. if (maxWidth < textWidth) {
  199. return split(splitted.concat(text.substr(0, spaceIndex ? spaceIndex : i)), text.slice(spaceIndex ? spaceIndex + 1 : i));
  200. }
  201. }
  202. return splitted.concat(text);
  203. }
  204. return split(splitted, tickText + "");
  205. };
  206. AxisInternal.prototype.ellipsify = function (splitted, max) {
  207. if (splitted.length <= max) {
  208. return splitted;
  209. }
  210. var ellipsified = splitted.slice(0, max);
  211. var remaining = 3;
  212. for (var i = max - 1; i >= 0; i--) {
  213. var available = ellipsified[i].length;
  214. ellipsified[i] = ellipsified[i].substr(0, available - remaining).padEnd(available, '.');
  215. remaining -= available;
  216. if (remaining <= 0) {
  217. break;
  218. }
  219. }
  220. return ellipsified;
  221. };
  222. AxisInternal.prototype.updateTickLength = function () {
  223. var internal = this;
  224. internal.tickLength = Math.max(internal.innerTickSize, 0) + internal.tickPadding;
  225. };
  226. AxisInternal.prototype.lineY2 = function (d) {
  227. var internal = this,
  228. tickPosition = internal.scale(d) + (internal.tickCentered ? 0 : internal.tickOffset);
  229. return internal.range[0] < tickPosition && tickPosition < internal.range[1] ? internal.innerTickSize : 0;
  230. };
  231. AxisInternal.prototype.textY = function () {
  232. var internal = this,
  233. rotate = internal.tickTextRotate;
  234. return rotate ? 11.5 - 2.5 * (rotate / 15) * (rotate > 0 ? 1 : -1) : internal.tickLength;
  235. };
  236. AxisInternal.prototype.textTransform = function () {
  237. var internal = this,
  238. rotate = internal.tickTextRotate;
  239. return rotate ? "rotate(" + rotate + ")" : "";
  240. };
  241. AxisInternal.prototype.textTextAnchor = function () {
  242. var internal = this,
  243. rotate = internal.tickTextRotate;
  244. return rotate ? rotate > 0 ? "start" : "end" : "middle";
  245. };
  246. AxisInternal.prototype.tspanDx = function () {
  247. var internal = this,
  248. rotate = internal.tickTextRotate;
  249. return rotate ? 8 * Math.sin(Math.PI * (rotate / 180)) : 0;
  250. };
  251. AxisInternal.prototype.tspanDy = function (d, i) {
  252. var internal = this,
  253. dy = internal.tickTextCharSize.h;
  254. if (i === 0) {
  255. if (internal.isVertical()) {
  256. dy = -((d.length - 1) * (internal.tickTextCharSize.h / 2) - 3);
  257. } else {
  258. dy = ".71em";
  259. }
  260. }
  261. return dy;
  262. };
  263. AxisInternal.prototype.generateAxis = function () {
  264. var internal = this,
  265. d3 = internal.d3,
  266. params = internal.params;
  267. function axis(g, transition) {
  268. var self;
  269. g.each(function () {
  270. var g = axis.g = d3.select(this);
  271. var scale0 = this.__chart__ || internal.scale,
  272. scale1 = this.__chart__ = internal.copyScale();
  273. var ticksValues = internal.tickValues ? internal.tickValues : internal.generateTicks(scale1),
  274. ticks = g.selectAll(".tick").data(ticksValues, scale1),
  275. tickEnter = ticks.enter().insert("g", ".domain").attr("class", "tick").style("opacity", 1e-6),
  276. // MEMO: No exit transition. The reason is this transition affects max tick width calculation because old tick will be included in the ticks.
  277. tickExit = ticks.exit().remove(),
  278. tickUpdate = ticks.merge(tickEnter),
  279. tickTransform,
  280. tickX,
  281. tickY;
  282. if (params.isCategory) {
  283. internal.tickOffset = Math.ceil((scale1(1) - scale1(0)) / 2);
  284. tickX = internal.tickCentered ? 0 : internal.tickOffset;
  285. tickY = internal.tickCentered ? internal.tickOffset : 0;
  286. } else {
  287. internal.tickOffset = tickX = 0;
  288. }
  289. internal.updateRange();
  290. internal.updateTickLength();
  291. internal.updateTickTextCharSize(g.select('.tick'));
  292. var lineUpdate = tickUpdate.select("line").merge(tickEnter.append("line")),
  293. textUpdate = tickUpdate.select("text").merge(tickEnter.append("text"));
  294. var tspans = tickUpdate.selectAll('text').selectAll('tspan').data(function (d, i) {
  295. return internal.tspanData(d, i, scale1);
  296. }),
  297. tspanEnter = tspans.enter().append('tspan'),
  298. tspanUpdate = tspanEnter.merge(tspans).text(function (d) {
  299. return d.splitted;
  300. });
  301. tspans.exit().remove();
  302. var path = g.selectAll(".domain").data([0]),
  303. pathUpdate = path.enter().append("path").merge(path).attr("class", "domain"); // TODO: each attr should be one function and change its behavior by internal.orient, probably
  304. switch (internal.orient) {
  305. case "bottom":
  306. {
  307. tickTransform = internal.axisX;
  308. lineUpdate.attr("x1", tickX).attr("x2", tickX).attr("y2", function (d, i) {
  309. return internal.lineY2(d, i);
  310. });
  311. textUpdate.attr("x", 0).attr("y", function (d, i) {
  312. return internal.textY(d, i);
  313. }).attr("transform", function (d, i) {
  314. return internal.textTransform(d, i);
  315. }).style("text-anchor", function (d, i) {
  316. return internal.textTextAnchor(d, i);
  317. });
  318. tspanUpdate.attr('x', 0).attr("dy", function (d, i) {
  319. return internal.tspanDy(d, i);
  320. }).attr('dx', function (d, i) {
  321. return internal.tspanDx(d, i);
  322. });
  323. pathUpdate.attr("d", "M" + internal.range[0] + "," + internal.outerTickSize + "V0H" + internal.range[1] + "V" + internal.outerTickSize);
  324. break;
  325. }
  326. case "top":
  327. {
  328. // TODO: rotated tick text
  329. tickTransform = internal.axisX;
  330. lineUpdate.attr("x1", tickX).attr("x2", tickX).attr("y2", function (d, i) {
  331. return -1 * internal.lineY2(d, i);
  332. });
  333. textUpdate.attr("x", 0).attr("y", function (d, i) {
  334. return -1 * internal.textY(d, i) - (params.isCategory ? 2 : internal.tickLength - 2);
  335. }).attr("transform", function (d, i) {
  336. return internal.textTransform(d, i);
  337. }).style("text-anchor", function (d, i) {
  338. return internal.textTextAnchor(d, i);
  339. });
  340. tspanUpdate.attr('x', 0).attr("dy", function (d, i) {
  341. return internal.tspanDy(d, i);
  342. }).attr('dx', function (d, i) {
  343. return internal.tspanDx(d, i);
  344. });
  345. pathUpdate.attr("d", "M" + internal.range[0] + "," + -internal.outerTickSize + "V0H" + internal.range[1] + "V" + -internal.outerTickSize);
  346. break;
  347. }
  348. case "left":
  349. {
  350. tickTransform = internal.axisY;
  351. lineUpdate.attr("x2", -internal.innerTickSize).attr("y1", tickY).attr("y2", tickY);
  352. textUpdate.attr("x", -internal.tickLength).attr("y", internal.tickOffset).style("text-anchor", "end");
  353. tspanUpdate.attr('x', -internal.tickLength).attr("dy", function (d, i) {
  354. return internal.tspanDy(d, i);
  355. });
  356. pathUpdate.attr("d", "M" + -internal.outerTickSize + "," + internal.range[0] + "H0V" + internal.range[1] + "H" + -internal.outerTickSize);
  357. break;
  358. }
  359. case "right":
  360. {
  361. tickTransform = internal.axisY;
  362. lineUpdate.attr("x2", internal.innerTickSize).attr("y1", tickY).attr("y2", tickY);
  363. textUpdate.attr("x", internal.tickLength).attr("y", internal.tickOffset).style("text-anchor", "start");
  364. tspanUpdate.attr('x', internal.tickLength).attr("dy", function (d, i) {
  365. return internal.tspanDy(d, i);
  366. });
  367. pathUpdate.attr("d", "M" + internal.outerTickSize + "," + internal.range[0] + "H0V" + internal.range[1] + "H" + internal.outerTickSize);
  368. break;
  369. }
  370. }
  371. if (scale1.rangeBand) {
  372. var x = scale1,
  373. dx = x.rangeBand() / 2;
  374. scale0 = scale1 = function scale1(d) {
  375. return x(d) + dx;
  376. };
  377. } else if (scale0.rangeBand) {
  378. scale0 = scale1;
  379. } else {
  380. tickExit.call(tickTransform, scale1, internal.tickOffset);
  381. }
  382. tickEnter.call(tickTransform, scale0, internal.tickOffset);
  383. self = (transition ? tickUpdate.transition(transition) : tickUpdate).style('opacity', 1).call(tickTransform, scale1, internal.tickOffset);
  384. });
  385. return self;
  386. }
  387. axis.scale = function (x) {
  388. if (!arguments.length) {
  389. return internal.scale;
  390. }
  391. internal.scale = x;
  392. return axis;
  393. };
  394. axis.orient = function (x) {
  395. if (!arguments.length) {
  396. return internal.orient;
  397. }
  398. internal.orient = x in {
  399. top: 1,
  400. right: 1,
  401. bottom: 1,
  402. left: 1
  403. } ? x + "" : "bottom";
  404. return axis;
  405. };
  406. axis.tickFormat = function (format) {
  407. if (!arguments.length) {
  408. return internal.tickFormat;
  409. }
  410. internal.tickFormat = format;
  411. return axis;
  412. };
  413. axis.tickCentered = function (isCentered) {
  414. if (!arguments.length) {
  415. return internal.tickCentered;
  416. }
  417. internal.tickCentered = isCentered;
  418. return axis;
  419. };
  420. axis.tickOffset = function () {
  421. return internal.tickOffset;
  422. };
  423. axis.tickInterval = function () {
  424. var interval, length;
  425. if (params.isCategory) {
  426. interval = internal.tickOffset * 2;
  427. } else {
  428. length = axis.g.select('path.domain').node().getTotalLength() - internal.outerTickSize * 2;
  429. interval = length / axis.g.selectAll('line').size();
  430. }
  431. return interval === Infinity ? 0 : interval;
  432. };
  433. axis.ticks = function () {
  434. if (!arguments.length) {
  435. return internal.tickArguments;
  436. }
  437. internal.tickArguments = arguments;
  438. return axis;
  439. };
  440. axis.tickCulling = function (culling) {
  441. if (!arguments.length) {
  442. return internal.tickCulling;
  443. }
  444. internal.tickCulling = culling;
  445. return axis;
  446. };
  447. axis.tickValues = function (x) {
  448. if (typeof x === 'function') {
  449. internal.tickValues = function () {
  450. return x(internal.scale.domain());
  451. };
  452. } else {
  453. if (!arguments.length) {
  454. return internal.tickValues;
  455. }
  456. internal.tickValues = x;
  457. }
  458. return axis;
  459. };
  460. return axis;
  461. };
  462. var CLASS = {
  463. target: 'c3-target',
  464. chart: 'c3-chart',
  465. chartLine: 'c3-chart-line',
  466. chartLines: 'c3-chart-lines',
  467. chartBar: 'c3-chart-bar',
  468. chartBars: 'c3-chart-bars',
  469. chartText: 'c3-chart-text',
  470. chartTexts: 'c3-chart-texts',
  471. chartArc: 'c3-chart-arc',
  472. chartArcs: 'c3-chart-arcs',
  473. chartArcsTitle: 'c3-chart-arcs-title',
  474. chartArcsBackground: 'c3-chart-arcs-background',
  475. chartArcsGaugeUnit: 'c3-chart-arcs-gauge-unit',
  476. chartArcsGaugeMax: 'c3-chart-arcs-gauge-max',
  477. chartArcsGaugeMin: 'c3-chart-arcs-gauge-min',
  478. selectedCircle: 'c3-selected-circle',
  479. selectedCircles: 'c3-selected-circles',
  480. eventRect: 'c3-event-rect',
  481. eventRects: 'c3-event-rects',
  482. eventRectsSingle: 'c3-event-rects-single',
  483. eventRectsMultiple: 'c3-event-rects-multiple',
  484. zoomRect: 'c3-zoom-rect',
  485. brush: 'c3-brush',
  486. dragZoom: 'c3-drag-zoom',
  487. focused: 'c3-focused',
  488. defocused: 'c3-defocused',
  489. region: 'c3-region',
  490. regions: 'c3-regions',
  491. title: 'c3-title',
  492. tooltipContainer: 'c3-tooltip-container',
  493. tooltip: 'c3-tooltip',
  494. tooltipName: 'c3-tooltip-name',
  495. shape: 'c3-shape',
  496. shapes: 'c3-shapes',
  497. line: 'c3-line',
  498. lines: 'c3-lines',
  499. bar: 'c3-bar',
  500. bars: 'c3-bars',
  501. circle: 'c3-circle',
  502. circles: 'c3-circles',
  503. arc: 'c3-arc',
  504. arcLabelLine: 'c3-arc-label-line',
  505. arcs: 'c3-arcs',
  506. area: 'c3-area',
  507. areas: 'c3-areas',
  508. empty: 'c3-empty',
  509. text: 'c3-text',
  510. texts: 'c3-texts',
  511. gaugeValue: 'c3-gauge-value',
  512. grid: 'c3-grid',
  513. gridLines: 'c3-grid-lines',
  514. xgrid: 'c3-xgrid',
  515. xgrids: 'c3-xgrids',
  516. xgridLine: 'c3-xgrid-line',
  517. xgridLines: 'c3-xgrid-lines',
  518. xgridFocus: 'c3-xgrid-focus',
  519. ygrid: 'c3-ygrid',
  520. ygrids: 'c3-ygrids',
  521. ygridLine: 'c3-ygrid-line',
  522. ygridLines: 'c3-ygrid-lines',
  523. axis: 'c3-axis',
  524. axisX: 'c3-axis-x',
  525. axisXLabel: 'c3-axis-x-label',
  526. axisY: 'c3-axis-y',
  527. axisYLabel: 'c3-axis-y-label',
  528. axisY2: 'c3-axis-y2',
  529. axisY2Label: 'c3-axis-y2-label',
  530. legendBackground: 'c3-legend-background',
  531. legendItem: 'c3-legend-item',
  532. legendItemEvent: 'c3-legend-item-event',
  533. legendItemTile: 'c3-legend-item-tile',
  534. legendItemHidden: 'c3-legend-item-hidden',
  535. legendItemFocused: 'c3-legend-item-focused',
  536. dragarea: 'c3-dragarea',
  537. EXPANDED: '_expanded_',
  538. SELECTED: '_selected_',
  539. INCLUDED: '_included_'
  540. };
  541. var asHalfPixel = function asHalfPixel(n) {
  542. return Math.ceil(n) + 0.5;
  543. };
  544. var ceil10 = function ceil10(v) {
  545. return Math.ceil(v / 10) * 10;
  546. };
  547. var diffDomain = function diffDomain(d) {
  548. return d[1] - d[0];
  549. };
  550. var getOption = function getOption(options, key, defaultValue) {
  551. return isDefined(options[key]) ? options[key] : defaultValue;
  552. };
  553. var getPathBox = function getPathBox(path) {
  554. var box = path.getBoundingClientRect(),
  555. items = [path.pathSegList.getItem(0), path.pathSegList.getItem(1)],
  556. minX = items[0].x,
  557. minY = Math.min(items[0].y, items[1].y);
  558. return {
  559. x: minX,
  560. y: minY,
  561. width: box.width,
  562. height: box.height
  563. };
  564. };
  565. var hasValue = function hasValue(dict, value) {
  566. var found = false;
  567. Object.keys(dict).forEach(function (key) {
  568. if (dict[key] === value) {
  569. found = true;
  570. }
  571. });
  572. return found;
  573. };
  574. var isArray = function isArray(o) {
  575. return Array.isArray(o);
  576. };
  577. var isDefined = function isDefined(v) {
  578. return typeof v !== 'undefined';
  579. };
  580. var isEmpty = function isEmpty(o) {
  581. return typeof o === 'undefined' || o === null || isString(o) && o.length === 0 || _typeof(o) === 'object' && Object.keys(o).length === 0;
  582. };
  583. var isFunction = function isFunction(o) {
  584. return typeof o === 'function';
  585. };
  586. var isString = function isString(o) {
  587. return typeof o === 'string';
  588. };
  589. var isUndefined = function isUndefined(v) {
  590. return typeof v === 'undefined';
  591. };
  592. var isValue = function isValue(v) {
  593. return v || v === 0;
  594. };
  595. var notEmpty = function notEmpty(o) {
  596. return !isEmpty(o);
  597. };
  598. var sanitise = function sanitise(str) {
  599. return typeof str === 'string' ? str.replace(/</g, '&lt;').replace(/>/g, '&gt;') : str;
  600. };
  601. var Axis = function Axis(owner) {
  602. _classCallCheck(this, Axis);
  603. this.owner = owner;
  604. this.d3 = owner.d3;
  605. this.internal = AxisInternal;
  606. };
  607. Axis.prototype.init = function init() {
  608. var $$ = this.owner,
  609. config = $$.config,
  610. main = $$.main;
  611. $$.axes.x = main.append("g").attr("class", CLASS.axis + ' ' + CLASS.axisX).attr("clip-path", config.axis_x_inner ? "" : $$.clipPathForXAxis).attr("transform", $$.getTranslate('x')).style("visibility", config.axis_x_show ? 'visible' : 'hidden');
  612. $$.axes.x.append("text").attr("class", CLASS.axisXLabel).attr("transform", config.axis_rotated ? "rotate(-90)" : "").style("text-anchor", this.textAnchorForXAxisLabel.bind(this));
  613. $$.axes.y = main.append("g").attr("class", CLASS.axis + ' ' + CLASS.axisY).attr("clip-path", config.axis_y_inner ? "" : $$.clipPathForYAxis).attr("transform", $$.getTranslate('y')).style("visibility", config.axis_y_show ? 'visible' : 'hidden');
  614. $$.axes.y.append("text").attr("class", CLASS.axisYLabel).attr("transform", config.axis_rotated ? "" : "rotate(-90)").style("text-anchor", this.textAnchorForYAxisLabel.bind(this));
  615. $$.axes.y2 = main.append("g").attr("class", CLASS.axis + ' ' + CLASS.axisY2) // clip-path?
  616. .attr("transform", $$.getTranslate('y2')).style("visibility", config.axis_y2_show ? 'visible' : 'hidden');
  617. $$.axes.y2.append("text").attr("class", CLASS.axisY2Label).attr("transform", config.axis_rotated ? "" : "rotate(-90)").style("text-anchor", this.textAnchorForY2AxisLabel.bind(this));
  618. };
  619. Axis.prototype.getXAxis = function getXAxis(scale, orient, tickFormat, tickValues, withOuterTick, withoutTransition, withoutRotateTickText) {
  620. var $$ = this.owner,
  621. config = $$.config,
  622. axisParams = {
  623. isCategory: $$.isCategorized(),
  624. withOuterTick: withOuterTick,
  625. tickMultiline: config.axis_x_tick_multiline,
  626. tickMultilineMax: config.axis_x_tick_multiline ? Number(config.axis_x_tick_multilineMax) : 0,
  627. tickWidth: config.axis_x_tick_width,
  628. tickTextRotate: withoutRotateTickText ? 0 : config.axis_x_tick_rotate,
  629. withoutTransition: withoutTransition
  630. },
  631. axis = new this.internal(this, axisParams).axis.scale(scale).orient(orient);
  632. if ($$.isTimeSeries() && tickValues && typeof tickValues !== "function") {
  633. tickValues = tickValues.map(function (v) {
  634. return $$.parseDate(v);
  635. });
  636. } // Set tick
  637. axis.tickFormat(tickFormat).tickValues(tickValues);
  638. if ($$.isCategorized()) {
  639. axis.tickCentered(config.axis_x_tick_centered);
  640. if (isEmpty(config.axis_x_tick_culling)) {
  641. config.axis_x_tick_culling = false;
  642. }
  643. }
  644. return axis;
  645. };
  646. Axis.prototype.updateXAxisTickValues = function updateXAxisTickValues(targets, axis) {
  647. var $$ = this.owner,
  648. config = $$.config,
  649. tickValues;
  650. if (config.axis_x_tick_fit || config.axis_x_tick_count) {
  651. tickValues = this.generateTickValues($$.mapTargetsToUniqueXs(targets), config.axis_x_tick_count, $$.isTimeSeries());
  652. }
  653. if (axis) {
  654. axis.tickValues(tickValues);
  655. } else {
  656. $$.xAxis.tickValues(tickValues);
  657. $$.subXAxis.tickValues(tickValues);
  658. }
  659. return tickValues;
  660. };
  661. Axis.prototype.getYAxis = function getYAxis(scale, orient, tickFormat, tickValues, withOuterTick, withoutTransition, withoutRotateTickText) {
  662. var $$ = this.owner,
  663. config = $$.config,
  664. axisParams = {
  665. withOuterTick: withOuterTick,
  666. withoutTransition: withoutTransition,
  667. tickTextRotate: withoutRotateTickText ? 0 : config.axis_y_tick_rotate
  668. },
  669. axis = new this.internal(this, axisParams).axis.scale(scale).orient(orient).tickFormat(tickFormat);
  670. if ($$.isTimeSeriesY()) {
  671. axis.ticks(config.axis_y_tick_time_type, config.axis_y_tick_time_interval);
  672. } else {
  673. axis.tickValues(tickValues);
  674. }
  675. return axis;
  676. };
  677. Axis.prototype.getId = function getId(id) {
  678. var config = this.owner.config;
  679. return id in config.data_axes ? config.data_axes[id] : 'y';
  680. };
  681. Axis.prototype.getXAxisTickFormat = function getXAxisTickFormat() {
  682. // #2251 previously set any negative values to a whole number,
  683. // however both should be truncated according to the users format specification
  684. var $$ = this.owner,
  685. config = $$.config;
  686. var format = $$.isTimeSeries() ? $$.defaultAxisTimeFormat : $$.isCategorized() ? $$.categoryName : function (v) {
  687. return v;
  688. };
  689. if (config.axis_x_tick_format) {
  690. if (isFunction(config.axis_x_tick_format)) {
  691. format = config.axis_x_tick_format;
  692. } else if ($$.isTimeSeries()) {
  693. format = function format(date) {
  694. return date ? $$.axisTimeFormat(config.axis_x_tick_format)(date) : "";
  695. };
  696. }
  697. }
  698. return isFunction(format) ? function (v) {
  699. return format.call($$, v);
  700. } : format;
  701. };
  702. Axis.prototype.getTickValues = function getTickValues(tickValues, axis) {
  703. return tickValues ? tickValues : axis ? axis.tickValues() : undefined;
  704. };
  705. Axis.prototype.getXAxisTickValues = function getXAxisTickValues() {
  706. return this.getTickValues(this.owner.config.axis_x_tick_values, this.owner.xAxis);
  707. };
  708. Axis.prototype.getYAxisTickValues = function getYAxisTickValues() {
  709. return this.getTickValues(this.owner.config.axis_y_tick_values, this.owner.yAxis);
  710. };
  711. Axis.prototype.getY2AxisTickValues = function getY2AxisTickValues() {
  712. return this.getTickValues(this.owner.config.axis_y2_tick_values, this.owner.y2Axis);
  713. };
  714. Axis.prototype.getLabelOptionByAxisId = function getLabelOptionByAxisId(axisId) {
  715. var $$ = this.owner,
  716. config = $$.config,
  717. option;
  718. if (axisId === 'y') {
  719. option = config.axis_y_label;
  720. } else if (axisId === 'y2') {
  721. option = config.axis_y2_label;
  722. } else if (axisId === 'x') {
  723. option = config.axis_x_label;
  724. }
  725. return option;
  726. };
  727. Axis.prototype.getLabelText = function getLabelText(axisId) {
  728. var option = this.getLabelOptionByAxisId(axisId);
  729. return isString(option) ? option : option ? option.text : null;
  730. };
  731. Axis.prototype.setLabelText = function setLabelText(axisId, text) {
  732. var $$ = this.owner,
  733. config = $$.config,
  734. option = this.getLabelOptionByAxisId(axisId);
  735. if (isString(option)) {
  736. if (axisId === 'y') {
  737. config.axis_y_label = text;
  738. } else if (axisId === 'y2') {
  739. config.axis_y2_label = text;
  740. } else if (axisId === 'x') {
  741. config.axis_x_label = text;
  742. }
  743. } else if (option) {
  744. option.text = text;
  745. }
  746. };
  747. Axis.prototype.getLabelPosition = function getLabelPosition(axisId, defaultPosition) {
  748. var option = this.getLabelOptionByAxisId(axisId),
  749. position = option && _typeof(option) === 'object' && option.position ? option.position : defaultPosition;
  750. return {
  751. isInner: position.indexOf('inner') >= 0,
  752. isOuter: position.indexOf('outer') >= 0,
  753. isLeft: position.indexOf('left') >= 0,
  754. isCenter: position.indexOf('center') >= 0,
  755. isRight: position.indexOf('right') >= 0,
  756. isTop: position.indexOf('top') >= 0,
  757. isMiddle: position.indexOf('middle') >= 0,
  758. isBottom: position.indexOf('bottom') >= 0
  759. };
  760. };
  761. Axis.prototype.getXAxisLabelPosition = function getXAxisLabelPosition() {
  762. return this.getLabelPosition('x', this.owner.config.axis_rotated ? 'inner-top' : 'inner-right');
  763. };
  764. Axis.prototype.getYAxisLabelPosition = function getYAxisLabelPosition() {
  765. return this.getLabelPosition('y', this.owner.config.axis_rotated ? 'inner-right' : 'inner-top');
  766. };
  767. Axis.prototype.getY2AxisLabelPosition = function getY2AxisLabelPosition() {
  768. return this.getLabelPosition('y2', this.owner.config.axis_rotated ? 'inner-right' : 'inner-top');
  769. };
  770. Axis.prototype.getLabelPositionById = function getLabelPositionById(id) {
  771. return id === 'y2' ? this.getY2AxisLabelPosition() : id === 'y' ? this.getYAxisLabelPosition() : this.getXAxisLabelPosition();
  772. };
  773. Axis.prototype.textForXAxisLabel = function textForXAxisLabel() {
  774. return this.getLabelText('x');
  775. };
  776. Axis.prototype.textForYAxisLabel = function textForYAxisLabel() {
  777. return this.getLabelText('y');
  778. };
  779. Axis.prototype.textForY2AxisLabel = function textForY2AxisLabel() {
  780. return this.getLabelText('y2');
  781. };
  782. Axis.prototype.xForAxisLabel = function xForAxisLabel(forHorizontal, position) {
  783. var $$ = this.owner;
  784. if (forHorizontal) {
  785. return position.isLeft ? 0 : position.isCenter ? $$.width / 2 : $$.width;
  786. } else {
  787. return position.isBottom ? -$$.height : position.isMiddle ? -$$.height / 2 : 0;
  788. }
  789. };
  790. Axis.prototype.dxForAxisLabel = function dxForAxisLabel(forHorizontal, position) {
  791. if (forHorizontal) {
  792. return position.isLeft ? "0.5em" : position.isRight ? "-0.5em" : "0";
  793. } else {
  794. return position.isTop ? "-0.5em" : position.isBottom ? "0.5em" : "0";
  795. }
  796. };
  797. Axis.prototype.textAnchorForAxisLabel = function textAnchorForAxisLabel(forHorizontal, position) {
  798. if (forHorizontal) {
  799. return position.isLeft ? 'start' : position.isCenter ? 'middle' : 'end';
  800. } else {
  801. return position.isBottom ? 'start' : position.isMiddle ? 'middle' : 'end';
  802. }
  803. };
  804. Axis.prototype.xForXAxisLabel = function xForXAxisLabel() {
  805. return this.xForAxisLabel(!this.owner.config.axis_rotated, this.getXAxisLabelPosition());
  806. };
  807. Axis.prototype.xForYAxisLabel = function xForYAxisLabel() {
  808. return this.xForAxisLabel(this.owner.config.axis_rotated, this.getYAxisLabelPosition());
  809. };
  810. Axis.prototype.xForY2AxisLabel = function xForY2AxisLabel() {
  811. return this.xForAxisLabel(this.owner.config.axis_rotated, this.getY2AxisLabelPosition());
  812. };
  813. Axis.prototype.dxForXAxisLabel = function dxForXAxisLabel() {
  814. return this.dxForAxisLabel(!this.owner.config.axis_rotated, this.getXAxisLabelPosition());
  815. };
  816. Axis.prototype.dxForYAxisLabel = function dxForYAxisLabel() {
  817. return this.dxForAxisLabel(this.owner.config.axis_rotated, this.getYAxisLabelPosition());
  818. };
  819. Axis.prototype.dxForY2AxisLabel = function dxForY2AxisLabel() {
  820. return this.dxForAxisLabel(this.owner.config.axis_rotated, this.getY2AxisLabelPosition());
  821. };
  822. Axis.prototype.dyForXAxisLabel = function dyForXAxisLabel() {
  823. var $$ = this.owner,
  824. config = $$.config,
  825. position = this.getXAxisLabelPosition();
  826. if (config.axis_rotated) {
  827. return position.isInner ? "1.2em" : -25 - ($$.config.axis_x_inner ? 0 : this.getMaxTickWidth('x'));
  828. } else {
  829. return position.isInner ? "-0.5em" : config.axis_x_height ? config.axis_x_height - 10 : "3em";
  830. }
  831. };
  832. Axis.prototype.dyForYAxisLabel = function dyForYAxisLabel() {
  833. var $$ = this.owner,
  834. position = this.getYAxisLabelPosition();
  835. if ($$.config.axis_rotated) {
  836. return position.isInner ? "-0.5em" : "3em";
  837. } else {
  838. return position.isInner ? "1.2em" : -10 - ($$.config.axis_y_inner ? 0 : this.getMaxTickWidth('y') + 10);
  839. }
  840. };
  841. Axis.prototype.dyForY2AxisLabel = function dyForY2AxisLabel() {
  842. var $$ = this.owner,
  843. position = this.getY2AxisLabelPosition();
  844. if ($$.config.axis_rotated) {
  845. return position.isInner ? "1.2em" : "-2.2em";
  846. } else {
  847. return position.isInner ? "-0.5em" : 15 + ($$.config.axis_y2_inner ? 0 : this.getMaxTickWidth('y2') + 15);
  848. }
  849. };
  850. Axis.prototype.textAnchorForXAxisLabel = function textAnchorForXAxisLabel() {
  851. var $$ = this.owner;
  852. return this.textAnchorForAxisLabel(!$$.config.axis_rotated, this.getXAxisLabelPosition());
  853. };
  854. Axis.prototype.textAnchorForYAxisLabel = function textAnchorForYAxisLabel() {
  855. var $$ = this.owner;
  856. return this.textAnchorForAxisLabel($$.config.axis_rotated, this.getYAxisLabelPosition());
  857. };
  858. Axis.prototype.textAnchorForY2AxisLabel = function textAnchorForY2AxisLabel() {
  859. var $$ = this.owner;
  860. return this.textAnchorForAxisLabel($$.config.axis_rotated, this.getY2AxisLabelPosition());
  861. };
  862. Axis.prototype.getMaxTickWidth = function getMaxTickWidth(id, withoutRecompute) {
  863. var $$ = this.owner,
  864. config = $$.config,
  865. maxWidth = 0,
  866. targetsToShow,
  867. scale,
  868. axis,
  869. dummy,
  870. svg;
  871. if (withoutRecompute && $$.currentMaxTickWidths[id]) {
  872. return $$.currentMaxTickWidths[id];
  873. }
  874. if ($$.svg) {
  875. targetsToShow = $$.filterTargetsToShow($$.data.targets);
  876. if (id === 'y') {
  877. scale = $$.y.copy().domain($$.getYDomain(targetsToShow, 'y'));
  878. axis = this.getYAxis(scale, $$.yOrient, config.axis_y_tick_format, $$.yAxisTickValues, false, true, true);
  879. } else if (id === 'y2') {
  880. scale = $$.y2.copy().domain($$.getYDomain(targetsToShow, 'y2'));
  881. axis = this.getYAxis(scale, $$.y2Orient, config.axis_y2_tick_format, $$.y2AxisTickValues, false, true, true);
  882. } else {
  883. scale = $$.x.copy().domain($$.getXDomain(targetsToShow));
  884. axis = this.getXAxis(scale, $$.xOrient, $$.xAxisTickFormat, $$.xAxisTickValues, false, true, true);
  885. this.updateXAxisTickValues(targetsToShow, axis);
  886. }
  887. dummy = $$.d3.select('body').append('div').classed('c3', true);
  888. svg = dummy.append("svg").style('visibility', 'hidden').style('position', 'fixed').style('top', 0).style('left', 0), svg.append('g').call(axis).each(function () {
  889. $$.d3.select(this).selectAll('text').each(function () {
  890. var box = this.getBoundingClientRect();
  891. if (maxWidth < box.width) {
  892. maxWidth = box.width;
  893. }
  894. });
  895. dummy.remove();
  896. });
  897. }
  898. $$.currentMaxTickWidths[id] = maxWidth <= 0 ? $$.currentMaxTickWidths[id] : maxWidth;
  899. return $$.currentMaxTickWidths[id];
  900. };
  901. Axis.prototype.updateLabels = function updateLabels(withTransition) {
  902. var $$ = this.owner;
  903. var axisXLabel = $$.main.select('.' + CLASS.axisX + ' .' + CLASS.axisXLabel),
  904. axisYLabel = $$.main.select('.' + CLASS.axisY + ' .' + CLASS.axisYLabel),
  905. axisY2Label = $$.main.select('.' + CLASS.axisY2 + ' .' + CLASS.axisY2Label);
  906. (withTransition ? axisXLabel.transition() : axisXLabel).attr("x", this.xForXAxisLabel.bind(this)).attr("dx", this.dxForXAxisLabel.bind(this)).attr("dy", this.dyForXAxisLabel.bind(this)).text(this.textForXAxisLabel.bind(this));
  907. (withTransition ? axisYLabel.transition() : axisYLabel).attr("x", this.xForYAxisLabel.bind(this)).attr("dx", this.dxForYAxisLabel.bind(this)).attr("dy", this.dyForYAxisLabel.bind(this)).text(this.textForYAxisLabel.bind(this));
  908. (withTransition ? axisY2Label.transition() : axisY2Label).attr("x", this.xForY2AxisLabel.bind(this)).attr("dx", this.dxForY2AxisLabel.bind(this)).attr("dy", this.dyForY2AxisLabel.bind(this)).text(this.textForY2AxisLabel.bind(this));
  909. };
  910. Axis.prototype.getPadding = function getPadding(padding, key, defaultValue, domainLength) {
  911. var p = typeof padding === 'number' ? padding : padding[key];
  912. if (!isValue(p)) {
  913. return defaultValue;
  914. }
  915. if (padding.unit === 'ratio') {
  916. return padding[key] * domainLength;
  917. } // assume padding is pixels if unit is not specified
  918. return this.convertPixelsToAxisPadding(p, domainLength);
  919. };
  920. Axis.prototype.convertPixelsToAxisPadding = function convertPixelsToAxisPadding(pixels, domainLength) {
  921. var $$ = this.owner,
  922. length = $$.config.axis_rotated ? $$.width : $$.height;
  923. return domainLength * (pixels / length);
  924. };
  925. Axis.prototype.generateTickValues = function generateTickValues(values, tickCount, forTimeSeries) {
  926. var tickValues = values,
  927. targetCount,
  928. start,
  929. end,
  930. count,
  931. interval,
  932. i,
  933. tickValue;
  934. if (tickCount) {
  935. targetCount = isFunction(tickCount) ? tickCount() : tickCount; // compute ticks according to tickCount
  936. if (targetCount === 1) {
  937. tickValues = [values[0]];
  938. } else if (targetCount === 2) {
  939. tickValues = [values[0], values[values.length - 1]];
  940. } else if (targetCount > 2) {
  941. count = targetCount - 2;
  942. start = values[0];
  943. end = values[values.length - 1];
  944. interval = (end - start) / (count + 1); // re-construct unique values
  945. tickValues = [start];
  946. for (i = 0; i < count; i++) {
  947. tickValue = +start + interval * (i + 1);
  948. tickValues.push(forTimeSeries ? new Date(tickValue) : tickValue);
  949. }
  950. tickValues.push(end);
  951. }
  952. }
  953. if (!forTimeSeries) {
  954. tickValues = tickValues.sort(function (a, b) {
  955. return a - b;
  956. });
  957. }
  958. return tickValues;
  959. };
  960. Axis.prototype.generateTransitions = function generateTransitions(duration) {
  961. var $$ = this.owner,
  962. axes = $$.axes;
  963. return {
  964. axisX: duration ? axes.x.transition().duration(duration) : axes.x,
  965. axisY: duration ? axes.y.transition().duration(duration) : axes.y,
  966. axisY2: duration ? axes.y2.transition().duration(duration) : axes.y2,
  967. axisSubX: duration ? axes.subx.transition().duration(duration) : axes.subx
  968. };
  969. };
  970. Axis.prototype.redraw = function redraw(duration, isHidden) {
  971. var $$ = this.owner,
  972. transition = duration ? $$.d3.transition().duration(duration) : null;
  973. $$.axes.x.style("opacity", isHidden ? 0 : 1).call($$.xAxis, transition);
  974. $$.axes.y.style("opacity", isHidden ? 0 : 1).call($$.yAxis, transition);
  975. $$.axes.y2.style("opacity", isHidden ? 0 : 1).call($$.y2Axis, transition);
  976. $$.axes.subx.style("opacity", isHidden ? 0 : 1).call($$.subXAxis, transition);
  977. };
  978. var c3 = {
  979. version: "0.6.8",
  980. chart: {
  981. fn: Chart.prototype,
  982. internal: {
  983. fn: ChartInternal.prototype,
  984. axis: {
  985. fn: Axis.prototype,
  986. internal: {
  987. fn: AxisInternal.prototype
  988. }
  989. }
  990. }
  991. },
  992. generate: function generate(config) {
  993. return new Chart(config);
  994. }
  995. };
  996. ChartInternal.prototype.beforeInit = function () {// can do something
  997. };
  998. ChartInternal.prototype.afterInit = function () {// can do something
  999. };
  1000. ChartInternal.prototype.init = function () {
  1001. var $$ = this,
  1002. config = $$.config;
  1003. $$.initParams();
  1004. if (config.data_url) {
  1005. $$.convertUrlToData(config.data_url, config.data_mimeType, config.data_headers, config.data_keys, $$.initWithData);
  1006. } else if (config.data_json) {
  1007. $$.initWithData($$.convertJsonToData(config.data_json, config.data_keys));
  1008. } else if (config.data_rows) {
  1009. $$.initWithData($$.convertRowsToData(config.data_rows));
  1010. } else if (config.data_columns) {
  1011. $$.initWithData($$.convertColumnsToData(config.data_columns));
  1012. } else {
  1013. throw Error('url or json or rows or columns is required.');
  1014. }
  1015. };
  1016. ChartInternal.prototype.initParams = function () {
  1017. var $$ = this,
  1018. d3 = $$.d3,
  1019. config = $$.config; // MEMO: clipId needs to be unique because it conflicts when multiple charts exist
  1020. $$.clipId = "c3-" + +new Date() + '-clip';
  1021. $$.clipIdForXAxis = $$.clipId + '-xaxis';
  1022. $$.clipIdForYAxis = $$.clipId + '-yaxis';
  1023. $$.clipIdForGrid = $$.clipId + '-grid';
  1024. $$.clipIdForSubchart = $$.clipId + '-subchart';
  1025. $$.clipPath = $$.getClipPath($$.clipId);
  1026. $$.clipPathForXAxis = $$.getClipPath($$.clipIdForXAxis);
  1027. $$.clipPathForYAxis = $$.getClipPath($$.clipIdForYAxis);
  1028. $$.clipPathForGrid = $$.getClipPath($$.clipIdForGrid);
  1029. $$.clipPathForSubchart = $$.getClipPath($$.clipIdForSubchart);
  1030. $$.dragStart = null;
  1031. $$.dragging = false;
  1032. $$.flowing = false;
  1033. $$.cancelClick = false;
  1034. $$.mouseover = false;
  1035. $$.transiting = false;
  1036. $$.color = $$.generateColor();
  1037. $$.levelColor = $$.generateLevelColor();
  1038. $$.dataTimeParse = (config.data_xLocaltime ? d3.timeParse : d3.utcParse)($$.config.data_xFormat);
  1039. $$.axisTimeFormat = config.axis_x_localtime ? d3.timeFormat : d3.utcFormat;
  1040. $$.defaultAxisTimeFormat = function (date) {
  1041. if (date.getMilliseconds()) {
  1042. return d3.timeFormat(".%L")(date);
  1043. }
  1044. if (date.getSeconds()) {
  1045. return d3.timeFormat(":%S")(date);
  1046. }
  1047. if (date.getMinutes()) {
  1048. return d3.timeFormat("%I:%M")(date);
  1049. }
  1050. if (date.getHours()) {
  1051. return d3.timeFormat("%I %p")(date);
  1052. }
  1053. if (date.getDay() && date.getDate() !== 1) {
  1054. return d3.timeFormat("%-m/%-d")(date);
  1055. }
  1056. if (date.getDate() !== 1) {
  1057. return d3.timeFormat("%-m/%-d")(date);
  1058. }
  1059. if (date.getMonth()) {
  1060. return d3.timeFormat("%-m/%-d")(date);
  1061. }
  1062. return d3.timeFormat("%Y/%-m/%-d")(date);
  1063. };
  1064. $$.hiddenTargetIds = [];
  1065. $$.hiddenLegendIds = [];
  1066. $$.focusedTargetIds = [];
  1067. $$.defocusedTargetIds = [];
  1068. $$.xOrient = config.axis_rotated ? config.axis_x_inner ? "right" : "left" : config.axis_x_inner ? "top" : "bottom";
  1069. $$.yOrient = config.axis_rotated ? config.axis_y_inner ? "top" : "bottom" : config.axis_y_inner ? "right" : "left";
  1070. $$.y2Orient = config.axis_rotated ? config.axis_y2_inner ? "bottom" : "top" : config.axis_y2_inner ? "left" : "right";
  1071. $$.subXOrient = config.axis_rotated ? "left" : "bottom";
  1072. $$.isLegendRight = config.legend_position === 'right';
  1073. $$.isLegendInset = config.legend_position === 'inset';
  1074. $$.isLegendTop = config.legend_inset_anchor === 'top-left' || config.legend_inset_anchor === 'top-right';
  1075. $$.isLegendLeft = config.legend_inset_anchor === 'top-left' || config.legend_inset_anchor === 'bottom-left';
  1076. $$.legendStep = 0;
  1077. $$.legendItemWidth = 0;
  1078. $$.legendItemHeight = 0;
  1079. $$.currentMaxTickWidths = {
  1080. x: 0,
  1081. y: 0,
  1082. y2: 0
  1083. };
  1084. $$.rotated_padding_left = 30;
  1085. $$.rotated_padding_right = config.axis_rotated && !config.axis_x_show ? 0 : 30;
  1086. $$.rotated_padding_top = 5;
  1087. $$.withoutFadeIn = {};
  1088. $$.intervalForObserveInserted = undefined;
  1089. $$.axes.subx = d3.selectAll([]); // needs when excluding subchart.js
  1090. };
  1091. ChartInternal.prototype.initChartElements = function () {
  1092. if (this.initBar) {
  1093. this.initBar();
  1094. }
  1095. if (this.initLine) {
  1096. this.initLine();
  1097. }
  1098. if (this.initArc) {
  1099. this.initArc();
  1100. }
  1101. if (this.initGauge) {
  1102. this.initGauge();
  1103. }
  1104. if (this.initText) {
  1105. this.initText();
  1106. }
  1107. };
  1108. ChartInternal.prototype.initWithData = function (data) {
  1109. var $$ = this,
  1110. d3 = $$.d3,
  1111. config = $$.config;
  1112. var defs,
  1113. main,
  1114. binding = true;
  1115. $$.axis = new Axis($$);
  1116. if (!config.bindto) {
  1117. $$.selectChart = d3.selectAll([]);
  1118. } else if (typeof config.bindto.node === 'function') {
  1119. $$.selectChart = config.bindto;
  1120. } else {
  1121. $$.selectChart = d3.select(config.bindto);
  1122. }
  1123. if ($$.selectChart.empty()) {
  1124. $$.selectChart = d3.select(document.createElement('div')).style('opacity', 0);
  1125. $$.observeInserted($$.selectChart);
  1126. binding = false;
  1127. }
  1128. $$.selectChart.html("").classed("c3", true); // Init data as targets
  1129. $$.data.xs = {};
  1130. $$.data.targets = $$.convertDataToTargets(data);
  1131. if (config.data_filter) {
  1132. $$.data.targets = $$.data.targets.filter(config.data_filter);
  1133. } // Set targets to hide if needed
  1134. if (config.data_hide) {
  1135. $$.addHiddenTargetIds(config.data_hide === true ? $$.mapToIds($$.data.targets) : config.data_hide);
  1136. }
  1137. if (config.legend_hide) {
  1138. $$.addHiddenLegendIds(config.legend_hide === true ? $$.mapToIds($$.data.targets) : config.legend_hide);
  1139. } // Init sizes and scales
  1140. $$.updateSizes();
  1141. $$.updateScales(); // Set domains for each scale
  1142. $$.x.domain(d3.extent($$.getXDomain($$.data.targets)));
  1143. $$.y.domain($$.getYDomain($$.data.targets, 'y'));
  1144. $$.y2.domain($$.getYDomain($$.data.targets, 'y2'));
  1145. $$.subX.domain($$.x.domain());
  1146. $$.subY.domain($$.y.domain());
  1147. $$.subY2.domain($$.y2.domain()); // Save original x domain for zoom update
  1148. $$.orgXDomain = $$.x.domain();
  1149. /*-- Basic Elements --*/
  1150. // Define svgs
  1151. $$.svg = $$.selectChart.append("svg").style("overflow", "hidden").on('mouseenter', function () {
  1152. return config.onmouseover.call($$);
  1153. }).on('mouseleave', function () {
  1154. return config.onmouseout.call($$);
  1155. });
  1156. if ($$.config.svg_classname) {
  1157. $$.svg.attr('class', $$.config.svg_classname);
  1158. } // Define defs
  1159. defs = $$.svg.append("defs");
  1160. $$.clipChart = $$.appendClip(defs, $$.clipId);
  1161. $$.clipXAxis = $$.appendClip(defs, $$.clipIdForXAxis);
  1162. $$.clipYAxis = $$.appendClip(defs, $$.clipIdForYAxis);
  1163. $$.clipGrid = $$.appendClip(defs, $$.clipIdForGrid);
  1164. $$.clipSubchart = $$.appendClip(defs, $$.clipIdForSubchart);
  1165. $$.updateSvgSize(); // Define regions
  1166. main = $$.main = $$.svg.append("g").attr("transform", $$.getTranslate('main'));
  1167. if ($$.initPie) {
  1168. $$.initPie();
  1169. }
  1170. if ($$.initDragZoom) {
  1171. $$.initDragZoom();
  1172. }
  1173. if ($$.initSubchart) {
  1174. $$.initSubchart();
  1175. }
  1176. if ($$.initTooltip) {
  1177. $$.initTooltip();
  1178. }
  1179. if ($$.initLegend) {
  1180. $$.initLegend();
  1181. }
  1182. if ($$.initTitle) {
  1183. $$.initTitle();
  1184. }
  1185. if ($$.initZoom) {
  1186. $$.initZoom();
  1187. } // Update selection based on size and scale
  1188. // TODO: currently this must be called after initLegend because of update of sizes, but it should be done in initSubchart.
  1189. if ($$.initSubchartBrush) {
  1190. $$.initSubchartBrush();
  1191. }
  1192. /*-- Main Region --*/
  1193. // text when empty
  1194. main.append("text").attr("class", CLASS.text + ' ' + CLASS.empty).attr("text-anchor", "middle") // horizontal centering of text at x position in all browsers.
  1195. .attr("dominant-baseline", "middle"); // vertical centering of text at y position in all browsers, except IE.
  1196. // Regions
  1197. $$.initRegion(); // Grids
  1198. $$.initGrid(); // Define g for chart area
  1199. main.append('g').attr("clip-path", $$.clipPath).attr('class', CLASS.chart); // Grid lines
  1200. if (config.grid_lines_front) {
  1201. $$.initGridLines();
  1202. } // Cover whole with rects for events
  1203. $$.initEventRect(); // Define g for chart
  1204. $$.initChartElements(); // Add Axis
  1205. $$.axis.init(); // Set targets
  1206. $$.updateTargets($$.data.targets); // Set default extent if defined
  1207. if (config.axis_x_selection) {
  1208. $$.brush.selectionAsValue($$.getDefaultSelection());
  1209. } // Draw with targets
  1210. if (binding) {
  1211. $$.updateDimension();
  1212. $$.config.oninit.call($$);
  1213. $$.redraw({
  1214. withTransition: false,
  1215. withTransform: true,
  1216. withUpdateXDomain: true,
  1217. withUpdateOrgXDomain: true,
  1218. withTransitionForAxis: false
  1219. });
  1220. } // Bind resize event
  1221. $$.bindResize(); // export element of the chart
  1222. $$.api.element = $$.selectChart.node();
  1223. };
  1224. ChartInternal.prototype.smoothLines = function (el, type) {
  1225. var $$ = this;
  1226. if (type === 'grid') {
  1227. el.each(function () {
  1228. var g = $$.d3.select(this),
  1229. x1 = g.attr('x1'),
  1230. x2 = g.attr('x2'),
  1231. y1 = g.attr('y1'),
  1232. y2 = g.attr('y2');
  1233. g.attr({
  1234. 'x1': Math.ceil(x1),
  1235. 'x2': Math.ceil(x2),
  1236. 'y1': Math.ceil(y1),
  1237. 'y2': Math.ceil(y2)
  1238. });
  1239. });
  1240. }
  1241. };
  1242. ChartInternal.prototype.updateSizes = function () {
  1243. var $$ = this,
  1244. config = $$.config;
  1245. var legendHeight = $$.legend ? $$.getLegendHeight() : 0,
  1246. legendWidth = $$.legend ? $$.getLegendWidth() : 0,
  1247. legendHeightForBottom = $$.isLegendRight || $$.isLegendInset ? 0 : legendHeight,
  1248. hasArc = $$.hasArcType(),
  1249. xAxisHeight = config.axis_rotated || hasArc ? 0 : $$.getHorizontalAxisHeight('x'),
  1250. subchartHeight = config.subchart_show && !hasArc ? config.subchart_size_height + xAxisHeight : 0;
  1251. $$.currentWidth = $$.getCurrentWidth();
  1252. $$.currentHeight = $$.getCurrentHeight(); // for main
  1253. $$.margin = config.axis_rotated ? {
  1254. top: $$.getHorizontalAxisHeight('y2') + $$.getCurrentPaddingTop(),
  1255. right: hasArc ? 0 : $$.getCurrentPaddingRight(),
  1256. bottom: $$.getHorizontalAxisHeight('y') + legendHeightForBottom + $$.getCurrentPaddingBottom(),
  1257. left: subchartHeight + (hasArc ? 0 : $$.getCurrentPaddingLeft())
  1258. } : {
  1259. top: 4 + $$.getCurrentPaddingTop(),
  1260. // for top tick text
  1261. right: hasArc ? 0 : $$.getCurrentPaddingRight(),
  1262. bottom: xAxisHeight + subchartHeight + legendHeightForBottom + $$.getCurrentPaddingBottom(),
  1263. left: hasArc ? 0 : $$.getCurrentPaddingLeft()
  1264. }; // for subchart
  1265. $$.margin2 = config.axis_rotated ? {
  1266. top: $$.margin.top,
  1267. right: NaN,
  1268. bottom: 20 + legendHeightForBottom,
  1269. left: $$.rotated_padding_left
  1270. } : {
  1271. top: $$.currentHeight - subchartHeight - legendHeightForBottom,
  1272. right: NaN,
  1273. bottom: xAxisHeight + legendHeightForBottom,
  1274. left: $$.margin.left
  1275. }; // for legend
  1276. $$.margin3 = {
  1277. top: 0,
  1278. right: NaN,
  1279. bottom: 0,
  1280. left: 0
  1281. };
  1282. if ($$.updateSizeForLegend) {
  1283. $$.updateSizeForLegend(legendHeight, legendWidth);
  1284. }
  1285. $$.width = $$.currentWidth - $$.margin.left - $$.margin.right;
  1286. $$.height = $$.currentHeight - $$.margin.top - $$.margin.bottom;
  1287. if ($$.width < 0) {
  1288. $$.width = 0;
  1289. }
  1290. if ($$.height < 0) {
  1291. $$.height = 0;
  1292. }
  1293. $$.width2 = config.axis_rotated ? $$.margin.left - $$.rotated_padding_left - $$.rotated_padding_right : $$.width;
  1294. $$.height2 = config.axis_rotated ? $$.height : $$.currentHeight - $$.margin2.top - $$.margin2.bottom;
  1295. if ($$.width2 < 0) {
  1296. $$.width2 = 0;
  1297. }
  1298. if ($$.height2 < 0) {
  1299. $$.height2 = 0;
  1300. } // for arc
  1301. $$.arcWidth = $$.width - ($$.isLegendRight ? legendWidth + 10 : 0);
  1302. $$.arcHeight = $$.height - ($$.isLegendRight ? 0 : 10);
  1303. if ($$.hasType('gauge') && !config.gauge_fullCircle) {
  1304. $$.arcHeight += $$.height - $$.getGaugeLabelHeight();
  1305. }
  1306. if ($$.updateRadius) {
  1307. $$.updateRadius();
  1308. }
  1309. if ($$.isLegendRight && hasArc) {
  1310. $$.margin3.left = $$.arcWidth / 2 + $$.radiusExpanded * 1.1;
  1311. }
  1312. };
  1313. ChartInternal.prototype.updateTargets = function (targets) {
  1314. var $$ = this;
  1315. /*-- Main --*/
  1316. //-- Text --//
  1317. $$.updateTargetsForText(targets); //-- Bar --//
  1318. $$.updateTargetsForBar(targets); //-- Line --//
  1319. $$.updateTargetsForLine(targets); //-- Arc --//
  1320. if ($$.hasArcType() && $$.updateTargetsForArc) {
  1321. $$.updateTargetsForArc(targets);
  1322. }
  1323. /*-- Sub --*/
  1324. if ($$.updateTargetsForSubchart) {
  1325. $$.updateTargetsForSubchart(targets);
  1326. } // Fade-in each chart
  1327. $$.showTargets();
  1328. };
  1329. ChartInternal.prototype.showTargets = function () {
  1330. var $$ = this;
  1331. $$.svg.selectAll('.' + CLASS.target).filter(function (d) {
  1332. return $$.isTargetToShow(d.id);
  1333. }).transition().duration($$.config.transition_duration).style("opacity", 1);
  1334. };
  1335. ChartInternal.prototype.redraw = function (options, transitions) {
  1336. var $$ = this,
  1337. main = $$.main,
  1338. d3 = $$.d3,
  1339. config = $$.config;
  1340. var areaIndices = $$.getShapeIndices($$.isAreaType),
  1341. barIndices = $$.getShapeIndices($$.isBarType),
  1342. lineIndices = $$.getShapeIndices($$.isLineType);
  1343. var withY, withSubchart, withTransition, withTransitionForExit, withTransitionForAxis, withTransform, withUpdateXDomain, withUpdateOrgXDomain, withTrimXDomain, withLegend, withEventRect, withDimension, withUpdateXAxis;
  1344. var hideAxis = $$.hasArcType();
  1345. var drawArea, drawBar, drawLine, xForText, yForText;
  1346. var duration, durationForExit, durationForAxis;
  1347. var transitionsToWait, waitForDraw, flow, transition;
  1348. var targetsToShow = $$.filterTargetsToShow($$.data.targets),
  1349. tickValues,
  1350. i,
  1351. intervalForCulling,
  1352. xDomainForZoom;
  1353. var xv = $$.xv.bind($$),
  1354. cx,
  1355. cy;
  1356. options = options || {};
  1357. withY = getOption(options, "withY", true);
  1358. withSubchart = getOption(options, "withSubchart", true);
  1359. withTransition = getOption(options, "withTransition", true);
  1360. withTransform = getOption(options, "withTransform", false);
  1361. withUpdateXDomain = getOption(options, "withUpdateXDomain", false);
  1362. withUpdateOrgXDomain = getOption(options, "withUpdateOrgXDomain", false);
  1363. withTrimXDomain = getOption(options, "withTrimXDomain", true);
  1364. withUpdateXAxis = getOption(options, "withUpdateXAxis", withUpdateXDomain);
  1365. withLegend = getOption(options, "withLegend", false);
  1366. withEventRect = getOption(options, "withEventRect", true);
  1367. withDimension = getOption(options, "withDimension", true);
  1368. withTransitionForExit = getOption(options, "withTransitionForExit", withTransition);
  1369. withTransitionForAxis = getOption(options, "withTransitionForAxis", withTransition);
  1370. duration = withTransition ? config.transition_duration : 0;
  1371. durationForExit = withTransitionForExit ? duration : 0;
  1372. durationForAxis = withTransitionForAxis ? duration : 0;
  1373. transitions = transitions || $$.axis.generateTransitions(durationForAxis); // update legend and transform each g
  1374. if (withLegend && config.legend_show) {
  1375. $$.updateLegend($$.mapToIds($$.data.targets), options, transitions);
  1376. } else if (withDimension) {
  1377. // need to update dimension (e.g. axis.y.tick.values) because y tick values should change
  1378. // no need to update axis in it because they will be updated in redraw()
  1379. $$.updateDimension(true);
  1380. } // MEMO: needed for grids calculation
  1381. if ($$.isCategorized() && targetsToShow.length === 0) {
  1382. $$.x.domain([0, $$.axes.x.selectAll('.tick').size()]);
  1383. }
  1384. if (targetsToShow.length) {
  1385. $$.updateXDomain(targetsToShow, withUpdateXDomain, withUpdateOrgXDomain, withTrimXDomain);
  1386. if (!config.axis_x_tick_values) {
  1387. tickValues = $$.axis.updateXAxisTickValues(targetsToShow);
  1388. }
  1389. } else {
  1390. $$.xAxis.tickValues([]);
  1391. $$.subXAxis.tickValues([]);
  1392. }
  1393. if (config.zoom_rescale && !options.flow) {
  1394. xDomainForZoom = $$.x.orgDomain();
  1395. }
  1396. $$.y.domain($$.getYDomain(targetsToShow, 'y', xDomainForZoom));
  1397. $$.y2.domain($$.getYDomain(targetsToShow, 'y2', xDomainForZoom));
  1398. if (!config.axis_y_tick_values && config.axis_y_tick_count) {
  1399. $$.yAxis.tickValues($$.axis.generateTickValues($$.y.domain(), config.axis_y_tick_count));
  1400. }
  1401. if (!config.axis_y2_tick_values && config.axis_y2_tick_count) {
  1402. $$.y2Axis.tickValues($$.axis.generateTickValues($$.y2.domain(), config.axis_y2_tick_count));
  1403. } // axes
  1404. $$.axis.redraw(durationForAxis, hideAxis); // Update axis label
  1405. $$.axis.updateLabels(withTransition); // show/hide if manual culling needed
  1406. if ((withUpdateXDomain || withUpdateXAxis) && targetsToShow.length) {
  1407. if (config.axis_x_tick_culling && tickValues) {
  1408. for (i = 1; i < tickValues.length; i++) {
  1409. if (tickValues.length / i < config.axis_x_tick_culling_max) {
  1410. intervalForCulling = i;
  1411. break;
  1412. }
  1413. }
  1414. $$.svg.selectAll('.' + CLASS.axisX + ' .tick text').each(function (e) {
  1415. var index = tickValues.indexOf(e);
  1416. if (index >= 0) {
  1417. d3.select(this).style('display', index % intervalForCulling ? 'none' : 'block');
  1418. }
  1419. });
  1420. } else {
  1421. $$.svg.selectAll('.' + CLASS.axisX + ' .tick text').style('display', 'block');
  1422. }
  1423. } // setup drawer - MEMO: these must be called after axis updated
  1424. drawArea = $$.generateDrawArea ? $$.generateDrawArea(areaIndices, false) : undefined;
  1425. drawBar = $$.generateDrawBar ? $$.generateDrawBar(barIndices) : undefined;
  1426. drawLine = $$.generateDrawLine ? $$.generateDrawLine(lineIndices, false) : undefined;
  1427. xForText = $$.generateXYForText(areaIndices, barIndices, lineIndices, true);
  1428. yForText = $$.generateXYForText(areaIndices, barIndices, lineIndices, false); // update circleY based on updated parameters
  1429. $$.updateCircleY(); // generate circle x/y functions depending on updated params
  1430. cx = ($$.config.axis_rotated ? $$.circleY : $$.circleX).bind($$);
  1431. cy = ($$.config.axis_rotated ? $$.circleX : $$.circleY).bind($$); // Update sub domain
  1432. if (withY) {
  1433. $$.subY.domain($$.getYDomain(targetsToShow, 'y'));
  1434. $$.subY2.domain($$.getYDomain(targetsToShow, 'y2'));
  1435. } // xgrid focus
  1436. $$.updateXgridFocus(); // Data empty label positioning and text.
  1437. main.select("text." + CLASS.text + '.' + CLASS.empty).attr("x", $$.width / 2).attr("y", $$.height / 2).text(config.data_empty_label_text).transition().style('opacity', targetsToShow.length ? 0 : 1); // event rect
  1438. if (withEventRect) {
  1439. $$.redrawEventRect();
  1440. } // grid
  1441. $$.updateGrid(duration); // rect for regions
  1442. $$.updateRegion(duration); // bars
  1443. $$.updateBar(durationForExit); // lines, areas and cricles
  1444. $$.updateLine(durationForExit);
  1445. $$.updateArea(durationForExit);
  1446. $$.updateCircle(cx, cy); // text
  1447. if ($$.hasDataLabel()) {
  1448. $$.updateText(xForText, yForText, durationForExit);
  1449. } // title
  1450. if ($$.redrawTitle) {
  1451. $$.redrawTitle();
  1452. } // arc
  1453. if ($$.redrawArc) {
  1454. $$.redrawArc(duration, durationForExit, withTransform);
  1455. } // subchart
  1456. if ($$.redrawSubchart) {
  1457. $$.redrawSubchart(withSubchart, transitions, duration, durationForExit, areaIndices, barIndices, lineIndices);
  1458. } // circles for select
  1459. main.selectAll('.' + CLASS.selectedCircles).filter($$.isBarType.bind($$)).selectAll('circle').remove();
  1460. if (options.flow) {
  1461. flow = $$.generateFlow({
  1462. targets: targetsToShow,
  1463. flow: options.flow,
  1464. duration: options.flow.duration,
  1465. drawBar: drawBar,
  1466. drawLine: drawLine,
  1467. drawArea: drawArea,
  1468. cx: cx,
  1469. cy: cy,
  1470. xv: xv,
  1471. xForText: xForText,
  1472. yForText: yForText
  1473. });
  1474. }
  1475. if ($$.isTabVisible()) {
  1476. // Only use transition if tab visible. See #938.
  1477. if (duration) {
  1478. // transition should be derived from one transition
  1479. transition = d3.transition().duration(duration);
  1480. transitionsToWait = [];
  1481. [$$.redrawBar(drawBar, true, transition), $$.redrawLine(drawLine, true, transition), $$.redrawArea(drawArea, true, transition), $$.redrawCircle(cx, cy, true, transition), $$.redrawText(xForText, yForText, options.flow, true, transition), $$.redrawRegion(true, transition), $$.redrawGrid(true, transition)].forEach(function (transitions) {
  1482. transitions.forEach(function (transition) {
  1483. transitionsToWait.push(transition);
  1484. });
  1485. }); // Wait for end of transitions to call flow and onrendered callback
  1486. waitForDraw = $$.generateWait();
  1487. transitionsToWait.forEach(function (t) {
  1488. waitForDraw.add(t);
  1489. });
  1490. waitForDraw(function () {
  1491. if (flow) {
  1492. flow();
  1493. }
  1494. if (config.onrendered) {
  1495. config.onrendered.call($$);
  1496. }
  1497. });
  1498. } else {
  1499. $$.redrawBar(drawBar);
  1500. $$.redrawLine(drawLine);
  1501. $$.redrawArea(drawArea);
  1502. $$.redrawCircle(cx, cy);
  1503. $$.redrawText(xForText, yForText, options.flow);
  1504. $$.redrawRegion();
  1505. $$.redrawGrid();
  1506. if (flow) {
  1507. flow();
  1508. }
  1509. if (config.onrendered) {
  1510. config.onrendered.call($$);
  1511. }
  1512. }
  1513. } // update fadein condition
  1514. $$.mapToIds($$.data.targets).forEach(function (id) {
  1515. $$.withoutFadeIn[id] = true;
  1516. });
  1517. };
  1518. ChartInternal.prototype.updateAndRedraw = function (options) {
  1519. var $$ = this,
  1520. config = $$.config,
  1521. transitions;
  1522. options = options || {}; // same with redraw
  1523. options.withTransition = getOption(options, "withTransition", true);
  1524. options.withTransform = getOption(options, "withTransform", false);
  1525. options.withLegend = getOption(options, "withLegend", false); // NOT same with redraw
  1526. options.withUpdateXDomain = getOption(options, "withUpdateXDomain", true);
  1527. options.withUpdateOrgXDomain = getOption(options, "withUpdateOrgXDomain", true);
  1528. options.withTransitionForExit = false;
  1529. options.withTransitionForTransform = getOption(options, "withTransitionForTransform", options.withTransition); // MEMO: this needs to be called before updateLegend and it means this ALWAYS needs to be called)
  1530. $$.updateSizes(); // MEMO: called in updateLegend in redraw if withLegend
  1531. if (!(options.withLegend && config.legend_show)) {
  1532. transitions = $$.axis.generateTransitions(options.withTransitionForAxis ? config.transition_duration : 0); // Update scales
  1533. $$.updateScales();
  1534. $$.updateSvgSize(); // Update g positions
  1535. $$.transformAll(options.withTransitionForTransform, transitions);
  1536. } // Draw with new sizes & scales
  1537. $$.redraw(options, transitions);
  1538. };
  1539. ChartInternal.prototype.redrawWithoutRescale = function () {
  1540. this.redraw({
  1541. withY: false,
  1542. withSubchart: false,
  1543. withEventRect: false,
  1544. withTransitionForAxis: false
  1545. });
  1546. };
  1547. ChartInternal.prototype.isTimeSeries = function () {
  1548. return this.config.axis_x_type === 'timeseries';
  1549. };
  1550. ChartInternal.prototype.isCategorized = function () {
  1551. return this.config.axis_x_type.indexOf('categor') >= 0;
  1552. };
  1553. ChartInternal.prototype.isCustomX = function () {
  1554. var $$ = this,
  1555. config = $$.config;
  1556. return !$$.isTimeSeries() && (config.data_x || notEmpty(config.data_xs));
  1557. };
  1558. ChartInternal.prototype.isTimeSeriesY = function () {
  1559. return this.config.axis_y_type === 'timeseries';
  1560. };
  1561. ChartInternal.prototype.getTranslate = function (target) {
  1562. var $$ = this,
  1563. config = $$.config,
  1564. x,
  1565. y;
  1566. if (target === 'main') {
  1567. x = asHalfPixel($$.margin.left);
  1568. y = asHalfPixel($$.margin.top);
  1569. } else if (target === 'context') {
  1570. x = asHalfPixel($$.margin2.left);
  1571. y = asHalfPixel($$.margin2.top);
  1572. } else if (target === 'legend') {
  1573. x = $$.margin3.left;
  1574. y = $$.margin3.top;
  1575. } else if (target === 'x') {
  1576. x = 0;
  1577. y = config.axis_rotated ? 0 : $$.height;
  1578. } else if (target === 'y') {
  1579. x = 0;
  1580. y = config.axis_rotated ? $$.height : 0;
  1581. } else if (target === 'y2') {
  1582. x = config.axis_rotated ? 0 : $$.width;
  1583. y = config.axis_rotated ? 1 : 0;
  1584. } else if (target === 'subx') {
  1585. x = 0;
  1586. y = config.axis_rotated ? 0 : $$.height2;
  1587. } else if (target === 'arc') {
  1588. x = $$.arcWidth / 2;
  1589. y = $$.arcHeight / 2 - ($$.hasType('gauge') ? 6 : 0); // to prevent wrong display of min and max label
  1590. }
  1591. return "translate(" + x + "," + y + ")";
  1592. };
  1593. ChartInternal.prototype.initialOpacity = function (d) {
  1594. return d.value !== null && this.withoutFadeIn[d.id] ? 1 : 0;
  1595. };
  1596. ChartInternal.prototype.initialOpacityForCircle = function (d) {
  1597. return d.value !== null && this.withoutFadeIn[d.id] ? this.opacityForCircle(d) : 0;
  1598. };
  1599. ChartInternal.prototype.opacityForCircle = function (d) {
  1600. var isPointShouldBeShown = isFunction(this.config.point_show) ? this.config.point_show(d) : this.config.point_show;
  1601. var opacity = isPointShouldBeShown ? 1 : 0;
  1602. return isValue(d.value) ? this.isScatterType(d) ? 0.5 : opacity : 0;
  1603. };
  1604. ChartInternal.prototype.opacityForText = function () {
  1605. return this.hasDataLabel() ? 1 : 0;
  1606. };
  1607. ChartInternal.prototype.xx = function (d) {
  1608. return d ? this.x(d.x) : null;
  1609. };
  1610. ChartInternal.prototype.xv = function (d) {
  1611. var $$ = this,
  1612. value = d.value;
  1613. if ($$.isTimeSeries()) {
  1614. value = $$.parseDate(d.value);
  1615. } else if ($$.isCategorized() && typeof d.value === 'string') {
  1616. value = $$.config.axis_x_categories.indexOf(d.value);
  1617. }
  1618. return Math.ceil($$.x(value));
  1619. };
  1620. ChartInternal.prototype.yv = function (d) {
  1621. var $$ = this,
  1622. yScale = d.axis && d.axis === 'y2' ? $$.y2 : $$.y;
  1623. return Math.ceil(yScale(d.value));
  1624. };
  1625. ChartInternal.prototype.subxx = function (d) {
  1626. return d ? this.subX(d.x) : null;
  1627. };
  1628. ChartInternal.prototype.transformMain = function (withTransition, transitions) {
  1629. var $$ = this,
  1630. xAxis,
  1631. yAxis,
  1632. y2Axis;
  1633. if (transitions && transitions.axisX) {
  1634. xAxis = transitions.axisX;
  1635. } else {
  1636. xAxis = $$.main.select('.' + CLASS.axisX);
  1637. if (withTransition) {
  1638. xAxis = xAxis.transition();
  1639. }
  1640. }
  1641. if (transitions && transitions.axisY) {
  1642. yAxis = transitions.axisY;
  1643. } else {
  1644. yAxis = $$.main.select('.' + CLASS.axisY);
  1645. if (withTransition) {
  1646. yAxis = yAxis.transition();
  1647. }
  1648. }
  1649. if (transitions && transitions.axisY2) {
  1650. y2Axis = transitions.axisY2;
  1651. } else {
  1652. y2Axis = $$.main.select('.' + CLASS.axisY2);
  1653. if (withTransition) {
  1654. y2Axis = y2Axis.transition();
  1655. }
  1656. }
  1657. (withTransition ? $$.main.transition() : $$.main).attr("transform", $$.getTranslate('main'));
  1658. xAxis.attr("transform", $$.getTranslate('x'));
  1659. yAxis.attr("transform", $$.getTranslate('y'));
  1660. y2Axis.attr("transform", $$.getTranslate('y2'));
  1661. $$.main.select('.' + CLASS.chartArcs).attr("transform", $$.getTranslate('arc'));
  1662. };
  1663. ChartInternal.prototype.transformAll = function (withTransition, transitions) {
  1664. var $$ = this;
  1665. $$.transformMain(withTransition, transitions);
  1666. if ($$.config.subchart_show) {
  1667. $$.transformContext(withTransition, transitions);
  1668. }
  1669. if ($$.legend) {
  1670. $$.transformLegend(withTransition);
  1671. }
  1672. };
  1673. ChartInternal.prototype.updateSvgSize = function () {
  1674. var $$ = this,
  1675. brush = $$.svg.select(".c3-brush .overlay");
  1676. $$.svg.attr('width', $$.currentWidth).attr('height', $$.currentHeight);
  1677. $$.svg.selectAll(['#' + $$.clipId, '#' + $$.clipIdForGrid]).select('rect').attr('width', $$.width).attr('height', $$.height);
  1678. $$.svg.select('#' + $$.clipIdForXAxis).select('rect').attr('x', $$.getXAxisClipX.bind($$)).attr('y', $$.getXAxisClipY.bind($$)).attr('width', $$.getXAxisClipWidth.bind($$)).attr('height', $$.getXAxisClipHeight.bind($$));
  1679. $$.svg.select('#' + $$.clipIdForYAxis).select('rect').attr('x', $$.getYAxisClipX.bind($$)).attr('y', $$.getYAxisClipY.bind($$)).attr('width', $$.getYAxisClipWidth.bind($$)).attr('height', $$.getYAxisClipHeight.bind($$));
  1680. $$.svg.select('#' + $$.clipIdForSubchart).select('rect').attr('width', $$.width).attr('height', brush.size() ? brush.attr('height') : 0); // MEMO: parent div's height will be bigger than svg when <!DOCTYPE html>
  1681. $$.selectChart.style('max-height', $$.currentHeight + "px");
  1682. };
  1683. ChartInternal.prototype.updateDimension = function (withoutAxis) {
  1684. var $$ = this;
  1685. if (!withoutAxis) {
  1686. if ($$.config.axis_rotated) {
  1687. $$.axes.x.call($$.xAxis);
  1688. $$.axes.subx.call($$.subXAxis);
  1689. } else {
  1690. $$.axes.y.call($$.yAxis);
  1691. $$.axes.y2.call($$.y2Axis);
  1692. }
  1693. }
  1694. $$.updateSizes();
  1695. $$.updateScales();
  1696. $$.updateSvgSize();
  1697. $$.transformAll(false);
  1698. };
  1699. ChartInternal.prototype.observeInserted = function (selection) {
  1700. var $$ = this,
  1701. observer;
  1702. if (typeof MutationObserver === 'undefined') {
  1703. window.console.error("MutationObserver not defined.");
  1704. return;
  1705. }
  1706. observer = new MutationObserver(function (mutations) {
  1707. mutations.forEach(function (mutation) {
  1708. if (mutation.type === 'childList' && mutation.previousSibling) {
  1709. observer.disconnect(); // need to wait for completion of load because size calculation requires the actual sizes determined after that completion
  1710. $$.intervalForObserveInserted = window.setInterval(function () {
  1711. // parentNode will NOT be null when completed
  1712. if (selection.node().parentNode) {
  1713. window.clearInterval($$.intervalForObserveInserted);
  1714. $$.updateDimension();
  1715. if ($$.brush) {
  1716. $$.brush.update();
  1717. }
  1718. $$.config.oninit.call($$);
  1719. $$.redraw({
  1720. withTransform: true,
  1721. withUpdateXDomain: true,
  1722. withUpdateOrgXDomain: true,
  1723. withTransition: false,
  1724. withTransitionForTransform: false,
  1725. withLegend: true
  1726. });
  1727. selection.transition().style('opacity', 1);
  1728. }
  1729. }, 10);
  1730. }
  1731. });
  1732. });
  1733. observer.observe(selection.node(), {
  1734. attributes: true,
  1735. childList: true,
  1736. characterData: true
  1737. });
  1738. };
  1739. ChartInternal.prototype.bindResize = function () {
  1740. var $$ = this,
  1741. config = $$.config;
  1742. $$.resizeFunction = $$.generateResize(); // need to call .remove
  1743. $$.resizeFunction.add(function () {
  1744. config.onresize.call($$);
  1745. });
  1746. if (config.resize_auto) {
  1747. $$.resizeFunction.add(function () {
  1748. if ($$.resizeTimeout !== undefined) {
  1749. window.clearTimeout($$.resizeTimeout);
  1750. }
  1751. $$.resizeTimeout = window.setTimeout(function () {
  1752. delete $$.resizeTimeout;
  1753. $$.updateAndRedraw({
  1754. withUpdateXDomain: false,
  1755. withUpdateOrgXDomain: false,
  1756. withTransition: false,
  1757. withTransitionForTransform: false,
  1758. withLegend: true
  1759. });
  1760. if ($$.brush) {
  1761. $$.brush.update();
  1762. }
  1763. }, 100);
  1764. });
  1765. }
  1766. $$.resizeFunction.add(function () {
  1767. config.onresized.call($$);
  1768. });
  1769. $$.resizeIfElementDisplayed = function () {
  1770. // if element not displayed skip it
  1771. if ($$.api == null || !$$.api.element.offsetParent) {
  1772. return;
  1773. }
  1774. $$.resizeFunction();
  1775. };
  1776. if (window.attachEvent) {
  1777. window.attachEvent('onresize', $$.resizeIfElementDisplayed);
  1778. } else if (window.addEventListener) {
  1779. window.addEventListener('resize', $$.resizeIfElementDisplayed, false);
  1780. } else {
  1781. // fallback to this, if this is a very old browser
  1782. var wrapper = window.onresize;
  1783. if (!wrapper) {
  1784. // create a wrapper that will call all charts
  1785. wrapper = $$.generateResize();
  1786. } else if (!wrapper.add || !wrapper.remove) {
  1787. // there is already a handler registered, make sure we call it too
  1788. wrapper = $$.generateResize();
  1789. wrapper.add(window.onresize);
  1790. } // add this graph to the wrapper, we will be removed if the user calls destroy
  1791. wrapper.add($$.resizeFunction);
  1792. window.onresize = function () {
  1793. // if element not displayed skip it
  1794. if (!$$.api.element.offsetParent) {
  1795. return;
  1796. }
  1797. wrapper();
  1798. };
  1799. }
  1800. };
  1801. ChartInternal.prototype.generateResize = function () {
  1802. var resizeFunctions = [];
  1803. function callResizeFunctions() {
  1804. resizeFunctions.forEach(function (f) {
  1805. f();
  1806. });
  1807. }
  1808. callResizeFunctions.add = function (f) {
  1809. resizeFunctions.push(f);
  1810. };
  1811. callResizeFunctions.remove = function (f) {
  1812. for (var i = 0; i < resizeFunctions.length; i++) {
  1813. if (resizeFunctions[i] === f) {
  1814. resizeFunctions.splice(i, 1);
  1815. break;
  1816. }
  1817. }
  1818. };
  1819. return callResizeFunctions;
  1820. };
  1821. ChartInternal.prototype.endall = function (transition, callback) {
  1822. var n = 0;
  1823. transition.each(function () {
  1824. ++n;
  1825. }).on("end", function () {
  1826. if (! --n) {
  1827. callback.apply(this, arguments);
  1828. }
  1829. });
  1830. };
  1831. ChartInternal.prototype.generateWait = function () {
  1832. var transitionsToWait = [],
  1833. f = function f(callback) {
  1834. var timer = setInterval(function () {
  1835. var done = 0;
  1836. transitionsToWait.forEach(function (t) {
  1837. if (t.empty()) {
  1838. done += 1;
  1839. return;
  1840. }
  1841. try {
  1842. t.transition();
  1843. } catch (e) {
  1844. done += 1;
  1845. }
  1846. });
  1847. if (done === transitionsToWait.length) {
  1848. clearInterval(timer);
  1849. if (callback) {
  1850. callback();
  1851. }
  1852. }
  1853. }, 50);
  1854. };
  1855. f.add = function (transition) {
  1856. transitionsToWait.push(transition);
  1857. };
  1858. return f;
  1859. };
  1860. ChartInternal.prototype.parseDate = function (date) {
  1861. var $$ = this,
  1862. parsedDate;
  1863. if (date instanceof Date) {
  1864. parsedDate = date;
  1865. } else if (typeof date === 'string') {
  1866. parsedDate = $$.dataTimeParse(date);
  1867. } else if (_typeof(date) === 'object') {
  1868. parsedDate = new Date(+date);
  1869. } else if (typeof date === 'number' && !isNaN(date)) {
  1870. parsedDate = new Date(+date);
  1871. }
  1872. if (!parsedDate || isNaN(+parsedDate)) {
  1873. window.console.error("Failed to parse x '" + date + "' to Date object");
  1874. }
  1875. return parsedDate;
  1876. };
  1877. ChartInternal.prototype.isTabVisible = function () {
  1878. var hidden;
  1879. if (typeof document.hidden !== "undefined") {
  1880. // Opera 12.10 and Firefox 18 and later support
  1881. hidden = "hidden";
  1882. } else if (typeof document.mozHidden !== "undefined") {
  1883. hidden = "mozHidden";
  1884. } else if (typeof document.msHidden !== "undefined") {
  1885. hidden = "msHidden";
  1886. } else if (typeof document.webkitHidden !== "undefined") {
  1887. hidden = "webkitHidden";
  1888. }
  1889. return document[hidden] ? false : true;
  1890. };
  1891. ChartInternal.prototype.getPathBox = getPathBox;
  1892. ChartInternal.prototype.CLASS = CLASS;
  1893. /* jshint ignore:start */
  1894. // SVGPathSeg API polyfill
  1895. // https://github.com/progers/pathseg
  1896. //
  1897. // This is a drop-in replacement for the SVGPathSeg and SVGPathSegList APIs that were removed from
  1898. // SVG2 (https://lists.w3.org/Archives/Public/www-svg/2015Jun/0044.html), including the latest spec
  1899. // changes which were implemented in Firefox 43 and Chrome 46.
  1900. (function () {
  1901. if (!("SVGPathSeg" in window)) {
  1902. // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathSeg
  1903. window.SVGPathSeg = function (type, typeAsLetter, owningPathSegList) {
  1904. this.pathSegType = type;
  1905. this.pathSegTypeAsLetter = typeAsLetter;
  1906. this._owningPathSegList = owningPathSegList;
  1907. };
  1908. window.SVGPathSeg.prototype.classname = "SVGPathSeg";
  1909. window.SVGPathSeg.PATHSEG_UNKNOWN = 0;
  1910. window.SVGPathSeg.PATHSEG_CLOSEPATH = 1;
  1911. window.SVGPathSeg.PATHSEG_MOVETO_ABS = 2;
  1912. window.SVGPathSeg.PATHSEG_MOVETO_REL = 3;
  1913. window.SVGPathSeg.PATHSEG_LINETO_ABS = 4;
  1914. window.SVGPathSeg.PATHSEG_LINETO_REL = 5;
  1915. window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS = 6;
  1916. window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL = 7;
  1917. window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS = 8;
  1918. window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL = 9;
  1919. window.SVGPathSeg.PATHSEG_ARC_ABS = 10;
  1920. window.SVGPathSeg.PATHSEG_ARC_REL = 11;
  1921. window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS = 12;
  1922. window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL = 13;
  1923. window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS = 14;
  1924. window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL = 15;
  1925. window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS = 16;
  1926. window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL = 17;
  1927. window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS = 18;
  1928. window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL = 19; // Notify owning PathSegList on any changes so they can be synchronized back to the path element.
  1929. window.SVGPathSeg.prototype._segmentChanged = function () {
  1930. if (this._owningPathSegList) this._owningPathSegList.segmentChanged(this);
  1931. };
  1932. window.SVGPathSegClosePath = function (owningPathSegList) {
  1933. window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CLOSEPATH, "z", owningPathSegList);
  1934. };
  1935. window.SVGPathSegClosePath.prototype = Object.create(window.SVGPathSeg.prototype);
  1936. window.SVGPathSegClosePath.prototype.toString = function () {
  1937. return "[object SVGPathSegClosePath]";
  1938. };
  1939. window.SVGPathSegClosePath.prototype._asPathString = function () {
  1940. return this.pathSegTypeAsLetter;
  1941. };
  1942. window.SVGPathSegClosePath.prototype.clone = function () {
  1943. return new window.SVGPathSegClosePath(undefined);
  1944. };
  1945. window.SVGPathSegMovetoAbs = function (owningPathSegList, x, y) {
  1946. window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_MOVETO_ABS, "M", owningPathSegList);
  1947. this._x = x;
  1948. this._y = y;
  1949. };
  1950. window.SVGPathSegMovetoAbs.prototype = Object.create(window.SVGPathSeg.prototype);
  1951. window.SVGPathSegMovetoAbs.prototype.toString = function () {
  1952. return "[object SVGPathSegMovetoAbs]";
  1953. };
  1954. window.SVGPathSegMovetoAbs.prototype._asPathString = function () {
  1955. return this.pathSegTypeAsLetter + " " + this._x + " " + this._y;
  1956. };
  1957. window.SVGPathSegMovetoAbs.prototype.clone = function () {
  1958. return new window.SVGPathSegMovetoAbs(undefined, this._x, this._y);
  1959. };
  1960. Object.defineProperty(window.SVGPathSegMovetoAbs.prototype, "x", {
  1961. get: function get() {
  1962. return this._x;
  1963. },
  1964. set: function set(x) {
  1965. this._x = x;
  1966. this._segmentChanged();
  1967. },
  1968. enumerable: true
  1969. });
  1970. Object.defineProperty(window.SVGPathSegMovetoAbs.prototype, "y", {
  1971. get: function get() {
  1972. return this._y;
  1973. },
  1974. set: function set(y) {
  1975. this._y = y;
  1976. this._segmentChanged();
  1977. },
  1978. enumerable: true
  1979. });
  1980. window.SVGPathSegMovetoRel = function (owningPathSegList, x, y) {
  1981. window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_MOVETO_REL, "m", owningPathSegList);
  1982. this._x = x;
  1983. this._y = y;
  1984. };
  1985. window.SVGPathSegMovetoRel.prototype = Object.create(window.SVGPathSeg.prototype);
  1986. window.SVGPathSegMovetoRel.prototype.toString = function () {
  1987. return "[object SVGPathSegMovetoRel]";
  1988. };
  1989. window.SVGPathSegMovetoRel.prototype._asPathString = function () {
  1990. return this.pathSegTypeAsLetter + " " + this._x + " " + this._y;
  1991. };
  1992. window.SVGPathSegMovetoRel.prototype.clone = function () {
  1993. return new window.SVGPathSegMovetoRel(undefined, this._x, this._y);
  1994. };
  1995. Object.defineProperty(window.SVGPathSegMovetoRel.prototype, "x", {
  1996. get: function get() {
  1997. return this._x;
  1998. },
  1999. set: function set(x) {
  2000. this._x = x;
  2001. this._segmentChanged();
  2002. },
  2003. enumerable: true
  2004. });
  2005. Object.defineProperty(window.SVGPathSegMovetoRel.prototype, "y", {
  2006. get: function get() {
  2007. return this._y;
  2008. },
  2009. set: function set(y) {
  2010. this._y = y;
  2011. this._segmentChanged();
  2012. },
  2013. enumerable: true
  2014. });
  2015. window.SVGPathSegLinetoAbs = function (owningPathSegList, x, y) {
  2016. window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_ABS, "L", owningPathSegList);
  2017. this._x = x;
  2018. this._y = y;
  2019. };
  2020. window.SVGPathSegLinetoAbs.prototype = Object.create(window.SVGPathSeg.prototype);
  2021. window.SVGPathSegLinetoAbs.prototype.toString = function () {
  2022. return "[object SVGPathSegLinetoAbs]";
  2023. };
  2024. window.SVGPathSegLinetoAbs.prototype._asPathString = function () {
  2025. return this.pathSegTypeAsLetter + " " + this._x + " " + this._y;
  2026. };
  2027. window.SVGPathSegLinetoAbs.prototype.clone = function () {
  2028. return new window.SVGPathSegLinetoAbs(undefined, this._x, this._y);
  2029. };
  2030. Object.defineProperty(window.SVGPathSegLinetoAbs.prototype, "x", {
  2031. get: function get() {
  2032. return this._x;
  2033. },
  2034. set: function set(x) {
  2035. this._x = x;
  2036. this._segmentChanged();
  2037. },
  2038. enumerable: true
  2039. });
  2040. Object.defineProperty(window.SVGPathSegLinetoAbs.prototype, "y", {
  2041. get: function get() {
  2042. return this._y;
  2043. },
  2044. set: function set(y) {
  2045. this._y = y;
  2046. this._segmentChanged();
  2047. },
  2048. enumerable: true
  2049. });
  2050. window.SVGPathSegLinetoRel = function (owningPathSegList, x, y) {
  2051. window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_REL, "l", owningPathSegList);
  2052. this._x = x;
  2053. this._y = y;
  2054. };
  2055. window.SVGPathSegLinetoRel.prototype = Object.create(window.SVGPathSeg.prototype);
  2056. window.SVGPathSegLinetoRel.prototype.toString = function () {
  2057. return "[object SVGPathSegLinetoRel]";
  2058. };
  2059. window.SVGPathSegLinetoRel.prototype._asPathString = function () {
  2060. return this.pathSegTypeAsLetter + " " + this._x + " " + this._y;
  2061. };
  2062. window.SVGPathSegLinetoRel.prototype.clone = function () {
  2063. return new window.SVGPathSegLinetoRel(undefined, this._x, this._y);
  2064. };
  2065. Object.defineProperty(window.SVGPathSegLinetoRel.prototype, "x", {
  2066. get: function get() {
  2067. return this._x;
  2068. },
  2069. set: function set(x) {
  2070. this._x = x;
  2071. this._segmentChanged();
  2072. },
  2073. enumerable: true
  2074. });
  2075. Object.defineProperty(window.SVGPathSegLinetoRel.prototype, "y", {
  2076. get: function get() {
  2077. return this._y;
  2078. },
  2079. set: function set(y) {
  2080. this._y = y;
  2081. this._segmentChanged();
  2082. },
  2083. enumerable: true
  2084. });
  2085. window.SVGPathSegCurvetoCubicAbs = function (owningPathSegList, x, y, x1, y1, x2, y2) {
  2086. window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS, "C", owningPathSegList);
  2087. this._x = x;
  2088. this._y = y;
  2089. this._x1 = x1;
  2090. this._y1 = y1;
  2091. this._x2 = x2;
  2092. this._y2 = y2;
  2093. };
  2094. window.SVGPathSegCurvetoCubicAbs.prototype = Object.create(window.SVGPathSeg.prototype);
  2095. window.SVGPathSegCurvetoCubicAbs.prototype.toString = function () {
  2096. return "[object SVGPathSegCurvetoCubicAbs]";
  2097. };
  2098. window.SVGPathSegCurvetoCubicAbs.prototype._asPathString = function () {
  2099. return this.pathSegTypeAsLetter + " " + this._x1 + " " + this._y1 + " " + this._x2 + " " + this._y2 + " " + this._x + " " + this._y;
  2100. };
  2101. window.SVGPathSegCurvetoCubicAbs.prototype.clone = function () {
  2102. return new window.SVGPathSegCurvetoCubicAbs(undefined, this._x, this._y, this._x1, this._y1, this._x2, this._y2);
  2103. };
  2104. Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, "x", {
  2105. get: function get() {
  2106. return this._x;
  2107. },
  2108. set: function set(x) {
  2109. this._x = x;
  2110. this._segmentChanged();
  2111. },
  2112. enumerable: true
  2113. });
  2114. Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, "y", {
  2115. get: function get() {
  2116. return this._y;
  2117. },
  2118. set: function set(y) {
  2119. this._y = y;
  2120. this._segmentChanged();
  2121. },
  2122. enumerable: true
  2123. });
  2124. Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, "x1", {
  2125. get: function get() {
  2126. return this._x1;
  2127. },
  2128. set: function set(x1) {
  2129. this._x1 = x1;
  2130. this._segmentChanged();
  2131. },
  2132. enumerable: true
  2133. });
  2134. Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, "y1", {
  2135. get: function get() {
  2136. return this._y1;
  2137. },
  2138. set: function set(y1) {
  2139. this._y1 = y1;
  2140. this._segmentChanged();
  2141. },
  2142. enumerable: true
  2143. });
  2144. Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, "x2", {
  2145. get: function get() {
  2146. return this._x2;
  2147. },
  2148. set: function set(x2) {
  2149. this._x2 = x2;
  2150. this._segmentChanged();
  2151. },
  2152. enumerable: true
  2153. });
  2154. Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, "y2", {
  2155. get: function get() {
  2156. return this._y2;
  2157. },
  2158. set: function set(y2) {
  2159. this._y2 = y2;
  2160. this._segmentChanged();
  2161. },
  2162. enumerable: true
  2163. });
  2164. window.SVGPathSegCurvetoCubicRel = function (owningPathSegList, x, y, x1, y1, x2, y2) {
  2165. window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL, "c", owningPathSegList);
  2166. this._x = x;
  2167. this._y = y;
  2168. this._x1 = x1;
  2169. this._y1 = y1;
  2170. this._x2 = x2;
  2171. this._y2 = y2;
  2172. };
  2173. window.SVGPathSegCurvetoCubicRel.prototype = Object.create(window.SVGPathSeg.prototype);
  2174. window.SVGPathSegCurvetoCubicRel.prototype.toString = function () {
  2175. return "[object SVGPathSegCurvetoCubicRel]";
  2176. };
  2177. window.SVGPathSegCurvetoCubicRel.prototype._asPathString = function () {
  2178. return this.pathSegTypeAsLetter + " " + this._x1 + " " + this._y1 + " " + this._x2 + " " + this._y2 + " " + this._x + " " + this._y;
  2179. };
  2180. window.SVGPathSegCurvetoCubicRel.prototype.clone = function () {
  2181. return new window.SVGPathSegCurvetoCubicRel(undefined, this._x, this._y, this._x1, this._y1, this._x2, this._y2);
  2182. };
  2183. Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, "x", {
  2184. get: function get() {
  2185. return this._x;
  2186. },
  2187. set: function set(x) {
  2188. this._x = x;
  2189. this._segmentChanged();
  2190. },
  2191. enumerable: true
  2192. });
  2193. Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, "y", {
  2194. get: function get() {
  2195. return this._y;
  2196. },
  2197. set: function set(y) {
  2198. this._y = y;
  2199. this._segmentChanged();
  2200. },
  2201. enumerable: true
  2202. });
  2203. Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, "x1", {
  2204. get: function get() {
  2205. return this._x1;
  2206. },
  2207. set: function set(x1) {
  2208. this._x1 = x1;
  2209. this._segmentChanged();
  2210. },
  2211. enumerable: true
  2212. });
  2213. Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, "y1", {
  2214. get: function get() {
  2215. return this._y1;
  2216. },
  2217. set: function set(y1) {
  2218. this._y1 = y1;
  2219. this._segmentChanged();
  2220. },
  2221. enumerable: true
  2222. });
  2223. Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, "x2", {
  2224. get: function get() {
  2225. return this._x2;
  2226. },
  2227. set: function set(x2) {
  2228. this._x2 = x2;
  2229. this._segmentChanged();
  2230. },
  2231. enumerable: true
  2232. });
  2233. Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, "y2", {
  2234. get: function get() {
  2235. return this._y2;
  2236. },
  2237. set: function set(y2) {
  2238. this._y2 = y2;
  2239. this._segmentChanged();
  2240. },
  2241. enumerable: true
  2242. });
  2243. window.SVGPathSegCurvetoQuadraticAbs = function (owningPathSegList, x, y, x1, y1) {
  2244. window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS, "Q", owningPathSegList);
  2245. this._x = x;
  2246. this._y = y;
  2247. this._x1 = x1;
  2248. this._y1 = y1;
  2249. };
  2250. window.SVGPathSegCurvetoQuadraticAbs.prototype = Object.create(window.SVGPathSeg.prototype);
  2251. window.SVGPathSegCurvetoQuadraticAbs.prototype.toString = function () {
  2252. return "[object SVGPathSegCurvetoQuadraticAbs]";
  2253. };
  2254. window.SVGPathSegCurvetoQuadraticAbs.prototype._asPathString = function () {
  2255. return this.pathSegTypeAsLetter + " " + this._x1 + " " + this._y1 + " " + this._x + " " + this._y;
  2256. };
  2257. window.SVGPathSegCurvetoQuadraticAbs.prototype.clone = function () {
  2258. return new window.SVGPathSegCurvetoQuadraticAbs(undefined, this._x, this._y, this._x1, this._y1);
  2259. };
  2260. Object.defineProperty(window.SVGPathSegCurvetoQuadraticAbs.prototype, "x", {
  2261. get: function get() {
  2262. return this._x;
  2263. },
  2264. set: function set(x) {
  2265. this._x = x;
  2266. this._segmentChanged();
  2267. },
  2268. enumerable: true
  2269. });
  2270. Object.defineProperty(window.SVGPathSegCurvetoQuadraticAbs.prototype, "y", {
  2271. get: function get() {
  2272. return this._y;
  2273. },
  2274. set: function set(y) {
  2275. this._y = y;
  2276. this._segmentChanged();
  2277. },
  2278. enumerable: true
  2279. });
  2280. Object.defineProperty(window.SVGPathSegCurvetoQuadraticAbs.prototype, "x1", {
  2281. get: function get() {
  2282. return this._x1;
  2283. },
  2284. set: function set(x1) {
  2285. this._x1 = x1;
  2286. this._segmentChanged();
  2287. },
  2288. enumerable: true
  2289. });
  2290. Object.defineProperty(window.SVGPathSegCurvetoQuadraticAbs.prototype, "y1", {
  2291. get: function get() {
  2292. return this._y1;
  2293. },
  2294. set: function set(y1) {
  2295. this._y1 = y1;
  2296. this._segmentChanged();
  2297. },
  2298. enumerable: true
  2299. });
  2300. window.SVGPathSegCurvetoQuadraticRel = function (owningPathSegList, x, y, x1, y1) {
  2301. window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL, "q", owningPathSegList);
  2302. this._x = x;
  2303. this._y = y;
  2304. this._x1 = x1;
  2305. this._y1 = y1;
  2306. };
  2307. window.SVGPathSegCurvetoQuadraticRel.prototype = Object.create(window.SVGPathSeg.prototype);
  2308. window.SVGPathSegCurvetoQuadraticRel.prototype.toString = function () {
  2309. return "[object SVGPathSegCurvetoQuadraticRel]";
  2310. };
  2311. window.SVGPathSegCurvetoQuadraticRel.prototype._asPathString = function () {
  2312. return this.pathSegTypeAsLetter + " " + this._x1 + " " + this._y1 + " " + this._x + " " + this._y;
  2313. };
  2314. window.SVGPathSegCurvetoQuadraticRel.prototype.clone = function () {
  2315. return new window.SVGPathSegCurvetoQuadraticRel(undefined, this._x, this._y, this._x1, this._y1);
  2316. };
  2317. Object.defineProperty(window.SVGPathSegCurvetoQuadraticRel.prototype, "x", {
  2318. get: function get() {
  2319. return this._x;
  2320. },
  2321. set: function set(x) {
  2322. this._x = x;
  2323. this._segmentChanged();
  2324. },
  2325. enumerable: true
  2326. });
  2327. Object.defineProperty(window.SVGPathSegCurvetoQuadraticRel.prototype, "y", {
  2328. get: function get() {
  2329. return this._y;
  2330. },
  2331. set: function set(y) {
  2332. this._y = y;
  2333. this._segmentChanged();
  2334. },
  2335. enumerable: true
  2336. });
  2337. Object.defineProperty(window.SVGPathSegCurvetoQuadraticRel.prototype, "x1", {
  2338. get: function get() {
  2339. return this._x1;
  2340. },
  2341. set: function set(x1) {
  2342. this._x1 = x1;
  2343. this._segmentChanged();
  2344. },
  2345. enumerable: true
  2346. });
  2347. Object.defineProperty(window.SVGPathSegCurvetoQuadraticRel.prototype, "y1", {
  2348. get: function get() {
  2349. return this._y1;
  2350. },
  2351. set: function set(y1) {
  2352. this._y1 = y1;
  2353. this._segmentChanged();
  2354. },
  2355. enumerable: true
  2356. });
  2357. window.SVGPathSegArcAbs = function (owningPathSegList, x, y, r1, r2, angle, largeArcFlag, sweepFlag) {
  2358. window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_ARC_ABS, "A", owningPathSegList);
  2359. this._x = x;
  2360. this._y = y;
  2361. this._r1 = r1;
  2362. this._r2 = r2;
  2363. this._angle = angle;
  2364. this._largeArcFlag = largeArcFlag;
  2365. this._sweepFlag = sweepFlag;
  2366. };
  2367. window.SVGPathSegArcAbs.prototype = Object.create(window.SVGPathSeg.prototype);
  2368. window.SVGPathSegArcAbs.prototype.toString = function () {
  2369. return "[object SVGPathSegArcAbs]";
  2370. };
  2371. window.SVGPathSegArcAbs.prototype._asPathString = function () {
  2372. return this.pathSegTypeAsLetter + " " + this._r1 + " " + this._r2 + " " + this._angle + " " + (this._largeArcFlag ? "1" : "0") + " " + (this._sweepFlag ? "1" : "0") + " " + this._x + " " + this._y;
  2373. };
  2374. window.SVGPathSegArcAbs.prototype.clone = function () {
  2375. return new window.SVGPathSegArcAbs(undefined, this._x, this._y, this._r1, this._r2, this._angle, this._largeArcFlag, this._sweepFlag);
  2376. };
  2377. Object.defineProperty(window.SVGPathSegArcAbs.prototype, "x", {
  2378. get: function get() {
  2379. return this._x;
  2380. },
  2381. set: function set(x) {
  2382. this._x = x;
  2383. this._segmentChanged();
  2384. },
  2385. enumerable: true
  2386. });
  2387. Object.defineProperty(window.SVGPathSegArcAbs.prototype, "y", {
  2388. get: function get() {
  2389. return this._y;
  2390. },
  2391. set: function set(y) {
  2392. this._y = y;
  2393. this._segmentChanged();
  2394. },
  2395. enumerable: true
  2396. });
  2397. Object.defineProperty(window.SVGPathSegArcAbs.prototype, "r1", {
  2398. get: function get() {
  2399. return this._r1;
  2400. },
  2401. set: function set(r1) {
  2402. this._r1 = r1;
  2403. this._segmentChanged();
  2404. },
  2405. enumerable: true
  2406. });
  2407. Object.defineProperty(window.SVGPathSegArcAbs.prototype, "r2", {
  2408. get: function get() {
  2409. return this._r2;
  2410. },
  2411. set: function set(r2) {
  2412. this._r2 = r2;
  2413. this._segmentChanged();
  2414. },
  2415. enumerable: true
  2416. });
  2417. Object.defineProperty(window.SVGPathSegArcAbs.prototype, "angle", {
  2418. get: function get() {
  2419. return this._angle;
  2420. },
  2421. set: function set(angle) {
  2422. this._angle = angle;
  2423. this._segmentChanged();
  2424. },
  2425. enumerable: true
  2426. });
  2427. Object.defineProperty(window.SVGPathSegArcAbs.prototype, "largeArcFlag", {
  2428. get: function get() {
  2429. return this._largeArcFlag;
  2430. },
  2431. set: function set(largeArcFlag) {
  2432. this._largeArcFlag = largeArcFlag;
  2433. this._segmentChanged();
  2434. },
  2435. enumerable: true
  2436. });
  2437. Object.defineProperty(window.SVGPathSegArcAbs.prototype, "sweepFlag", {
  2438. get: function get() {
  2439. return this._sweepFlag;
  2440. },
  2441. set: function set(sweepFlag) {
  2442. this._sweepFlag = sweepFlag;
  2443. this._segmentChanged();
  2444. },
  2445. enumerable: true
  2446. });
  2447. window.SVGPathSegArcRel = function (owningPathSegList, x, y, r1, r2, angle, largeArcFlag, sweepFlag) {
  2448. window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_ARC_REL, "a", owningPathSegList);
  2449. this._x = x;
  2450. this._y = y;
  2451. this._r1 = r1;
  2452. this._r2 = r2;
  2453. this._angle = angle;
  2454. this._largeArcFlag = largeArcFlag;
  2455. this._sweepFlag = sweepFlag;
  2456. };
  2457. window.SVGPathSegArcRel.prototype = Object.create(window.SVGPathSeg.prototype);
  2458. window.SVGPathSegArcRel.prototype.toString = function () {
  2459. return "[object SVGPathSegArcRel]";
  2460. };
  2461. window.SVGPathSegArcRel.prototype._asPathString = function () {
  2462. return this.pathSegTypeAsLetter + " " + this._r1 + " " + this._r2 + " " + this._angle + " " + (this._largeArcFlag ? "1" : "0") + " " + (this._sweepFlag ? "1" : "0") + " " + this._x + " " + this._y;
  2463. };
  2464. window.SVGPathSegArcRel.prototype.clone = function () {
  2465. return new window.SVGPathSegArcRel(undefined, this._x, this._y, this._r1, this._r2, this._angle, this._largeArcFlag, this._sweepFlag);
  2466. };
  2467. Object.defineProperty(window.SVGPathSegArcRel.prototype, "x", {
  2468. get: function get() {
  2469. return this._x;
  2470. },
  2471. set: function set(x) {
  2472. this._x = x;
  2473. this._segmentChanged();
  2474. },
  2475. enumerable: true
  2476. });
  2477. Object.defineProperty(window.SVGPathSegArcRel.prototype, "y", {
  2478. get: function get() {
  2479. return this._y;
  2480. },
  2481. set: function set(y) {
  2482. this._y = y;
  2483. this._segmentChanged();
  2484. },
  2485. enumerable: true
  2486. });
  2487. Object.defineProperty(window.SVGPathSegArcRel.prototype, "r1", {
  2488. get: function get() {
  2489. return this._r1;
  2490. },
  2491. set: function set(r1) {
  2492. this._r1 = r1;
  2493. this._segmentChanged();
  2494. },
  2495. enumerable: true
  2496. });
  2497. Object.defineProperty(window.SVGPathSegArcRel.prototype, "r2", {
  2498. get: function get() {
  2499. return this._r2;
  2500. },
  2501. set: function set(r2) {
  2502. this._r2 = r2;
  2503. this._segmentChanged();
  2504. },
  2505. enumerable: true
  2506. });
  2507. Object.defineProperty(window.SVGPathSegArcRel.prototype, "angle", {
  2508. get: function get() {
  2509. return this._angle;
  2510. },
  2511. set: function set(angle) {
  2512. this._angle = angle;
  2513. this._segmentChanged();
  2514. },
  2515. enumerable: true
  2516. });
  2517. Object.defineProperty(window.SVGPathSegArcRel.prototype, "largeArcFlag", {
  2518. get: function get() {
  2519. return this._largeArcFlag;
  2520. },
  2521. set: function set(largeArcFlag) {
  2522. this._largeArcFlag = largeArcFlag;
  2523. this._segmentChanged();
  2524. },
  2525. enumerable: true
  2526. });
  2527. Object.defineProperty(window.SVGPathSegArcRel.prototype, "sweepFlag", {
  2528. get: function get() {
  2529. return this._sweepFlag;
  2530. },
  2531. set: function set(sweepFlag) {
  2532. this._sweepFlag = sweepFlag;
  2533. this._segmentChanged();
  2534. },
  2535. enumerable: true
  2536. });
  2537. window.SVGPathSegLinetoHorizontalAbs = function (owningPathSegList, x) {
  2538. window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS, "H", owningPathSegList);
  2539. this._x = x;
  2540. };
  2541. window.SVGPathSegLinetoHorizontalAbs.prototype = Object.create(window.SVGPathSeg.prototype);
  2542. window.SVGPathSegLinetoHorizontalAbs.prototype.toString = function () {
  2543. return "[object SVGPathSegLinetoHorizontalAbs]";
  2544. };
  2545. window.SVGPathSegLinetoHorizontalAbs.prototype._asPathString = function () {
  2546. return this.pathSegTypeAsLetter + " " + this._x;
  2547. };
  2548. window.SVGPathSegLinetoHorizontalAbs.prototype.clone = function () {
  2549. return new window.SVGPathSegLinetoHorizontalAbs(undefined, this._x);
  2550. };
  2551. Object.defineProperty(window.SVGPathSegLinetoHorizontalAbs.prototype, "x", {
  2552. get: function get() {
  2553. return this._x;
  2554. },
  2555. set: function set(x) {
  2556. this._x = x;
  2557. this._segmentChanged();
  2558. },
  2559. enumerable: true
  2560. });
  2561. window.SVGPathSegLinetoHorizontalRel = function (owningPathSegList, x) {
  2562. window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL, "h", owningPathSegList);
  2563. this._x = x;
  2564. };
  2565. window.SVGPathSegLinetoHorizontalRel.prototype = Object.create(window.SVGPathSeg.prototype);
  2566. window.SVGPathSegLinetoHorizontalRel.prototype.toString = function () {
  2567. return "[object SVGPathSegLinetoHorizontalRel]";
  2568. };
  2569. window.SVGPathSegLinetoHorizontalRel.prototype._asPathString = function () {
  2570. return this.pathSegTypeAsLetter + " " + this._x;
  2571. };
  2572. window.SVGPathSegLinetoHorizontalRel.prototype.clone = function () {
  2573. return new window.SVGPathSegLinetoHorizontalRel(undefined, this._x);
  2574. };
  2575. Object.defineProperty(window.SVGPathSegLinetoHorizontalRel.prototype, "x", {
  2576. get: function get() {
  2577. return this._x;
  2578. },
  2579. set: function set(x) {
  2580. this._x = x;
  2581. this._segmentChanged();
  2582. },
  2583. enumerable: true
  2584. });
  2585. window.SVGPathSegLinetoVerticalAbs = function (owningPathSegList, y) {
  2586. window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS, "V", owningPathSegList);
  2587. this._y = y;
  2588. };
  2589. window.SVGPathSegLinetoVerticalAbs.prototype = Object.create(window.SVGPathSeg.prototype);
  2590. window.SVGPathSegLinetoVerticalAbs.prototype.toString = function () {
  2591. return "[object SVGPathSegLinetoVerticalAbs]";
  2592. };
  2593. window.SVGPathSegLinetoVerticalAbs.prototype._asPathString = function () {
  2594. return this.pathSegTypeAsLetter + " " + this._y;
  2595. };
  2596. window.SVGPathSegLinetoVerticalAbs.prototype.clone = function () {
  2597. return new window.SVGPathSegLinetoVerticalAbs(undefined, this._y);
  2598. };
  2599. Object.defineProperty(window.SVGPathSegLinetoVerticalAbs.prototype, "y", {
  2600. get: function get() {
  2601. return this._y;
  2602. },
  2603. set: function set(y) {
  2604. this._y = y;
  2605. this._segmentChanged();
  2606. },
  2607. enumerable: true
  2608. });
  2609. window.SVGPathSegLinetoVerticalRel = function (owningPathSegList, y) {
  2610. window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL, "v", owningPathSegList);
  2611. this._y = y;
  2612. };
  2613. window.SVGPathSegLinetoVerticalRel.prototype = Object.create(window.SVGPathSeg.prototype);
  2614. window.SVGPathSegLinetoVerticalRel.prototype.toString = function () {
  2615. return "[object SVGPathSegLinetoVerticalRel]";
  2616. };
  2617. window.SVGPathSegLinetoVerticalRel.prototype._asPathString = function () {
  2618. return this.pathSegTypeAsLetter + " " + this._y;
  2619. };
  2620. window.SVGPathSegLinetoVerticalRel.prototype.clone = function () {
  2621. return new window.SVGPathSegLinetoVerticalRel(undefined, this._y);
  2622. };
  2623. Object.defineProperty(window.SVGPathSegLinetoVerticalRel.prototype, "y", {
  2624. get: function get() {
  2625. return this._y;
  2626. },
  2627. set: function set(y) {
  2628. this._y = y;
  2629. this._segmentChanged();
  2630. },
  2631. enumerable: true
  2632. });
  2633. window.SVGPathSegCurvetoCubicSmoothAbs = function (owningPathSegList, x, y, x2, y2) {
  2634. window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS, "S", owningPathSegList);
  2635. this._x = x;
  2636. this._y = y;
  2637. this._x2 = x2;
  2638. this._y2 = y2;
  2639. };
  2640. window.SVGPathSegCurvetoCubicSmoothAbs.prototype = Object.create(window.SVGPathSeg.prototype);
  2641. window.SVGPathSegCurvetoCubicSmoothAbs.prototype.toString = function () {
  2642. return "[object SVGPathSegCurvetoCubicSmoothAbs]";
  2643. };
  2644. window.SVGPathSegCurvetoCubicSmoothAbs.prototype._asPathString = function () {
  2645. return this.pathSegTypeAsLetter + " " + this._x2 + " " + this._y2 + " " + this._x + " " + this._y;
  2646. };
  2647. window.SVGPathSegCurvetoCubicSmoothAbs.prototype.clone = function () {
  2648. return new window.SVGPathSegCurvetoCubicSmoothAbs(undefined, this._x, this._y, this._x2, this._y2);
  2649. };
  2650. Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothAbs.prototype, "x", {
  2651. get: function get() {
  2652. return this._x;
  2653. },
  2654. set: function set(x) {
  2655. this._x = x;
  2656. this._segmentChanged();
  2657. },
  2658. enumerable: true
  2659. });
  2660. Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothAbs.prototype, "y", {
  2661. get: function get() {
  2662. return this._y;
  2663. },
  2664. set: function set(y) {
  2665. this._y = y;
  2666. this._segmentChanged();
  2667. },
  2668. enumerable: true
  2669. });
  2670. Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothAbs.prototype, "x2", {
  2671. get: function get() {
  2672. return this._x2;
  2673. },
  2674. set: function set(x2) {
  2675. this._x2 = x2;
  2676. this._segmentChanged();
  2677. },
  2678. enumerable: true
  2679. });
  2680. Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothAbs.prototype, "y2", {
  2681. get: function get() {
  2682. return this._y2;
  2683. },
  2684. set: function set(y2) {
  2685. this._y2 = y2;
  2686. this._segmentChanged();
  2687. },
  2688. enumerable: true
  2689. });
  2690. window.SVGPathSegCurvetoCubicSmoothRel = function (owningPathSegList, x, y, x2, y2) {
  2691. window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL, "s", owningPathSegList);
  2692. this._x = x;
  2693. this._y = y;
  2694. this._x2 = x2;
  2695. this._y2 = y2;
  2696. };
  2697. window.SVGPathSegCurvetoCubicSmoothRel.prototype = Object.create(window.SVGPathSeg.prototype);
  2698. window.SVGPathSegCurvetoCubicSmoothRel.prototype.toString = function () {
  2699. return "[object SVGPathSegCurvetoCubicSmoothRel]";
  2700. };
  2701. window.SVGPathSegCurvetoCubicSmoothRel.prototype._asPathString = function () {
  2702. return this.pathSegTypeAsLetter + " " + this._x2 + " " + this._y2 + " " + this._x + " " + this._y;
  2703. };
  2704. window.SVGPathSegCurvetoCubicSmoothRel.prototype.clone = function () {
  2705. return new window.SVGPathSegCurvetoCubicSmoothRel(undefined, this._x, this._y, this._x2, this._y2);
  2706. };
  2707. Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothRel.prototype, "x", {
  2708. get: function get() {
  2709. return this._x;
  2710. },
  2711. set: function set(x) {
  2712. this._x = x;
  2713. this._segmentChanged();
  2714. },
  2715. enumerable: true
  2716. });
  2717. Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothRel.prototype, "y", {
  2718. get: function get() {
  2719. return this._y;
  2720. },
  2721. set: function set(y) {
  2722. this._y = y;
  2723. this._segmentChanged();
  2724. },
  2725. enumerable: true
  2726. });
  2727. Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothRel.prototype, "x2", {
  2728. get: function get() {
  2729. return this._x2;
  2730. },
  2731. set: function set(x2) {
  2732. this._x2 = x2;
  2733. this._segmentChanged();
  2734. },
  2735. enumerable: true
  2736. });
  2737. Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothRel.prototype, "y2", {
  2738. get: function get() {
  2739. return this._y2;
  2740. },
  2741. set: function set(y2) {
  2742. this._y2 = y2;
  2743. this._segmentChanged();
  2744. },
  2745. enumerable: true
  2746. });
  2747. window.SVGPathSegCurvetoQuadraticSmoothAbs = function (owningPathSegList, x, y) {
  2748. window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS, "T", owningPathSegList);
  2749. this._x = x;
  2750. this._y = y;
  2751. };
  2752. window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype = Object.create(window.SVGPathSeg.prototype);
  2753. window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype.toString = function () {
  2754. return "[object SVGPathSegCurvetoQuadraticSmoothAbs]";
  2755. };
  2756. window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype._asPathString = function () {
  2757. return this.pathSegTypeAsLetter + " " + this._x + " " + this._y;
  2758. };
  2759. window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype.clone = function () {
  2760. return new window.SVGPathSegCurvetoQuadraticSmoothAbs(undefined, this._x, this._y);
  2761. };
  2762. Object.defineProperty(window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype, "x", {
  2763. get: function get() {
  2764. return this._x;
  2765. },
  2766. set: function set(x) {
  2767. this._x = x;
  2768. this._segmentChanged();
  2769. },
  2770. enumerable: true
  2771. });
  2772. Object.defineProperty(window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype, "y", {
  2773. get: function get() {
  2774. return this._y;
  2775. },
  2776. set: function set(y) {
  2777. this._y = y;
  2778. this._segmentChanged();
  2779. },
  2780. enumerable: true
  2781. });
  2782. window.SVGPathSegCurvetoQuadraticSmoothRel = function (owningPathSegList, x, y) {
  2783. window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL, "t", owningPathSegList);
  2784. this._x = x;
  2785. this._y = y;
  2786. };
  2787. window.SVGPathSegCurvetoQuadraticSmoothRel.prototype = Object.create(window.SVGPathSeg.prototype);
  2788. window.SVGPathSegCurvetoQuadraticSmoothRel.prototype.toString = function () {
  2789. return "[object SVGPathSegCurvetoQuadraticSmoothRel]";
  2790. };
  2791. window.SVGPathSegCurvetoQuadraticSmoothRel.prototype._asPathString = function () {
  2792. return this.pathSegTypeAsLetter + " " + this._x + " " + this._y;
  2793. };
  2794. window.SVGPathSegCurvetoQuadraticSmoothRel.prototype.clone = function () {
  2795. return new window.SVGPathSegCurvetoQuadraticSmoothRel(undefined, this._x, this._y);
  2796. };
  2797. Object.defineProperty(window.SVGPathSegCurvetoQuadraticSmoothRel.prototype, "x", {
  2798. get: function get() {
  2799. return this._x;
  2800. },
  2801. set: function set(x) {
  2802. this._x = x;
  2803. this._segmentChanged();
  2804. },
  2805. enumerable: true
  2806. });
  2807. Object.defineProperty(window.SVGPathSegCurvetoQuadraticSmoothRel.prototype, "y", {
  2808. get: function get() {
  2809. return this._y;
  2810. },
  2811. set: function set(y) {
  2812. this._y = y;
  2813. this._segmentChanged();
  2814. },
  2815. enumerable: true
  2816. }); // Add createSVGPathSeg* functions to window.SVGPathElement.
  2817. // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-Interfacewindow.SVGPathElement.
  2818. window.SVGPathElement.prototype.createSVGPathSegClosePath = function () {
  2819. return new window.SVGPathSegClosePath(undefined);
  2820. };
  2821. window.SVGPathElement.prototype.createSVGPathSegMovetoAbs = function (x, y) {
  2822. return new window.SVGPathSegMovetoAbs(undefined, x, y);
  2823. };
  2824. window.SVGPathElement.prototype.createSVGPathSegMovetoRel = function (x, y) {
  2825. return new window.SVGPathSegMovetoRel(undefined, x, y);
  2826. };
  2827. window.SVGPathElement.prototype.createSVGPathSegLinetoAbs = function (x, y) {
  2828. return new window.SVGPathSegLinetoAbs(undefined, x, y);
  2829. };
  2830. window.SVGPathElement.prototype.createSVGPathSegLinetoRel = function (x, y) {
  2831. return new window.SVGPathSegLinetoRel(undefined, x, y);
  2832. };
  2833. window.SVGPathElement.prototype.createSVGPathSegCurvetoCubicAbs = function (x, y, x1, y1, x2, y2) {
  2834. return new window.SVGPathSegCurvetoCubicAbs(undefined, x, y, x1, y1, x2, y2);
  2835. };
  2836. window.SVGPathElement.prototype.createSVGPathSegCurvetoCubicRel = function (x, y, x1, y1, x2, y2) {
  2837. return new window.SVGPathSegCurvetoCubicRel(undefined, x, y, x1, y1, x2, y2);
  2838. };
  2839. window.SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticAbs = function (x, y, x1, y1) {
  2840. return new window.SVGPathSegCurvetoQuadraticAbs(undefined, x, y, x1, y1);
  2841. };
  2842. window.SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticRel = function (x, y, x1, y1) {
  2843. return new window.SVGPathSegCurvetoQuadraticRel(undefined, x, y, x1, y1);
  2844. };
  2845. window.SVGPathElement.prototype.createSVGPathSegArcAbs = function (x, y, r1, r2, angle, largeArcFlag, sweepFlag) {
  2846. return new window.SVGPathSegArcAbs(undefined, x, y, r1, r2, angle, largeArcFlag, sweepFlag);
  2847. };
  2848. window.SVGPathElement.prototype.createSVGPathSegArcRel = function (x, y, r1, r2, angle, largeArcFlag, sweepFlag) {
  2849. return new window.SVGPathSegArcRel(undefined, x, y, r1, r2, angle, largeArcFlag, sweepFlag);
  2850. };
  2851. window.SVGPathElement.prototype.createSVGPathSegLinetoHorizontalAbs = function (x) {
  2852. return new window.SVGPathSegLinetoHorizontalAbs(undefined, x);
  2853. };
  2854. window.SVGPathElement.prototype.createSVGPathSegLinetoHorizontalRel = function (x) {
  2855. return new window.SVGPathSegLinetoHorizontalRel(undefined, x);
  2856. };
  2857. window.SVGPathElement.prototype.createSVGPathSegLinetoVerticalAbs = function (y) {
  2858. return new window.SVGPathSegLinetoVerticalAbs(undefined, y);
  2859. };
  2860. window.SVGPathElement.prototype.createSVGPathSegLinetoVerticalRel = function (y) {
  2861. return new window.SVGPathSegLinetoVerticalRel(undefined, y);
  2862. };
  2863. window.SVGPathElement.prototype.createSVGPathSegCurvetoCubicSmoothAbs = function (x, y, x2, y2) {
  2864. return new window.SVGPathSegCurvetoCubicSmoothAbs(undefined, x, y, x2, y2);
  2865. };
  2866. window.SVGPathElement.prototype.createSVGPathSegCurvetoCubicSmoothRel = function (x, y, x2, y2) {
  2867. return new window.SVGPathSegCurvetoCubicSmoothRel(undefined, x, y, x2, y2);
  2868. };
  2869. window.SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticSmoothAbs = function (x, y) {
  2870. return new window.SVGPathSegCurvetoQuadraticSmoothAbs(undefined, x, y);
  2871. };
  2872. window.SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticSmoothRel = function (x, y) {
  2873. return new window.SVGPathSegCurvetoQuadraticSmoothRel(undefined, x, y);
  2874. };
  2875. if (!("getPathSegAtLength" in window.SVGPathElement.prototype)) {
  2876. // Add getPathSegAtLength to SVGPathElement.
  2877. // Spec: https://www.w3.org/TR/SVG11/single-page.html#paths-__svg__SVGPathElement__getPathSegAtLength
  2878. // This polyfill requires SVGPathElement.getTotalLength to implement the distance-along-a-path algorithm.
  2879. window.SVGPathElement.prototype.getPathSegAtLength = function (distance) {
  2880. if (distance === undefined || !isFinite(distance)) throw "Invalid arguments.";
  2881. var measurementElement = document.createElementNS("http://www.w3.org/2000/svg", "path");
  2882. measurementElement.setAttribute("d", this.getAttribute("d"));
  2883. var lastPathSegment = measurementElement.pathSegList.numberOfItems - 1; // If the path is empty, return 0.
  2884. if (lastPathSegment <= 0) return 0;
  2885. do {
  2886. measurementElement.pathSegList.removeItem(lastPathSegment);
  2887. if (distance > measurementElement.getTotalLength()) break;
  2888. lastPathSegment--;
  2889. } while (lastPathSegment > 0);
  2890. return lastPathSegment;
  2891. };
  2892. }
  2893. }
  2894. if (!("SVGPathSegList" in window)) {
  2895. // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathSegList
  2896. window.SVGPathSegList = function (pathElement) {
  2897. this._pathElement = pathElement;
  2898. this._list = this._parsePath(this._pathElement.getAttribute("d")); // Use a MutationObserver to catch changes to the path's "d" attribute.
  2899. this._mutationObserverConfig = {
  2900. "attributes": true,
  2901. "attributeFilter": ["d"]
  2902. };
  2903. this._pathElementMutationObserver = new MutationObserver(this._updateListFromPathMutations.bind(this));
  2904. this._pathElementMutationObserver.observe(this._pathElement, this._mutationObserverConfig);
  2905. };
  2906. window.SVGPathSegList.prototype.classname = "SVGPathSegList";
  2907. Object.defineProperty(window.SVGPathSegList.prototype, "numberOfItems", {
  2908. get: function get() {
  2909. this._checkPathSynchronizedToList();
  2910. return this._list.length;
  2911. },
  2912. enumerable: true
  2913. }); // Add the pathSegList accessors to window.SVGPathElement.
  2914. // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGAnimatedPathData
  2915. Object.defineProperty(window.SVGPathElement.prototype, "pathSegList", {
  2916. get: function get() {
  2917. if (!this._pathSegList) this._pathSegList = new window.SVGPathSegList(this);
  2918. return this._pathSegList;
  2919. },
  2920. enumerable: true
  2921. }); // FIXME: The following are not implemented and simply return window.SVGPathElement.pathSegList.
  2922. Object.defineProperty(window.SVGPathElement.prototype, "normalizedPathSegList", {
  2923. get: function get() {
  2924. return this.pathSegList;
  2925. },
  2926. enumerable: true
  2927. });
  2928. Object.defineProperty(window.SVGPathElement.prototype, "animatedPathSegList", {
  2929. get: function get() {
  2930. return this.pathSegList;
  2931. },
  2932. enumerable: true
  2933. });
  2934. Object.defineProperty(window.SVGPathElement.prototype, "animatedNormalizedPathSegList", {
  2935. get: function get() {
  2936. return this.pathSegList;
  2937. },
  2938. enumerable: true
  2939. }); // Process any pending mutations to the path element and update the list as needed.
  2940. // This should be the first call of all public functions and is needed because
  2941. // MutationObservers are not synchronous so we can have pending asynchronous mutations.
  2942. window.SVGPathSegList.prototype._checkPathSynchronizedToList = function () {
  2943. this._updateListFromPathMutations(this._pathElementMutationObserver.takeRecords());
  2944. };
  2945. window.SVGPathSegList.prototype._updateListFromPathMutations = function (mutationRecords) {
  2946. if (!this._pathElement) return;
  2947. var hasPathMutations = false;
  2948. mutationRecords.forEach(function (record) {
  2949. if (record.attributeName == "d") hasPathMutations = true;
  2950. });
  2951. if (hasPathMutations) this._list = this._parsePath(this._pathElement.getAttribute("d"));
  2952. }; // Serialize the list and update the path's 'd' attribute.
  2953. window.SVGPathSegList.prototype._writeListToPath = function () {
  2954. this._pathElementMutationObserver.disconnect();
  2955. this._pathElement.setAttribute("d", window.SVGPathSegList._pathSegArrayAsString(this._list));
  2956. this._pathElementMutationObserver.observe(this._pathElement, this._mutationObserverConfig);
  2957. }; // When a path segment changes the list needs to be synchronized back to the path element.
  2958. window.SVGPathSegList.prototype.segmentChanged = function (pathSeg) {
  2959. this._writeListToPath();
  2960. };
  2961. window.SVGPathSegList.prototype.clear = function () {
  2962. this._checkPathSynchronizedToList();
  2963. this._list.forEach(function (pathSeg) {
  2964. pathSeg._owningPathSegList = null;
  2965. });
  2966. this._list = [];
  2967. this._writeListToPath();
  2968. };
  2969. window.SVGPathSegList.prototype.initialize = function (newItem) {
  2970. this._checkPathSynchronizedToList();
  2971. this._list = [newItem];
  2972. newItem._owningPathSegList = this;
  2973. this._writeListToPath();
  2974. return newItem;
  2975. };
  2976. window.SVGPathSegList.prototype._checkValidIndex = function (index) {
  2977. if (isNaN(index) || index < 0 || index >= this.numberOfItems) throw "INDEX_SIZE_ERR";
  2978. };
  2979. window.SVGPathSegList.prototype.getItem = function (index) {
  2980. this._checkPathSynchronizedToList();
  2981. this._checkValidIndex(index);
  2982. return this._list[index];
  2983. };
  2984. window.SVGPathSegList.prototype.insertItemBefore = function (newItem, index) {
  2985. this._checkPathSynchronizedToList(); // Spec: If the index is greater than or equal to numberOfItems, then the new item is appended to the end of the list.
  2986. if (index > this.numberOfItems) index = this.numberOfItems;
  2987. if (newItem._owningPathSegList) {
  2988. // SVG2 spec says to make a copy.
  2989. newItem = newItem.clone();
  2990. }
  2991. this._list.splice(index, 0, newItem);
  2992. newItem._owningPathSegList = this;
  2993. this._writeListToPath();
  2994. return newItem;
  2995. };
  2996. window.SVGPathSegList.prototype.replaceItem = function (newItem, index) {
  2997. this._checkPathSynchronizedToList();
  2998. if (newItem._owningPathSegList) {
  2999. // SVG2 spec says to make a copy.
  3000. newItem = newItem.clone();
  3001. }
  3002. this._checkValidIndex(index);
  3003. this._list[index] = newItem;
  3004. newItem._owningPathSegList = this;
  3005. this._writeListToPath();
  3006. return newItem;
  3007. };
  3008. window.SVGPathSegList.prototype.removeItem = function (index) {
  3009. this._checkPathSynchronizedToList();
  3010. this._checkValidIndex(index);
  3011. var item = this._list[index];
  3012. this._list.splice(index, 1);
  3013. this._writeListToPath();
  3014. return item;
  3015. };
  3016. window.SVGPathSegList.prototype.appendItem = function (newItem) {
  3017. this._checkPathSynchronizedToList();
  3018. if (newItem._owningPathSegList) {
  3019. // SVG2 spec says to make a copy.
  3020. newItem = newItem.clone();
  3021. }
  3022. this._list.push(newItem);
  3023. newItem._owningPathSegList = this; // TODO: Optimize this to just append to the existing attribute.
  3024. this._writeListToPath();
  3025. return newItem;
  3026. };
  3027. window.SVGPathSegList._pathSegArrayAsString = function (pathSegArray) {
  3028. var string = "";
  3029. var first = true;
  3030. pathSegArray.forEach(function (pathSeg) {
  3031. if (first) {
  3032. first = false;
  3033. string += pathSeg._asPathString();
  3034. } else {
  3035. string += " " + pathSeg._asPathString();
  3036. }
  3037. });
  3038. return string;
  3039. }; // This closely follows SVGPathParser::parsePath from Source/core/svg/SVGPathParser.cpp.
  3040. window.SVGPathSegList.prototype._parsePath = function (string) {
  3041. if (!string || string.length == 0) return [];
  3042. var owningPathSegList = this;
  3043. var Builder = function Builder() {
  3044. this.pathSegList = [];
  3045. };
  3046. Builder.prototype.appendSegment = function (pathSeg) {
  3047. this.pathSegList.push(pathSeg);
  3048. };
  3049. var Source = function Source(string) {
  3050. this._string = string;
  3051. this._currentIndex = 0;
  3052. this._endIndex = this._string.length;
  3053. this._previousCommand = window.SVGPathSeg.PATHSEG_UNKNOWN;
  3054. this._skipOptionalSpaces();
  3055. };
  3056. Source.prototype._isCurrentSpace = function () {
  3057. var character = this._string[this._currentIndex];
  3058. return character <= " " && (character == " " || character == "\n" || character == "\t" || character == "\r" || character == "\f");
  3059. };
  3060. Source.prototype._skipOptionalSpaces = function () {
  3061. while (this._currentIndex < this._endIndex && this._isCurrentSpace()) {
  3062. this._currentIndex++;
  3063. }
  3064. return this._currentIndex < this._endIndex;
  3065. };
  3066. Source.prototype._skipOptionalSpacesOrDelimiter = function () {
  3067. if (this._currentIndex < this._endIndex && !this._isCurrentSpace() && this._string.charAt(this._currentIndex) != ",") return false;
  3068. if (this._skipOptionalSpaces()) {
  3069. if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) == ",") {
  3070. this._currentIndex++;
  3071. this._skipOptionalSpaces();
  3072. }
  3073. }
  3074. return this._currentIndex < this._endIndex;
  3075. };
  3076. Source.prototype.hasMoreData = function () {
  3077. return this._currentIndex < this._endIndex;
  3078. };
  3079. Source.prototype.peekSegmentType = function () {
  3080. var lookahead = this._string[this._currentIndex];
  3081. return this._pathSegTypeFromChar(lookahead);
  3082. };
  3083. Source.prototype._pathSegTypeFromChar = function (lookahead) {
  3084. switch (lookahead) {
  3085. case "Z":
  3086. case "z":
  3087. return window.SVGPathSeg.PATHSEG_CLOSEPATH;
  3088. case "M":
  3089. return window.SVGPathSeg.PATHSEG_MOVETO_ABS;
  3090. case "m":
  3091. return window.SVGPathSeg.PATHSEG_MOVETO_REL;
  3092. case "L":
  3093. return window.SVGPathSeg.PATHSEG_LINETO_ABS;
  3094. case "l":
  3095. return window.SVGPathSeg.PATHSEG_LINETO_REL;
  3096. case "C":
  3097. return window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS;
  3098. case "c":
  3099. return window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL;
  3100. case "Q":
  3101. return window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS;
  3102. case "q":
  3103. return window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL;
  3104. case "A":
  3105. return window.SVGPathSeg.PATHSEG_ARC_ABS;
  3106. case "a":
  3107. return window.SVGPathSeg.PATHSEG_ARC_REL;
  3108. case "H":
  3109. return window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS;
  3110. case "h":
  3111. return window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL;
  3112. case "V":
  3113. return window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS;
  3114. case "v":
  3115. return window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL;
  3116. case "S":
  3117. return window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS;
  3118. case "s":
  3119. return window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL;
  3120. case "T":
  3121. return window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS;
  3122. case "t":
  3123. return window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL;
  3124. default:
  3125. return window.SVGPathSeg.PATHSEG_UNKNOWN;
  3126. }
  3127. };
  3128. Source.prototype._nextCommandHelper = function (lookahead, previousCommand) {
  3129. // Check for remaining coordinates in the current command.
  3130. if ((lookahead == "+" || lookahead == "-" || lookahead == "." || lookahead >= "0" && lookahead <= "9") && previousCommand != window.SVGPathSeg.PATHSEG_CLOSEPATH) {
  3131. if (previousCommand == window.SVGPathSeg.PATHSEG_MOVETO_ABS) return window.SVGPathSeg.PATHSEG_LINETO_ABS;
  3132. if (previousCommand == window.SVGPathSeg.PATHSEG_MOVETO_REL) return window.SVGPathSeg.PATHSEG_LINETO_REL;
  3133. return previousCommand;
  3134. }
  3135. return window.SVGPathSeg.PATHSEG_UNKNOWN;
  3136. };
  3137. Source.prototype.initialCommandIsMoveTo = function () {
  3138. // If the path is empty it is still valid, so return true.
  3139. if (!this.hasMoreData()) return true;
  3140. var command = this.peekSegmentType(); // Path must start with moveTo.
  3141. return command == window.SVGPathSeg.PATHSEG_MOVETO_ABS || command == window.SVGPathSeg.PATHSEG_MOVETO_REL;
  3142. }; // Parse a number from an SVG path. This very closely follows genericParseNumber(...) from Source/core/svg/SVGParserUtilities.cpp.
  3143. // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-PathDataBNF
  3144. Source.prototype._parseNumber = function () {
  3145. var exponent = 0;
  3146. var integer = 0;
  3147. var frac = 1;
  3148. var decimal = 0;
  3149. var sign = 1;
  3150. var expsign = 1;
  3151. var startIndex = this._currentIndex;
  3152. this._skipOptionalSpaces(); // Read the sign.
  3153. if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) == "+") this._currentIndex++;else if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) == "-") {
  3154. this._currentIndex++;
  3155. sign = -1;
  3156. }
  3157. if (this._currentIndex == this._endIndex || (this._string.charAt(this._currentIndex) < "0" || this._string.charAt(this._currentIndex) > "9") && this._string.charAt(this._currentIndex) != ".") // The first character of a number must be one of [0-9+-.].
  3158. return undefined; // Read the integer part, build right-to-left.
  3159. var startIntPartIndex = this._currentIndex;
  3160. while (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) >= "0" && this._string.charAt(this._currentIndex) <= "9") {
  3161. this._currentIndex++;
  3162. } // Advance to first non-digit.
  3163. if (this._currentIndex != startIntPartIndex) {
  3164. var scanIntPartIndex = this._currentIndex - 1;
  3165. var multiplier = 1;
  3166. while (scanIntPartIndex >= startIntPartIndex) {
  3167. integer += multiplier * (this._string.charAt(scanIntPartIndex--) - "0");
  3168. multiplier *= 10;
  3169. }
  3170. } // Read the decimals.
  3171. if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) == ".") {
  3172. this._currentIndex++; // There must be a least one digit following the .
  3173. if (this._currentIndex >= this._endIndex || this._string.charAt(this._currentIndex) < "0" || this._string.charAt(this._currentIndex) > "9") return undefined;
  3174. while (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) >= "0" && this._string.charAt(this._currentIndex) <= "9") {
  3175. frac *= 10;
  3176. decimal += (this._string.charAt(this._currentIndex) - "0") / frac;
  3177. this._currentIndex += 1;
  3178. }
  3179. } // Read the exponent part.
  3180. if (this._currentIndex != startIndex && this._currentIndex + 1 < this._endIndex && (this._string.charAt(this._currentIndex) == "e" || this._string.charAt(this._currentIndex) == "E") && this._string.charAt(this._currentIndex + 1) != "x" && this._string.charAt(this._currentIndex + 1) != "m") {
  3181. this._currentIndex++; // Read the sign of the exponent.
  3182. if (this._string.charAt(this._currentIndex) == "+") {
  3183. this._currentIndex++;
  3184. } else if (this._string.charAt(this._currentIndex) == "-") {
  3185. this._currentIndex++;
  3186. expsign = -1;
  3187. } // There must be an exponent.
  3188. if (this._currentIndex >= this._endIndex || this._string.charAt(this._currentIndex) < "0" || this._string.charAt(this._currentIndex) > "9") return undefined;
  3189. while (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) >= "0" && this._string.charAt(this._currentIndex) <= "9") {
  3190. exponent *= 10;
  3191. exponent += this._string.charAt(this._currentIndex) - "0";
  3192. this._currentIndex++;
  3193. }
  3194. }
  3195. var number = integer + decimal;
  3196. number *= sign;
  3197. if (exponent) number *= Math.pow(10, expsign * exponent);
  3198. if (startIndex == this._currentIndex) return undefined;
  3199. this._skipOptionalSpacesOrDelimiter();
  3200. return number;
  3201. };
  3202. Source.prototype._parseArcFlag = function () {
  3203. if (this._currentIndex >= this._endIndex) return undefined;
  3204. var flag = false;
  3205. var flagChar = this._string.charAt(this._currentIndex++);
  3206. if (flagChar == "0") flag = false;else if (flagChar == "1") flag = true;else return undefined;
  3207. this._skipOptionalSpacesOrDelimiter();
  3208. return flag;
  3209. };
  3210. Source.prototype.parseSegment = function () {
  3211. var lookahead = this._string[this._currentIndex];
  3212. var command = this._pathSegTypeFromChar(lookahead);
  3213. if (command == window.SVGPathSeg.PATHSEG_UNKNOWN) {
  3214. // Possibly an implicit command. Not allowed if this is the first command.
  3215. if (this._previousCommand == window.SVGPathSeg.PATHSEG_UNKNOWN) return null;
  3216. command = this._nextCommandHelper(lookahead, this._previousCommand);
  3217. if (command == window.SVGPathSeg.PATHSEG_UNKNOWN) return null;
  3218. } else {
  3219. this._currentIndex++;
  3220. }
  3221. this._previousCommand = command;
  3222. switch (command) {
  3223. case window.SVGPathSeg.PATHSEG_MOVETO_REL:
  3224. return new window.SVGPathSegMovetoRel(owningPathSegList, this._parseNumber(), this._parseNumber());
  3225. case window.SVGPathSeg.PATHSEG_MOVETO_ABS:
  3226. return new window.SVGPathSegMovetoAbs(owningPathSegList, this._parseNumber(), this._parseNumber());
  3227. case window.SVGPathSeg.PATHSEG_LINETO_REL:
  3228. return new window.SVGPathSegLinetoRel(owningPathSegList, this._parseNumber(), this._parseNumber());
  3229. case window.SVGPathSeg.PATHSEG_LINETO_ABS:
  3230. return new window.SVGPathSegLinetoAbs(owningPathSegList, this._parseNumber(), this._parseNumber());
  3231. case window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL:
  3232. return new window.SVGPathSegLinetoHorizontalRel(owningPathSegList, this._parseNumber());
  3233. case window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS:
  3234. return new window.SVGPathSegLinetoHorizontalAbs(owningPathSegList, this._parseNumber());
  3235. case window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL:
  3236. return new window.SVGPathSegLinetoVerticalRel(owningPathSegList, this._parseNumber());
  3237. case window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS:
  3238. return new window.SVGPathSegLinetoVerticalAbs(owningPathSegList, this._parseNumber());
  3239. case window.SVGPathSeg.PATHSEG_CLOSEPATH:
  3240. this._skipOptionalSpaces();
  3241. return new window.SVGPathSegClosePath(owningPathSegList);
  3242. case window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL:
  3243. var points = {
  3244. x1: this._parseNumber(),
  3245. y1: this._parseNumber(),
  3246. x2: this._parseNumber(),
  3247. y2: this._parseNumber(),
  3248. x: this._parseNumber(),
  3249. y: this._parseNumber()
  3250. };
  3251. return new window.SVGPathSegCurvetoCubicRel(owningPathSegList, points.x, points.y, points.x1, points.y1, points.x2, points.y2);
  3252. case window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS:
  3253. var points = {
  3254. x1: this._parseNumber(),
  3255. y1: this._parseNumber(),
  3256. x2: this._parseNumber(),
  3257. y2: this._parseNumber(),
  3258. x: this._parseNumber(),
  3259. y: this._parseNumber()
  3260. };
  3261. return new window.SVGPathSegCurvetoCubicAbs(owningPathSegList, points.x, points.y, points.x1, points.y1, points.x2, points.y2);
  3262. case window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL:
  3263. var points = {
  3264. x2: this._parseNumber(),
  3265. y2: this._parseNumber(),
  3266. x: this._parseNumber(),
  3267. y: this._parseNumber()
  3268. };
  3269. return new window.SVGPathSegCurvetoCubicSmoothRel(owningPathSegList, points.x, points.y, points.x2, points.y2);
  3270. case window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS:
  3271. var points = {
  3272. x2: this._parseNumber(),
  3273. y2: this._parseNumber(),
  3274. x: this._parseNumber(),
  3275. y: this._parseNumber()
  3276. };
  3277. return new window.SVGPathSegCurvetoCubicSmoothAbs(owningPathSegList, points.x, points.y, points.x2, points.y2);
  3278. case window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL:
  3279. var points = {
  3280. x1: this._parseNumber(),
  3281. y1: this._parseNumber(),
  3282. x: this._parseNumber(),
  3283. y: this._parseNumber()
  3284. };
  3285. return new window.SVGPathSegCurvetoQuadraticRel(owningPathSegList, points.x, points.y, points.x1, points.y1);
  3286. case window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS:
  3287. var points = {
  3288. x1: this._parseNumber(),
  3289. y1: this._parseNumber(),
  3290. x: this._parseNumber(),
  3291. y: this._parseNumber()
  3292. };
  3293. return new window.SVGPathSegCurvetoQuadraticAbs(owningPathSegList, points.x, points.y, points.x1, points.y1);
  3294. case window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:
  3295. return new window.SVGPathSegCurvetoQuadraticSmoothRel(owningPathSegList, this._parseNumber(), this._parseNumber());
  3296. case window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS:
  3297. return new window.SVGPathSegCurvetoQuadraticSmoothAbs(owningPathSegList, this._parseNumber(), this._parseNumber());
  3298. case window.SVGPathSeg.PATHSEG_ARC_REL:
  3299. var points = {
  3300. x1: this._parseNumber(),
  3301. y1: this._parseNumber(),
  3302. arcAngle: this._parseNumber(),
  3303. arcLarge: this._parseArcFlag(),
  3304. arcSweep: this._parseArcFlag(),
  3305. x: this._parseNumber(),
  3306. y: this._parseNumber()
  3307. };
  3308. return new window.SVGPathSegArcRel(owningPathSegList, points.x, points.y, points.x1, points.y1, points.arcAngle, points.arcLarge, points.arcSweep);
  3309. case window.SVGPathSeg.PATHSEG_ARC_ABS:
  3310. var points = {
  3311. x1: this._parseNumber(),
  3312. y1: this._parseNumber(),
  3313. arcAngle: this._parseNumber(),
  3314. arcLarge: this._parseArcFlag(),
  3315. arcSweep: this._parseArcFlag(),
  3316. x: this._parseNumber(),
  3317. y: this._parseNumber()
  3318. };
  3319. return new window.SVGPathSegArcAbs(owningPathSegList, points.x, points.y, points.x1, points.y1, points.arcAngle, points.arcLarge, points.arcSweep);
  3320. default:
  3321. throw "Unknown path seg type.";
  3322. }
  3323. };
  3324. var builder = new Builder();
  3325. var source = new Source(string);
  3326. if (!source.initialCommandIsMoveTo()) return [];
  3327. while (source.hasMoreData()) {
  3328. var pathSeg = source.parseSegment();
  3329. if (!pathSeg) return [];
  3330. builder.appendSegment(pathSeg);
  3331. }
  3332. return builder.pathSegList;
  3333. };
  3334. }
  3335. })(); // String.padEnd polyfill for IE11
  3336. //
  3337. // https://github.com/uxitten/polyfill/blob/master/string.polyfill.js
  3338. // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padEnd
  3339. if (!String.prototype.padEnd) {
  3340. String.prototype.padEnd = function padEnd(targetLength, padString) {
  3341. targetLength = targetLength >> 0; //floor if number or convert non-number to 0;
  3342. padString = String(typeof padString !== 'undefined' ? padString : ' ');
  3343. if (this.length > targetLength) {
  3344. return String(this);
  3345. } else {
  3346. targetLength = targetLength - this.length;
  3347. if (targetLength > padString.length) {
  3348. padString += padString.repeat(targetLength / padString.length); //append to original to ensure we are longer than needed
  3349. }
  3350. return String(this) + padString.slice(0, targetLength);
  3351. }
  3352. };
  3353. }
  3354. /* jshint ignore:end */
  3355. Chart.prototype.axis = function () {};
  3356. Chart.prototype.axis.labels = function (labels) {
  3357. var $$ = this.internal;
  3358. if (arguments.length) {
  3359. Object.keys(labels).forEach(function (axisId) {
  3360. $$.axis.setLabelText(axisId, labels[axisId]);
  3361. });
  3362. $$.axis.updateLabels();
  3363. } // TODO: return some values?
  3364. };
  3365. Chart.prototype.axis.max = function (max) {
  3366. var $$ = this.internal,
  3367. config = $$.config;
  3368. if (arguments.length) {
  3369. if (_typeof(max) === 'object') {
  3370. if (isValue(max.x)) {
  3371. config.axis_x_max = max.x;
  3372. }
  3373. if (isValue(max.y)) {
  3374. config.axis_y_max = max.y;
  3375. }
  3376. if (isValue(max.y2)) {
  3377. config.axis_y2_max = max.y2;
  3378. }
  3379. } else {
  3380. config.axis_y_max = config.axis_y2_max = max;
  3381. }
  3382. $$.redraw({
  3383. withUpdateOrgXDomain: true,
  3384. withUpdateXDomain: true
  3385. });
  3386. } else {
  3387. return {
  3388. x: config.axis_x_max,
  3389. y: config.axis_y_max,
  3390. y2: config.axis_y2_max
  3391. };
  3392. }
  3393. };
  3394. Chart.prototype.axis.min = function (min) {
  3395. var $$ = this.internal,
  3396. config = $$.config;
  3397. if (arguments.length) {
  3398. if (_typeof(min) === 'object') {
  3399. if (isValue(min.x)) {
  3400. config.axis_x_min = min.x;
  3401. }
  3402. if (isValue(min.y)) {
  3403. config.axis_y_min = min.y;
  3404. }
  3405. if (isValue(min.y2)) {
  3406. config.axis_y2_min = min.y2;
  3407. }
  3408. } else {
  3409. config.axis_y_min = config.axis_y2_min = min;
  3410. }
  3411. $$.redraw({
  3412. withUpdateOrgXDomain: true,
  3413. withUpdateXDomain: true
  3414. });
  3415. } else {
  3416. return {
  3417. x: config.axis_x_min,
  3418. y: config.axis_y_min,
  3419. y2: config.axis_y2_min
  3420. };
  3421. }
  3422. };
  3423. Chart.prototype.axis.range = function (range) {
  3424. if (arguments.length) {
  3425. if (isDefined(range.max)) {
  3426. this.axis.max(range.max);
  3427. }
  3428. if (isDefined(range.min)) {
  3429. this.axis.min(range.min);
  3430. }
  3431. } else {
  3432. return {
  3433. max: this.axis.max(),
  3434. min: this.axis.min()
  3435. };
  3436. }
  3437. };
  3438. Chart.prototype.category = function (i, category) {
  3439. var $$ = this.internal,
  3440. config = $$.config;
  3441. if (arguments.length > 1) {
  3442. config.axis_x_categories[i] = category;
  3443. $$.redraw();
  3444. }
  3445. return config.axis_x_categories[i];
  3446. };
  3447. Chart.prototype.categories = function (categories) {
  3448. var $$ = this.internal,
  3449. config = $$.config;
  3450. if (!arguments.length) {
  3451. return config.axis_x_categories;
  3452. }
  3453. config.axis_x_categories = categories;
  3454. $$.redraw();
  3455. return config.axis_x_categories;
  3456. };
  3457. Chart.prototype.resize = function (size) {
  3458. var $$ = this.internal,
  3459. config = $$.config;
  3460. config.size_width = size ? size.width : null;
  3461. config.size_height = size ? size.height : null;
  3462. this.flush();
  3463. };
  3464. Chart.prototype.flush = function () {
  3465. var $$ = this.internal;
  3466. $$.updateAndRedraw({
  3467. withLegend: true,
  3468. withTransition: false,
  3469. withTransitionForTransform: false
  3470. });
  3471. };
  3472. Chart.prototype.destroy = function () {
  3473. var $$ = this.internal;
  3474. window.clearInterval($$.intervalForObserveInserted);
  3475. if ($$.resizeTimeout !== undefined) {
  3476. window.clearTimeout($$.resizeTimeout);
  3477. }
  3478. if (window.detachEvent) {
  3479. window.detachEvent('onresize', $$.resizeIfElementDisplayed);
  3480. } else if (window.removeEventListener) {
  3481. window.removeEventListener('resize', $$.resizeIfElementDisplayed);
  3482. } else {
  3483. var wrapper = window.onresize; // check if no one else removed our wrapper and remove our resizeFunction from it
  3484. if (wrapper && wrapper.add && wrapper.remove) {
  3485. wrapper.remove($$.resizeFunction);
  3486. }
  3487. } // remove the inner resize functions
  3488. $$.resizeFunction.remove();
  3489. $$.selectChart.classed('c3', false).html(""); // MEMO: this is needed because the reference of some elements will not be released, then memory leak will happen.
  3490. Object.keys($$).forEach(function (key) {
  3491. $$[key] = null;
  3492. });
  3493. return null;
  3494. };
  3495. Chart.prototype.color = function (id) {
  3496. var $$ = this.internal;
  3497. return $$.color(id); // more patterns
  3498. };
  3499. Chart.prototype.data = function (targetIds) {
  3500. var targets = this.internal.data.targets;
  3501. return typeof targetIds === 'undefined' ? targets : targets.filter(function (t) {
  3502. return [].concat(targetIds).indexOf(t.id) >= 0;
  3503. });
  3504. };
  3505. Chart.prototype.data.shown = function (targetIds) {
  3506. return this.internal.filterTargetsToShow(this.data(targetIds));
  3507. };
  3508. Chart.prototype.data.values = function (targetId) {
  3509. var targets,
  3510. values = null;
  3511. if (targetId) {
  3512. targets = this.data(targetId);
  3513. values = targets[0] ? targets[0].values.map(function (d) {
  3514. return d.value;
  3515. }) : null;
  3516. }
  3517. return values;
  3518. };
  3519. Chart.prototype.data.names = function (names) {
  3520. this.internal.clearLegendItemTextBoxCache();
  3521. return this.internal.updateDataAttributes('names', names);
  3522. };
  3523. Chart.prototype.data.colors = function (colors) {
  3524. return this.internal.updateDataAttributes('colors', colors);
  3525. };
  3526. Chart.prototype.data.axes = function (axes) {
  3527. return this.internal.updateDataAttributes('axes', axes);
  3528. };
  3529. Chart.prototype.flow = function (args) {
  3530. var $$ = this.internal,
  3531. targets,
  3532. data,
  3533. notfoundIds = [],
  3534. orgDataCount = $$.getMaxDataCount(),
  3535. dataCount,
  3536. domain,
  3537. baseTarget,
  3538. baseValue,
  3539. length = 0,
  3540. tail = 0,
  3541. diff,
  3542. to;
  3543. if (args.json) {
  3544. data = $$.convertJsonToData(args.json, args.keys);
  3545. } else if (args.rows) {
  3546. data = $$.convertRowsToData(args.rows);
  3547. } else if (args.columns) {
  3548. data = $$.convertColumnsToData(args.columns);
  3549. } else {
  3550. return;
  3551. }
  3552. targets = $$.convertDataToTargets(data, true); // Update/Add data
  3553. $$.data.targets.forEach(function (t) {
  3554. var found = false,
  3555. i,
  3556. j;
  3557. for (i = 0; i < targets.length; i++) {
  3558. if (t.id === targets[i].id) {
  3559. found = true;
  3560. if (t.values[t.values.length - 1]) {
  3561. tail = t.values[t.values.length - 1].index + 1;
  3562. }
  3563. length = targets[i].values.length;
  3564. for (j = 0; j < length; j++) {
  3565. targets[i].values[j].index = tail + j;
  3566. if (!$$.isTimeSeries()) {
  3567. targets[i].values[j].x = tail + j;
  3568. }
  3569. }
  3570. t.values = t.values.concat(targets[i].values);
  3571. targets.splice(i, 1);
  3572. break;
  3573. }
  3574. }
  3575. if (!found) {
  3576. notfoundIds.push(t.id);
  3577. }
  3578. }); // Append null for not found targets
  3579. $$.data.targets.forEach(function (t) {
  3580. var i, j;
  3581. for (i = 0; i < notfoundIds.length; i++) {
  3582. if (t.id === notfoundIds[i]) {
  3583. tail = t.values[t.values.length - 1].index + 1;
  3584. for (j = 0; j < length; j++) {
  3585. t.values.push({
  3586. id: t.id,
  3587. index: tail + j,
  3588. x: $$.isTimeSeries() ? $$.getOtherTargetX(tail + j) : tail + j,
  3589. value: null
  3590. });
  3591. }
  3592. }
  3593. }
  3594. }); // Generate null values for new target
  3595. if ($$.data.targets.length) {
  3596. targets.forEach(function (t) {
  3597. var i,
  3598. missing = [];
  3599. for (i = $$.data.targets[0].values[0].index; i < tail; i++) {
  3600. missing.push({
  3601. id: t.id,
  3602. index: i,
  3603. x: $$.isTimeSeries() ? $$.getOtherTargetX(i) : i,
  3604. value: null
  3605. });
  3606. }
  3607. t.values.forEach(function (v) {
  3608. v.index += tail;
  3609. if (!$$.isTimeSeries()) {
  3610. v.x += tail;
  3611. }
  3612. });
  3613. t.values = missing.concat(t.values);
  3614. });
  3615. }
  3616. $$.data.targets = $$.data.targets.concat(targets); // add remained
  3617. // check data count because behavior needs to change when it's only one
  3618. dataCount = $$.getMaxDataCount();
  3619. baseTarget = $$.data.targets[0];
  3620. baseValue = baseTarget.values[0]; // Update length to flow if needed
  3621. if (isDefined(args.to)) {
  3622. length = 0;
  3623. to = $$.isTimeSeries() ? $$.parseDate(args.to) : args.to;
  3624. baseTarget.values.forEach(function (v) {
  3625. if (v.x < to) {
  3626. length++;
  3627. }
  3628. });
  3629. } else if (isDefined(args.length)) {
  3630. length = args.length;
  3631. } // If only one data, update the domain to flow from left edge of the chart
  3632. if (!orgDataCount) {
  3633. if ($$.isTimeSeries()) {
  3634. if (baseTarget.values.length > 1) {
  3635. diff = baseTarget.values[baseTarget.values.length - 1].x - baseValue.x;
  3636. } else {
  3637. diff = baseValue.x - $$.getXDomain($$.data.targets)[0];
  3638. }
  3639. } else {
  3640. diff = 1;
  3641. }
  3642. domain = [baseValue.x - diff, baseValue.x];
  3643. $$.updateXDomain(null, true, true, false, domain);
  3644. } else if (orgDataCount === 1) {
  3645. if ($$.isTimeSeries()) {
  3646. diff = (baseTarget.values[baseTarget.values.length - 1].x - baseValue.x) / 2;
  3647. domain = [new Date(+baseValue.x - diff), new Date(+baseValue.x + diff)];
  3648. $$.updateXDomain(null, true, true, false, domain);
  3649. }
  3650. } // Set targets
  3651. $$.updateTargets($$.data.targets); // Redraw with new targets
  3652. $$.redraw({
  3653. flow: {
  3654. index: baseValue.index,
  3655. length: length,
  3656. duration: isValue(args.duration) ? args.duration : $$.config.transition_duration,
  3657. done: args.done,
  3658. orgDataCount: orgDataCount
  3659. },
  3660. withLegend: true,
  3661. withTransition: orgDataCount > 1,
  3662. withTrimXDomain: false,
  3663. withUpdateXAxis: true
  3664. });
  3665. };
  3666. ChartInternal.prototype.generateFlow = function (args) {
  3667. var $$ = this,
  3668. config = $$.config,
  3669. d3 = $$.d3;
  3670. return function () {
  3671. var targets = args.targets,
  3672. flow = args.flow,
  3673. drawBar = args.drawBar,
  3674. drawLine = args.drawLine,
  3675. drawArea = args.drawArea,
  3676. cx = args.cx,
  3677. cy = args.cy,
  3678. xv = args.xv,
  3679. xForText = args.xForText,
  3680. yForText = args.yForText,
  3681. duration = args.duration;
  3682. var translateX,
  3683. scaleX = 1,
  3684. transform,
  3685. flowIndex = flow.index,
  3686. flowLength = flow.length,
  3687. flowStart = $$.getValueOnIndex($$.data.targets[0].values, flowIndex),
  3688. flowEnd = $$.getValueOnIndex($$.data.targets[0].values, flowIndex + flowLength),
  3689. orgDomain = $$.x.domain(),
  3690. domain,
  3691. durationForFlow = flow.duration || duration,
  3692. done = flow.done || function () {},
  3693. wait = $$.generateWait();
  3694. var xgrid, xgridLines, mainRegion, mainText, mainBar, mainLine, mainArea, mainCircle; // set flag
  3695. $$.flowing = true; // remove head data after rendered
  3696. $$.data.targets.forEach(function (d) {
  3697. d.values.splice(0, flowLength);
  3698. }); // update x domain to generate axis elements for flow
  3699. domain = $$.updateXDomain(targets, true, true); // update elements related to x scale
  3700. if ($$.updateXGrid) {
  3701. $$.updateXGrid(true);
  3702. }
  3703. xgrid = $$.xgrid || d3.selectAll([]); // xgrid needs to be obtained after updateXGrid
  3704. xgridLines = $$.xgridLines || d3.selectAll([]);
  3705. mainRegion = $$.mainRegion || d3.selectAll([]);
  3706. mainText = $$.mainText || d3.selectAll([]);
  3707. mainBar = $$.mainBar || d3.selectAll([]);
  3708. mainLine = $$.mainLine || d3.selectAll([]);
  3709. mainArea = $$.mainArea || d3.selectAll([]);
  3710. mainCircle = $$.mainCircle || d3.selectAll([]); // generate transform to flow
  3711. if (!flow.orgDataCount) {
  3712. // if empty
  3713. if ($$.data.targets[0].values.length !== 1) {
  3714. translateX = $$.x(orgDomain[0]) - $$.x(domain[0]);
  3715. } else {
  3716. if ($$.isTimeSeries()) {
  3717. flowStart = $$.getValueOnIndex($$.data.targets[0].values, 0);
  3718. flowEnd = $$.getValueOnIndex($$.data.targets[0].values, $$.data.targets[0].values.length - 1);
  3719. translateX = $$.x(flowStart.x) - $$.x(flowEnd.x);
  3720. } else {
  3721. translateX = diffDomain(domain) / 2;
  3722. }
  3723. }
  3724. } else if (flow.orgDataCount === 1 || (flowStart && flowStart.x) === (flowEnd && flowEnd.x)) {
  3725. translateX = $$.x(orgDomain[0]) - $$.x(domain[0]);
  3726. } else {
  3727. if ($$.isTimeSeries()) {
  3728. translateX = $$.x(orgDomain[0]) - $$.x(domain[0]);
  3729. } else {
  3730. translateX = $$.x(flowStart.x) - $$.x(flowEnd.x);
  3731. }
  3732. }
  3733. scaleX = diffDomain(orgDomain) / diffDomain(domain);
  3734. transform = 'translate(' + translateX + ',0) scale(' + scaleX + ',1)';
  3735. $$.hideXGridFocus();
  3736. var flowTransition = d3.transition().ease(d3.easeLinear).duration(durationForFlow);
  3737. wait.add($$.xAxis($$.axes.x, flowTransition));
  3738. wait.add(mainBar.transition(flowTransition).attr('transform', transform));
  3739. wait.add(mainLine.transition(flowTransition).attr('transform', transform));
  3740. wait.add(mainArea.transition(flowTransition).attr('transform', transform));
  3741. wait.add(mainCircle.transition(flowTransition).attr('transform', transform));
  3742. wait.add(mainText.transition(flowTransition).attr('transform', transform));
  3743. wait.add(mainRegion.filter($$.isRegionOnX).transition(flowTransition).attr('transform', transform));
  3744. wait.add(xgrid.transition(flowTransition).attr('transform', transform));
  3745. wait.add(xgridLines.transition(flowTransition).attr('transform', transform));
  3746. wait(function () {
  3747. var i,
  3748. shapes = [],
  3749. texts = []; // remove flowed elements
  3750. if (flowLength) {
  3751. for (i = 0; i < flowLength; i++) {
  3752. shapes.push('.' + CLASS.shape + '-' + (flowIndex + i));
  3753. texts.push('.' + CLASS.text + '-' + (flowIndex + i));
  3754. }
  3755. $$.svg.selectAll('.' + CLASS.shapes).selectAll(shapes).remove();
  3756. $$.svg.selectAll('.' + CLASS.texts).selectAll(texts).remove();
  3757. $$.svg.select('.' + CLASS.xgrid).remove();
  3758. } // draw again for removing flowed elements and reverting attr
  3759. xgrid.attr('transform', null).attr('x1', $$.xgridAttr.x1).attr('x2', $$.xgridAttr.x2).attr('y1', $$.xgridAttr.y1).attr('y2', $$.xgridAttr.y2).style("opacity", $$.xgridAttr.opacity);
  3760. xgridLines.attr('transform', null);
  3761. xgridLines.select('line').attr("x1", config.axis_rotated ? 0 : xv).attr("x2", config.axis_rotated ? $$.width : xv);
  3762. xgridLines.select('text').attr("x", config.axis_rotated ? $$.width : 0).attr("y", xv);
  3763. mainBar.attr('transform', null).attr("d", drawBar);
  3764. mainLine.attr('transform', null).attr("d", drawLine);
  3765. mainArea.attr('transform', null).attr("d", drawArea);
  3766. mainCircle.attr('transform', null).attr("cx", cx).attr("cy", cy);
  3767. mainText.attr('transform', null).attr('x', xForText).attr('y', yForText).style('fill-opacity', $$.opacityForText.bind($$));
  3768. mainRegion.attr('transform', null);
  3769. mainRegion.filter($$.isRegionOnX).attr("x", $$.regionX.bind($$)).attr("width", $$.regionWidth.bind($$)); // callback for end of flow
  3770. done();
  3771. $$.flowing = false;
  3772. });
  3773. };
  3774. };
  3775. Chart.prototype.focus = function (targetIds) {
  3776. var $$ = this.internal,
  3777. candidates;
  3778. targetIds = $$.mapToTargetIds(targetIds);
  3779. candidates = $$.svg.selectAll($$.selectorTargets(targetIds.filter($$.isTargetToShow, $$))), this.revert();
  3780. this.defocus();
  3781. candidates.classed(CLASS.focused, true).classed(CLASS.defocused, false);
  3782. if ($$.hasArcType()) {
  3783. $$.expandArc(targetIds);
  3784. }
  3785. $$.toggleFocusLegend(targetIds, true);
  3786. $$.focusedTargetIds = targetIds;
  3787. $$.defocusedTargetIds = $$.defocusedTargetIds.filter(function (id) {
  3788. return targetIds.indexOf(id) < 0;
  3789. });
  3790. };
  3791. Chart.prototype.defocus = function (targetIds) {
  3792. var $$ = this.internal,
  3793. candidates;
  3794. targetIds = $$.mapToTargetIds(targetIds);
  3795. candidates = $$.svg.selectAll($$.selectorTargets(targetIds.filter($$.isTargetToShow, $$))), candidates.classed(CLASS.focused, false).classed(CLASS.defocused, true);
  3796. if ($$.hasArcType()) {
  3797. $$.unexpandArc(targetIds);
  3798. }
  3799. $$.toggleFocusLegend(targetIds, false);
  3800. $$.focusedTargetIds = $$.focusedTargetIds.filter(function (id) {
  3801. return targetIds.indexOf(id) < 0;
  3802. });
  3803. $$.defocusedTargetIds = targetIds;
  3804. };
  3805. Chart.prototype.revert = function (targetIds) {
  3806. var $$ = this.internal,
  3807. candidates;
  3808. targetIds = $$.mapToTargetIds(targetIds);
  3809. candidates = $$.svg.selectAll($$.selectorTargets(targetIds)); // should be for all targets
  3810. candidates.classed(CLASS.focused, false).classed(CLASS.defocused, false);
  3811. if ($$.hasArcType()) {
  3812. $$.unexpandArc(targetIds);
  3813. }
  3814. if ($$.config.legend_show) {
  3815. $$.showLegend(targetIds.filter($$.isLegendToShow.bind($$)));
  3816. $$.legend.selectAll($$.selectorLegends(targetIds)).filter(function () {
  3817. return $$.d3.select(this).classed(CLASS.legendItemFocused);
  3818. }).classed(CLASS.legendItemFocused, false);
  3819. }
  3820. $$.focusedTargetIds = [];
  3821. $$.defocusedTargetIds = [];
  3822. };
  3823. Chart.prototype.xgrids = function (grids) {
  3824. var $$ = this.internal,
  3825. config = $$.config;
  3826. if (!grids) {
  3827. return config.grid_x_lines;
  3828. }
  3829. config.grid_x_lines = grids;
  3830. $$.redrawWithoutRescale();
  3831. return config.grid_x_lines;
  3832. };
  3833. Chart.prototype.xgrids.add = function (grids) {
  3834. var $$ = this.internal;
  3835. return this.xgrids($$.config.grid_x_lines.concat(grids ? grids : []));
  3836. };
  3837. Chart.prototype.xgrids.remove = function (params) {
  3838. // TODO: multiple
  3839. var $$ = this.internal;
  3840. $$.removeGridLines(params, true);
  3841. };
  3842. Chart.prototype.ygrids = function (grids) {
  3843. var $$ = this.internal,
  3844. config = $$.config;
  3845. if (!grids) {
  3846. return config.grid_y_lines;
  3847. }
  3848. config.grid_y_lines = grids;
  3849. $$.redrawWithoutRescale();
  3850. return config.grid_y_lines;
  3851. };
  3852. Chart.prototype.ygrids.add = function (grids) {
  3853. var $$ = this.internal;
  3854. return this.ygrids($$.config.grid_y_lines.concat(grids ? grids : []));
  3855. };
  3856. Chart.prototype.ygrids.remove = function (params) {
  3857. // TODO: multiple
  3858. var $$ = this.internal;
  3859. $$.removeGridLines(params, false);
  3860. };
  3861. Chart.prototype.groups = function (groups) {
  3862. var $$ = this.internal,
  3863. config = $$.config;
  3864. if (isUndefined(groups)) {
  3865. return config.data_groups;
  3866. }
  3867. config.data_groups = groups;
  3868. $$.redraw();
  3869. return config.data_groups;
  3870. };
  3871. Chart.prototype.legend = function () {};
  3872. Chart.prototype.legend.show = function (targetIds) {
  3873. var $$ = this.internal;
  3874. $$.showLegend($$.mapToTargetIds(targetIds));
  3875. $$.updateAndRedraw({
  3876. withLegend: true
  3877. });
  3878. };
  3879. Chart.prototype.legend.hide = function (targetIds) {
  3880. var $$ = this.internal;
  3881. $$.hideLegend($$.mapToTargetIds(targetIds));
  3882. $$.updateAndRedraw({
  3883. withLegend: false
  3884. });
  3885. };
  3886. Chart.prototype.load = function (args) {
  3887. var $$ = this.internal,
  3888. config = $$.config; // update xs if specified
  3889. if (args.xs) {
  3890. $$.addXs(args.xs);
  3891. } // update names if exists
  3892. if ('names' in args) {
  3893. Chart.prototype.data.names.bind(this)(args.names);
  3894. } // update classes if exists
  3895. if ('classes' in args) {
  3896. Object.keys(args.classes).forEach(function (id) {
  3897. config.data_classes[id] = args.classes[id];
  3898. });
  3899. } // update categories if exists
  3900. if ('categories' in args && $$.isCategorized()) {
  3901. config.axis_x_categories = args.categories;
  3902. } // update axes if exists
  3903. if ('axes' in args) {
  3904. Object.keys(args.axes).forEach(function (id) {
  3905. config.data_axes[id] = args.axes[id];
  3906. });
  3907. } // update colors if exists
  3908. if ('colors' in args) {
  3909. Object.keys(args.colors).forEach(function (id) {
  3910. config.data_colors[id] = args.colors[id];
  3911. });
  3912. } // use cache if exists
  3913. if ('cacheIds' in args && $$.hasCaches(args.cacheIds)) {
  3914. $$.load($$.getCaches(args.cacheIds), args.done);
  3915. return;
  3916. } // unload if needed
  3917. if ('unload' in args) {
  3918. // TODO: do not unload if target will load (included in url/rows/columns)
  3919. $$.unload($$.mapToTargetIds(typeof args.unload === 'boolean' && args.unload ? null : args.unload), function () {
  3920. $$.loadFromArgs(args);
  3921. });
  3922. } else {
  3923. $$.loadFromArgs(args);
  3924. }
  3925. };
  3926. Chart.prototype.unload = function (args) {
  3927. var $$ = this.internal;
  3928. args = args || {};
  3929. if (args instanceof Array) {
  3930. args = {
  3931. ids: args
  3932. };
  3933. } else if (typeof args === 'string') {
  3934. args = {
  3935. ids: [args]
  3936. };
  3937. }
  3938. $$.unload($$.mapToTargetIds(args.ids), function () {
  3939. $$.redraw({
  3940. withUpdateOrgXDomain: true,
  3941. withUpdateXDomain: true,
  3942. withLegend: true
  3943. });
  3944. if (args.done) {
  3945. args.done();
  3946. }
  3947. });
  3948. };
  3949. Chart.prototype.regions = function (regions) {
  3950. var $$ = this.internal,
  3951. config = $$.config;
  3952. if (!regions) {
  3953. return config.regions;
  3954. }
  3955. config.regions = regions;
  3956. $$.redrawWithoutRescale();
  3957. return config.regions;
  3958. };
  3959. Chart.prototype.regions.add = function (regions) {
  3960. var $$ = this.internal,
  3961. config = $$.config;
  3962. if (!regions) {
  3963. return config.regions;
  3964. }
  3965. config.regions = config.regions.concat(regions);
  3966. $$.redrawWithoutRescale();
  3967. return config.regions;
  3968. };
  3969. Chart.prototype.regions.remove = function (options) {
  3970. var $$ = this.internal,
  3971. config = $$.config,
  3972. duration,
  3973. classes,
  3974. regions;
  3975. options = options || {};
  3976. duration = $$.getOption(options, "duration", config.transition_duration);
  3977. classes = $$.getOption(options, "classes", [CLASS.region]);
  3978. regions = $$.main.select('.' + CLASS.regions).selectAll(classes.map(function (c) {
  3979. return '.' + c;
  3980. }));
  3981. (duration ? regions.transition().duration(duration) : regions).style('opacity', 0).remove();
  3982. config.regions = config.regions.filter(function (region) {
  3983. var found = false;
  3984. if (!region['class']) {
  3985. return true;
  3986. }
  3987. region['class'].split(' ').forEach(function (c) {
  3988. if (classes.indexOf(c) >= 0) {
  3989. found = true;
  3990. }
  3991. });
  3992. return !found;
  3993. });
  3994. return config.regions;
  3995. };
  3996. Chart.prototype.selected = function (targetId) {
  3997. var $$ = this.internal,
  3998. d3 = $$.d3;
  3999. return d3.merge($$.main.selectAll('.' + CLASS.shapes + $$.getTargetSelectorSuffix(targetId)).selectAll('.' + CLASS.shape).filter(function () {
  4000. return d3.select(this).classed(CLASS.SELECTED);
  4001. }).map(function (d) {
  4002. return d.map(function (d) {
  4003. var data = d.__data__;
  4004. return data.data ? data.data : data;
  4005. });
  4006. }));
  4007. };
  4008. Chart.prototype.select = function (ids, indices, resetOther) {
  4009. var $$ = this.internal,
  4010. d3 = $$.d3,
  4011. config = $$.config;
  4012. if (!config.data_selection_enabled) {
  4013. return;
  4014. }
  4015. $$.main.selectAll('.' + CLASS.shapes).selectAll('.' + CLASS.shape).each(function (d, i) {
  4016. var shape = d3.select(this),
  4017. id = d.data ? d.data.id : d.id,
  4018. toggle = $$.getToggle(this, d).bind($$),
  4019. isTargetId = config.data_selection_grouped || !ids || ids.indexOf(id) >= 0,
  4020. isTargetIndex = !indices || indices.indexOf(i) >= 0,
  4021. isSelected = shape.classed(CLASS.SELECTED); // line/area selection not supported yet
  4022. if (shape.classed(CLASS.line) || shape.classed(CLASS.area)) {
  4023. return;
  4024. }
  4025. if (isTargetId && isTargetIndex) {
  4026. if (config.data_selection_isselectable(d) && !isSelected) {
  4027. toggle(true, shape.classed(CLASS.SELECTED, true), d, i);
  4028. }
  4029. } else if (isDefined(resetOther) && resetOther) {
  4030. if (isSelected) {
  4031. toggle(false, shape.classed(CLASS.SELECTED, false), d, i);
  4032. }
  4033. }
  4034. });
  4035. };
  4036. Chart.prototype.unselect = function (ids, indices) {
  4037. var $$ = this.internal,
  4038. d3 = $$.d3,
  4039. config = $$.config;
  4040. if (!config.data_selection_enabled) {
  4041. return;
  4042. }
  4043. $$.main.selectAll('.' + CLASS.shapes).selectAll('.' + CLASS.shape).each(function (d, i) {
  4044. var shape = d3.select(this),
  4045. id = d.data ? d.data.id : d.id,
  4046. toggle = $$.getToggle(this, d).bind($$),
  4047. isTargetId = config.data_selection_grouped || !ids || ids.indexOf(id) >= 0,
  4048. isTargetIndex = !indices || indices.indexOf(i) >= 0,
  4049. isSelected = shape.classed(CLASS.SELECTED); // line/area selection not supported yet
  4050. if (shape.classed(CLASS.line) || shape.classed(CLASS.area)) {
  4051. return;
  4052. }
  4053. if (isTargetId && isTargetIndex) {
  4054. if (config.data_selection_isselectable(d)) {
  4055. if (isSelected) {
  4056. toggle(false, shape.classed(CLASS.SELECTED, false), d, i);
  4057. }
  4058. }
  4059. }
  4060. });
  4061. };
  4062. Chart.prototype.show = function (targetIds, options) {
  4063. var $$ = this.internal,
  4064. targets;
  4065. targetIds = $$.mapToTargetIds(targetIds);
  4066. options = options || {};
  4067. $$.removeHiddenTargetIds(targetIds);
  4068. targets = $$.svg.selectAll($$.selectorTargets(targetIds));
  4069. targets.transition().style('display', 'initial', 'important').style('opacity', 1, 'important').call($$.endall, function () {
  4070. targets.style('opacity', null).style('opacity', 1);
  4071. });
  4072. if (options.withLegend) {
  4073. $$.showLegend(targetIds);
  4074. }
  4075. $$.redraw({
  4076. withUpdateOrgXDomain: true,
  4077. withUpdateXDomain: true,
  4078. withLegend: true
  4079. });
  4080. };
  4081. Chart.prototype.hide = function (targetIds, options) {
  4082. var $$ = this.internal,
  4083. targets;
  4084. targetIds = $$.mapToTargetIds(targetIds);
  4085. options = options || {};
  4086. $$.addHiddenTargetIds(targetIds);
  4087. targets = $$.svg.selectAll($$.selectorTargets(targetIds));
  4088. targets.transition().style('opacity', 0, 'important').call($$.endall, function () {
  4089. targets.style('opacity', null).style('opacity', 0);
  4090. targets.style('display', 'none');
  4091. });
  4092. if (options.withLegend) {
  4093. $$.hideLegend(targetIds);
  4094. }
  4095. $$.redraw({
  4096. withUpdateOrgXDomain: true,
  4097. withUpdateXDomain: true,
  4098. withLegend: true
  4099. });
  4100. };
  4101. Chart.prototype.toggle = function (targetIds, options) {
  4102. var that = this,
  4103. $$ = this.internal;
  4104. $$.mapToTargetIds(targetIds).forEach(function (targetId) {
  4105. $$.isTargetToShow(targetId) ? that.hide(targetId, options) : that.show(targetId, options);
  4106. });
  4107. };
  4108. Chart.prototype.tooltip = function () {};
  4109. Chart.prototype.tooltip.show = function (args) {
  4110. var $$ = this.internal,
  4111. targets,
  4112. data,
  4113. mouse = {}; // determine mouse position on the chart
  4114. if (args.mouse) {
  4115. mouse = args.mouse;
  4116. } else {
  4117. // determine focus data
  4118. if (args.data) {
  4119. data = args.data;
  4120. } else if (typeof args.x !== 'undefined') {
  4121. if (args.id) {
  4122. targets = $$.data.targets.filter(function (t) {
  4123. return t.id === args.id;
  4124. });
  4125. } else {
  4126. targets = $$.data.targets;
  4127. }
  4128. data = $$.filterByX(targets, args.x).slice(0, 1)[0];
  4129. }
  4130. mouse = data ? $$.getMousePosition(data) : null;
  4131. } // emulate mouse events to show
  4132. $$.dispatchEvent('mousemove', mouse);
  4133. $$.config.tooltip_onshow.call($$, data);
  4134. };
  4135. Chart.prototype.tooltip.hide = function () {
  4136. // TODO: get target data by checking the state of focus
  4137. this.internal.dispatchEvent('mouseout', 0);
  4138. this.internal.config.tooltip_onhide.call(this);
  4139. };
  4140. Chart.prototype.transform = function (type, targetIds) {
  4141. var $$ = this.internal,
  4142. options = ['pie', 'donut'].indexOf(type) >= 0 ? {
  4143. withTransform: true
  4144. } : null;
  4145. $$.transformTo(targetIds, type, options);
  4146. };
  4147. ChartInternal.prototype.transformTo = function (targetIds, type, optionsForRedraw) {
  4148. var $$ = this,
  4149. withTransitionForAxis = !$$.hasArcType(),
  4150. options = optionsForRedraw || {
  4151. withTransitionForAxis: withTransitionForAxis
  4152. };
  4153. options.withTransitionForTransform = false;
  4154. $$.transiting = false;
  4155. $$.setTargetType(targetIds, type);
  4156. $$.updateTargets($$.data.targets); // this is needed when transforming to arc
  4157. $$.updateAndRedraw(options);
  4158. };
  4159. Chart.prototype.x = function (x) {
  4160. var $$ = this.internal;
  4161. if (arguments.length) {
  4162. $$.updateTargetX($$.data.targets, x);
  4163. $$.redraw({
  4164. withUpdateOrgXDomain: true,
  4165. withUpdateXDomain: true
  4166. });
  4167. }
  4168. return $$.data.xs;
  4169. };
  4170. Chart.prototype.xs = function (xs) {
  4171. var $$ = this.internal;
  4172. if (arguments.length) {
  4173. $$.updateTargetXs($$.data.targets, xs);
  4174. $$.redraw({
  4175. withUpdateOrgXDomain: true,
  4176. withUpdateXDomain: true
  4177. });
  4178. }
  4179. return $$.data.xs;
  4180. };
  4181. Chart.prototype.zoom = function (domain) {
  4182. var $$ = this.internal;
  4183. if (domain) {
  4184. if ($$.isTimeSeries()) {
  4185. domain = domain.map(function (x) {
  4186. return $$.parseDate(x);
  4187. });
  4188. }
  4189. if ($$.config.subchart_show) {
  4190. $$.brush.selectionAsValue(domain, true);
  4191. } else {
  4192. $$.updateXDomain(null, true, false, false, domain);
  4193. $$.redraw({
  4194. withY: $$.config.zoom_rescale,
  4195. withSubchart: false
  4196. });
  4197. }
  4198. $$.config.zoom_onzoom.call(this, $$.x.orgDomain());
  4199. return domain;
  4200. } else {
  4201. return $$.x.domain();
  4202. }
  4203. };
  4204. Chart.prototype.zoom.enable = function (enabled) {
  4205. var $$ = this.internal;
  4206. $$.config.zoom_enabled = enabled;
  4207. $$.updateAndRedraw();
  4208. };
  4209. Chart.prototype.unzoom = function () {
  4210. var $$ = this.internal;
  4211. if ($$.config.subchart_show) {
  4212. $$.brush.clear();
  4213. } else {
  4214. $$.updateXDomain(null, true, false, false, $$.subX.domain());
  4215. $$.redraw({
  4216. withY: $$.config.zoom_rescale,
  4217. withSubchart: false
  4218. });
  4219. }
  4220. };
  4221. Chart.prototype.zoom.max = function (max) {
  4222. var $$ = this.internal,
  4223. config = $$.config,
  4224. d3 = $$.d3;
  4225. if (max === 0 || max) {
  4226. config.zoom_x_max = d3.max([$$.orgXDomain[1], max]);
  4227. } else {
  4228. return config.zoom_x_max;
  4229. }
  4230. };
  4231. Chart.prototype.zoom.min = function (min) {
  4232. var $$ = this.internal,
  4233. config = $$.config,
  4234. d3 = $$.d3;
  4235. if (min === 0 || min) {
  4236. config.zoom_x_min = d3.min([$$.orgXDomain[0], min]);
  4237. } else {
  4238. return config.zoom_x_min;
  4239. }
  4240. };
  4241. Chart.prototype.zoom.range = function (range) {
  4242. if (arguments.length) {
  4243. if (isDefined(range.max)) {
  4244. this.domain.max(range.max);
  4245. }
  4246. if (isDefined(range.min)) {
  4247. this.domain.min(range.min);
  4248. }
  4249. } else {
  4250. return {
  4251. max: this.domain.max(),
  4252. min: this.domain.min()
  4253. };
  4254. }
  4255. };
  4256. ChartInternal.prototype.initPie = function () {
  4257. var $$ = this,
  4258. d3 = $$.d3;
  4259. $$.pie = d3.pie().value(function (d) {
  4260. return d.values.reduce(function (a, b) {
  4261. return a + b.value;
  4262. }, 0);
  4263. });
  4264. var orderFct = $$.getOrderFunction(); // we need to reverse the returned order if asc or desc to have the slice in expected order.
  4265. if (orderFct && ($$.isOrderAsc() || $$.isOrderDesc())) {
  4266. var defaultSort = orderFct;
  4267. orderFct = function orderFct(t1, t2) {
  4268. return defaultSort(t1, t2) * -1;
  4269. };
  4270. }
  4271. $$.pie.sort(orderFct || null);
  4272. };
  4273. ChartInternal.prototype.updateRadius = function () {
  4274. var $$ = this,
  4275. config = $$.config,
  4276. w = config.gauge_width || config.donut_width,
  4277. gaugeArcWidth = $$.filterTargetsToShow($$.data.targets).length * $$.config.gauge_arcs_minWidth;
  4278. $$.radiusExpanded = Math.min($$.arcWidth, $$.arcHeight) / 2 * ($$.hasType('gauge') ? 0.85 : 1);
  4279. $$.radius = $$.radiusExpanded * 0.95;
  4280. $$.innerRadiusRatio = w ? ($$.radius - w) / $$.radius : 0.6;
  4281. $$.innerRadius = $$.hasType('donut') || $$.hasType('gauge') ? $$.radius * $$.innerRadiusRatio : 0;
  4282. $$.gaugeArcWidth = w ? w : gaugeArcWidth <= $$.radius - $$.innerRadius ? $$.radius - $$.innerRadius : gaugeArcWidth <= $$.radius ? gaugeArcWidth : $$.radius;
  4283. };
  4284. ChartInternal.prototype.updateArc = function () {
  4285. var $$ = this;
  4286. $$.svgArc = $$.getSvgArc();
  4287. $$.svgArcExpanded = $$.getSvgArcExpanded();
  4288. $$.svgArcExpandedSub = $$.getSvgArcExpanded(0.98);
  4289. };
  4290. ChartInternal.prototype.updateAngle = function (d) {
  4291. var $$ = this,
  4292. config = $$.config,
  4293. found = false,
  4294. index = 0,
  4295. gMin,
  4296. gMax,
  4297. gTic,
  4298. gValue;
  4299. if (!config) {
  4300. return null;
  4301. }
  4302. $$.pie($$.filterTargetsToShow($$.data.targets)).forEach(function (t) {
  4303. if (!found && t.data.id === d.data.id) {
  4304. found = true;
  4305. d = t;
  4306. d.index = index;
  4307. }
  4308. index++;
  4309. });
  4310. if (isNaN(d.startAngle)) {
  4311. d.startAngle = 0;
  4312. }
  4313. if (isNaN(d.endAngle)) {
  4314. d.endAngle = d.startAngle;
  4315. }
  4316. if ($$.isGaugeType(d.data)) {
  4317. gMin = config.gauge_min;
  4318. gMax = config.gauge_max;
  4319. gTic = Math.PI * (config.gauge_fullCircle ? 2 : 1) / (gMax - gMin);
  4320. gValue = d.value < gMin ? 0 : d.value < gMax ? d.value - gMin : gMax - gMin;
  4321. d.startAngle = config.gauge_startingAngle;
  4322. d.endAngle = d.startAngle + gTic * gValue;
  4323. }
  4324. return found ? d : null;
  4325. };
  4326. ChartInternal.prototype.getSvgArc = function () {
  4327. var $$ = this,
  4328. hasGaugeType = $$.hasType('gauge'),
  4329. singleArcWidth = $$.gaugeArcWidth / $$.filterTargetsToShow($$.data.targets).length,
  4330. arc = $$.d3.arc().outerRadius(function (d) {
  4331. return hasGaugeType ? $$.radius - singleArcWidth * d.index : $$.radius;
  4332. }).innerRadius(function (d) {
  4333. return hasGaugeType ? $$.radius - singleArcWidth * (d.index + 1) : $$.innerRadius;
  4334. }),
  4335. newArc = function newArc(d, withoutUpdate) {
  4336. var updated;
  4337. if (withoutUpdate) {
  4338. return arc(d);
  4339. } // for interpolate
  4340. updated = $$.updateAngle(d);
  4341. return updated ? arc(updated) : "M 0 0";
  4342. }; // TODO: extends all function
  4343. newArc.centroid = arc.centroid;
  4344. return newArc;
  4345. };
  4346. ChartInternal.prototype.getSvgArcExpanded = function (rate) {
  4347. rate = rate || 1;
  4348. var $$ = this,
  4349. hasGaugeType = $$.hasType('gauge'),
  4350. singleArcWidth = $$.gaugeArcWidth / $$.filterTargetsToShow($$.data.targets).length,
  4351. expandWidth = Math.min($$.radiusExpanded * rate - $$.radius, singleArcWidth * 0.8 - (1 - rate) * 100),
  4352. arc = $$.d3.arc().outerRadius(function (d) {
  4353. return hasGaugeType ? $$.radius - singleArcWidth * d.index + expandWidth : $$.radiusExpanded * rate;
  4354. }).innerRadius(function (d) {
  4355. return hasGaugeType ? $$.radius - singleArcWidth * (d.index + 1) : $$.innerRadius;
  4356. });
  4357. return function (d) {
  4358. var updated = $$.updateAngle(d);
  4359. return updated ? arc(updated) : "M 0 0";
  4360. };
  4361. };
  4362. ChartInternal.prototype.getArc = function (d, withoutUpdate, force) {
  4363. return force || this.isArcType(d.data) ? this.svgArc(d, withoutUpdate) : "M 0 0";
  4364. };
  4365. ChartInternal.prototype.transformForArcLabel = function (d) {
  4366. var $$ = this,
  4367. config = $$.config,
  4368. updated = $$.updateAngle(d),
  4369. c,
  4370. x,
  4371. y,
  4372. h,
  4373. ratio,
  4374. translate = "",
  4375. hasGauge = $$.hasType('gauge');
  4376. if (updated && !hasGauge) {
  4377. c = this.svgArc.centroid(updated);
  4378. x = isNaN(c[0]) ? 0 : c[0];
  4379. y = isNaN(c[1]) ? 0 : c[1];
  4380. h = Math.sqrt(x * x + y * y);
  4381. if ($$.hasType('donut') && config.donut_label_ratio) {
  4382. ratio = isFunction(config.donut_label_ratio) ? config.donut_label_ratio(d, $$.radius, h) : config.donut_label_ratio;
  4383. } else if ($$.hasType('pie') && config.pie_label_ratio) {
  4384. ratio = isFunction(config.pie_label_ratio) ? config.pie_label_ratio(d, $$.radius, h) : config.pie_label_ratio;
  4385. } else {
  4386. ratio = $$.radius && h ? (36 / $$.radius > 0.375 ? 1.175 - 36 / $$.radius : 0.8) * $$.radius / h : 0;
  4387. }
  4388. translate = "translate(" + x * ratio + ',' + y * ratio + ")";
  4389. } else if (updated && hasGauge && $$.filterTargetsToShow($$.data.targets).length > 1) {
  4390. var y1 = Math.sin(updated.endAngle - Math.PI / 2);
  4391. x = Math.cos(updated.endAngle - Math.PI / 2) * ($$.radiusExpanded + 25);
  4392. y = y1 * ($$.radiusExpanded + 15 - Math.abs(y1 * 10)) + 3;
  4393. translate = "translate(" + x + ',' + y + ")";
  4394. }
  4395. return translate;
  4396. };
  4397. ChartInternal.prototype.getArcRatio = function (d) {
  4398. var $$ = this,
  4399. config = $$.config,
  4400. whole = Math.PI * ($$.hasType('gauge') && !config.gauge_fullCircle ? 1 : 2);
  4401. return d ? (d.endAngle - d.startAngle) / whole : null;
  4402. };
  4403. ChartInternal.prototype.convertToArcData = function (d) {
  4404. return this.addName({
  4405. id: d.data.id,
  4406. value: d.value,
  4407. ratio: this.getArcRatio(d),
  4408. index: d.index
  4409. });
  4410. };
  4411. ChartInternal.prototype.textForArcLabel = function (d) {
  4412. var $$ = this,
  4413. updated,
  4414. value,
  4415. ratio,
  4416. id,
  4417. format;
  4418. if (!$$.shouldShowArcLabel()) {
  4419. return "";
  4420. }
  4421. updated = $$.updateAngle(d);
  4422. value = updated ? updated.value : null;
  4423. ratio = $$.getArcRatio(updated);
  4424. id = d.data.id;
  4425. if (!$$.hasType('gauge') && !$$.meetsArcLabelThreshold(ratio)) {
  4426. return "";
  4427. }
  4428. format = $$.getArcLabelFormat();
  4429. return format ? format(value, ratio, id) : $$.defaultArcValueFormat(value, ratio);
  4430. };
  4431. ChartInternal.prototype.textForGaugeMinMax = function (value, isMax) {
  4432. var $$ = this,
  4433. format = $$.getGaugeLabelExtents();
  4434. return format ? format(value, isMax) : value;
  4435. };
  4436. ChartInternal.prototype.expandArc = function (targetIds) {
  4437. var $$ = this,
  4438. interval; // MEMO: avoid to cancel transition
  4439. if ($$.transiting) {
  4440. interval = window.setInterval(function () {
  4441. if (!$$.transiting) {
  4442. window.clearInterval(interval);
  4443. if ($$.legend.selectAll('.c3-legend-item-focused').size() > 0) {
  4444. $$.expandArc(targetIds);
  4445. }
  4446. }
  4447. }, 10);
  4448. return;
  4449. }
  4450. targetIds = $$.mapToTargetIds(targetIds);
  4451. $$.svg.selectAll($$.selectorTargets(targetIds, '.' + CLASS.chartArc)).each(function (d) {
  4452. if (!$$.shouldExpand(d.data.id)) {
  4453. return;
  4454. }
  4455. $$.d3.select(this).selectAll('path').transition().duration($$.expandDuration(d.data.id)).attr("d", $$.svgArcExpanded).transition().duration($$.expandDuration(d.data.id) * 2).attr("d", $$.svgArcExpandedSub).each(function (d) {
  4456. if ($$.isDonutType(d.data)) ;
  4457. });
  4458. });
  4459. };
  4460. ChartInternal.prototype.unexpandArc = function (targetIds) {
  4461. var $$ = this;
  4462. if ($$.transiting) {
  4463. return;
  4464. }
  4465. targetIds = $$.mapToTargetIds(targetIds);
  4466. $$.svg.selectAll($$.selectorTargets(targetIds, '.' + CLASS.chartArc)).selectAll('path').transition().duration(function (d) {
  4467. return $$.expandDuration(d.data.id);
  4468. }).attr("d", $$.svgArc);
  4469. $$.svg.selectAll('.' + CLASS.arc);
  4470. };
  4471. ChartInternal.prototype.expandDuration = function (id) {
  4472. var $$ = this,
  4473. config = $$.config;
  4474. if ($$.isDonutType(id)) {
  4475. return config.donut_expand_duration;
  4476. } else if ($$.isGaugeType(id)) {
  4477. return config.gauge_expand_duration;
  4478. } else if ($$.isPieType(id)) {
  4479. return config.pie_expand_duration;
  4480. } else {
  4481. return 50;
  4482. }
  4483. };
  4484. ChartInternal.prototype.shouldExpand = function (id) {
  4485. var $$ = this,
  4486. config = $$.config;
  4487. return $$.isDonutType(id) && config.donut_expand || $$.isGaugeType(id) && config.gauge_expand || $$.isPieType(id) && config.pie_expand;
  4488. };
  4489. ChartInternal.prototype.shouldShowArcLabel = function () {
  4490. var $$ = this,
  4491. config = $$.config,
  4492. shouldShow = true;
  4493. if ($$.hasType('donut')) {
  4494. shouldShow = config.donut_label_show;
  4495. } else if ($$.hasType('pie')) {
  4496. shouldShow = config.pie_label_show;
  4497. } // when gauge, always true
  4498. return shouldShow;
  4499. };
  4500. ChartInternal.prototype.meetsArcLabelThreshold = function (ratio) {
  4501. var $$ = this,
  4502. config = $$.config,
  4503. threshold = $$.hasType('donut') ? config.donut_label_threshold : config.pie_label_threshold;
  4504. return ratio >= threshold;
  4505. };
  4506. ChartInternal.prototype.getArcLabelFormat = function () {
  4507. var $$ = this,
  4508. config = $$.config,
  4509. format = config.pie_label_format;
  4510. if ($$.hasType('gauge')) {
  4511. format = config.gauge_label_format;
  4512. } else if ($$.hasType('donut')) {
  4513. format = config.donut_label_format;
  4514. }
  4515. return format;
  4516. };
  4517. ChartInternal.prototype.getGaugeLabelExtents = function () {
  4518. var $$ = this,
  4519. config = $$.config;
  4520. return config.gauge_label_extents;
  4521. };
  4522. ChartInternal.prototype.getArcTitle = function () {
  4523. var $$ = this;
  4524. return $$.hasType('donut') ? $$.config.donut_title : "";
  4525. };
  4526. ChartInternal.prototype.updateTargetsForArc = function (targets) {
  4527. var $$ = this,
  4528. main = $$.main,
  4529. mainPies,
  4530. mainPieEnter,
  4531. classChartArc = $$.classChartArc.bind($$),
  4532. classArcs = $$.classArcs.bind($$),
  4533. classFocus = $$.classFocus.bind($$);
  4534. mainPies = main.select('.' + CLASS.chartArcs).selectAll('.' + CLASS.chartArc).data($$.pie(targets)).attr("class", function (d) {
  4535. return classChartArc(d) + classFocus(d.data);
  4536. });
  4537. mainPieEnter = mainPies.enter().append("g").attr("class", classChartArc);
  4538. mainPieEnter.append('g').attr('class', classArcs);
  4539. mainPieEnter.append("text").attr("dy", $$.hasType('gauge') ? "-.1em" : ".35em").style("opacity", 0).style("text-anchor", "middle").style("pointer-events", "none"); // MEMO: can not keep same color..., but not bad to update color in redraw
  4540. //mainPieUpdate.exit().remove();
  4541. };
  4542. ChartInternal.prototype.initArc = function () {
  4543. var $$ = this;
  4544. $$.arcs = $$.main.select('.' + CLASS.chart).append("g").attr("class", CLASS.chartArcs).attr("transform", $$.getTranslate('arc'));
  4545. $$.arcs.append('text').attr('class', CLASS.chartArcsTitle).style("text-anchor", "middle").text($$.getArcTitle());
  4546. };
  4547. ChartInternal.prototype.redrawArc = function (duration, durationForExit, withTransform) {
  4548. var $$ = this,
  4549. d3 = $$.d3,
  4550. config = $$.config,
  4551. main = $$.main,
  4552. arcs,
  4553. mainArc,
  4554. arcLabelLines,
  4555. mainArcLabelLine,
  4556. hasGaugeType = $$.hasType('gauge');
  4557. arcs = main.selectAll('.' + CLASS.arcs).selectAll('.' + CLASS.arc).data($$.arcData.bind($$));
  4558. mainArc = arcs.enter().append('path').attr("class", $$.classArc.bind($$)).style("fill", function (d) {
  4559. return $$.color(d.data);
  4560. }).style("cursor", function (d) {
  4561. return config.interaction_enabled && config.data_selection_isselectable(d) ? "pointer" : null;
  4562. }).each(function (d) {
  4563. if ($$.isGaugeType(d.data)) {
  4564. d.startAngle = d.endAngle = config.gauge_startingAngle;
  4565. }
  4566. this._current = d;
  4567. }).merge(arcs);
  4568. if (hasGaugeType) {
  4569. arcLabelLines = main.selectAll('.' + CLASS.arcs).selectAll('.' + CLASS.arcLabelLine).data($$.arcData.bind($$));
  4570. mainArcLabelLine = arcLabelLines.enter().append('rect').attr("class", function (d) {
  4571. return CLASS.arcLabelLine + ' ' + CLASS.target + ' ' + CLASS.target + '-' + d.data.id;
  4572. }).merge(arcLabelLines);
  4573. if ($$.filterTargetsToShow($$.data.targets).length === 1) {
  4574. mainArcLabelLine.style("display", "none");
  4575. } else {
  4576. mainArcLabelLine.style("fill", function (d) {
  4577. return config.color_pattern.length > 0 ? $$.levelColor(d.data.values[0].value) : $$.color(d.data);
  4578. }).style("display", config.gauge_labelLine_show ? "" : "none").each(function (d) {
  4579. var lineLength = 0,
  4580. lineThickness = 2,
  4581. x = 0,
  4582. y = 0,
  4583. transform = "";
  4584. if ($$.hiddenTargetIds.indexOf(d.data.id) < 0) {
  4585. var updated = $$.updateAngle(d),
  4586. innerLineLength = $$.gaugeArcWidth / $$.filterTargetsToShow($$.data.targets).length * (updated.index + 1),
  4587. lineAngle = updated.endAngle - Math.PI / 2,
  4588. arcInnerRadius = $$.radius - innerLineLength,
  4589. linePositioningAngle = lineAngle - (arcInnerRadius === 0 ? 0 : 1 / arcInnerRadius);
  4590. lineLength = $$.radiusExpanded - $$.radius + innerLineLength;
  4591. x = Math.cos(linePositioningAngle) * arcInnerRadius;
  4592. y = Math.sin(linePositioningAngle) * arcInnerRadius;
  4593. transform = "rotate(" + lineAngle * 180 / Math.PI + ", " + x + ", " + y + ")";
  4594. }
  4595. d3.select(this).attr('x', x).attr('y', y).attr('width', lineLength).attr('height', lineThickness).attr('transform', transform).style("stroke-dasharray", "0, " + (lineLength + lineThickness) + ", 0");
  4596. });
  4597. }
  4598. }
  4599. mainArc.attr("transform", function (d) {
  4600. return !$$.isGaugeType(d.data) && withTransform ? "scale(0)" : "";
  4601. }).on('mouseover', config.interaction_enabled ? function (d) {
  4602. var updated, arcData;
  4603. if ($$.transiting) {
  4604. // skip while transiting
  4605. return;
  4606. }
  4607. updated = $$.updateAngle(d);
  4608. if (updated) {
  4609. arcData = $$.convertToArcData(updated); // transitions
  4610. $$.expandArc(updated.data.id);
  4611. $$.api.focus(updated.data.id);
  4612. $$.toggleFocusLegend(updated.data.id, true);
  4613. $$.config.data_onmouseover(arcData, this);
  4614. }
  4615. } : null).on('mousemove', config.interaction_enabled ? function (d) {
  4616. var updated = $$.updateAngle(d),
  4617. arcData,
  4618. selectedData;
  4619. if (updated) {
  4620. arcData = $$.convertToArcData(updated), selectedData = [arcData];
  4621. $$.showTooltip(selectedData, this);
  4622. }
  4623. } : null).on('mouseout', config.interaction_enabled ? function (d) {
  4624. var updated, arcData;
  4625. if ($$.transiting) {
  4626. // skip while transiting
  4627. return;
  4628. }
  4629. updated = $$.updateAngle(d);
  4630. if (updated) {
  4631. arcData = $$.convertToArcData(updated); // transitions
  4632. $$.unexpandArc(updated.data.id);
  4633. $$.api.revert();
  4634. $$.revertLegend();
  4635. $$.hideTooltip();
  4636. $$.config.data_onmouseout(arcData, this);
  4637. }
  4638. } : null).on('click', config.interaction_enabled ? function (d, i) {
  4639. var updated = $$.updateAngle(d),
  4640. arcData;
  4641. if (updated) {
  4642. arcData = $$.convertToArcData(updated);
  4643. if ($$.toggleShape) {
  4644. $$.toggleShape(this, arcData, i);
  4645. }
  4646. $$.config.data_onclick.call($$.api, arcData, this);
  4647. }
  4648. } : null).each(function () {
  4649. $$.transiting = true;
  4650. }).transition().duration(duration).attrTween("d", function (d) {
  4651. var updated = $$.updateAngle(d),
  4652. interpolate;
  4653. if (!updated) {
  4654. return function () {
  4655. return "M 0 0";
  4656. };
  4657. } // if (this._current === d) {
  4658. // this._current = {
  4659. // startAngle: Math.PI*2,
  4660. // endAngle: Math.PI*2,
  4661. // };
  4662. // }
  4663. if (isNaN(this._current.startAngle)) {
  4664. this._current.startAngle = 0;
  4665. }
  4666. if (isNaN(this._current.endAngle)) {
  4667. this._current.endAngle = this._current.startAngle;
  4668. }
  4669. interpolate = d3.interpolate(this._current, updated);
  4670. this._current = interpolate(0);
  4671. return function (t) {
  4672. var interpolated = interpolate(t);
  4673. interpolated.data = d.data; // data.id will be updated by interporator
  4674. return $$.getArc(interpolated, true);
  4675. };
  4676. }).attr("transform", withTransform ? "scale(1)" : "").style("fill", function (d) {
  4677. return $$.levelColor ? $$.levelColor(d.data.values[0].value) : $$.color(d.data.id);
  4678. }) // Where gauge reading color would receive customization.
  4679. .call($$.endall, function () {
  4680. $$.transiting = false;
  4681. });
  4682. arcs.exit().transition().duration(durationForExit).style('opacity', 0).remove();
  4683. main.selectAll('.' + CLASS.chartArc).select('text').style("opacity", 0).attr('class', function (d) {
  4684. return $$.isGaugeType(d.data) ? CLASS.gaugeValue : '';
  4685. }).text($$.textForArcLabel.bind($$)).attr("transform", $$.transformForArcLabel.bind($$)).style('font-size', function (d) {
  4686. return $$.isGaugeType(d.data) && $$.filterTargetsToShow($$.data.targets).length === 1 ? Math.round($$.radius / 5) + 'px' : '';
  4687. }).transition().duration(duration).style("opacity", function (d) {
  4688. return $$.isTargetToShow(d.data.id) && $$.isArcType(d.data) ? 1 : 0;
  4689. });
  4690. main.select('.' + CLASS.chartArcsTitle).style("opacity", $$.hasType('donut') || hasGaugeType ? 1 : 0);
  4691. if (hasGaugeType) {
  4692. var index = 0;
  4693. var backgroundArc = $$.arcs.select('g.' + CLASS.chartArcsBackground).selectAll('path.' + CLASS.chartArcsBackground).data($$.data.targets);
  4694. backgroundArc.enter().append("path").attr("class", function (d, i) {
  4695. return CLASS.chartArcsBackground + ' ' + CLASS.chartArcsBackground + '-' + i;
  4696. }).merge(backgroundArc).attr("d", function (d1) {
  4697. if ($$.hiddenTargetIds.indexOf(d1.id) >= 0) {
  4698. return "M 0 0";
  4699. }
  4700. var d = {
  4701. data: [{
  4702. value: config.gauge_max
  4703. }],
  4704. startAngle: config.gauge_startingAngle,
  4705. endAngle: -1 * config.gauge_startingAngle * (config.gauge_fullCircle ? Math.PI : 1),
  4706. index: index++
  4707. };
  4708. return $$.getArc(d, true, true);
  4709. });
  4710. backgroundArc.exit().remove();
  4711. $$.arcs.select('.' + CLASS.chartArcsGaugeUnit).attr("dy", ".75em").text(config.gauge_label_show ? config.gauge_units : '');
  4712. $$.arcs.select('.' + CLASS.chartArcsGaugeMin).attr("dx", -1 * ($$.innerRadius + ($$.radius - $$.innerRadius) / (config.gauge_fullCircle ? 1 : 2)) + "px").attr("dy", "1.2em").text(config.gauge_label_show ? $$.textForGaugeMinMax(config.gauge_min, false) : '');
  4713. $$.arcs.select('.' + CLASS.chartArcsGaugeMax).attr("dx", $$.innerRadius + ($$.radius - $$.innerRadius) / (config.gauge_fullCircle ? 1 : 2) + "px").attr("dy", "1.2em").text(config.gauge_label_show ? $$.textForGaugeMinMax(config.gauge_max, true) : '');
  4714. }
  4715. };
  4716. ChartInternal.prototype.initGauge = function () {
  4717. var arcs = this.arcs;
  4718. if (this.hasType('gauge')) {
  4719. arcs.append('g').attr("class", CLASS.chartArcsBackground);
  4720. arcs.append("text").attr("class", CLASS.chartArcsGaugeUnit).style("text-anchor", "middle").style("pointer-events", "none");
  4721. arcs.append("text").attr("class", CLASS.chartArcsGaugeMin).style("text-anchor", "middle").style("pointer-events", "none");
  4722. arcs.append("text").attr("class", CLASS.chartArcsGaugeMax).style("text-anchor", "middle").style("pointer-events", "none");
  4723. }
  4724. };
  4725. ChartInternal.prototype.getGaugeLabelHeight = function () {
  4726. return this.config.gauge_label_show ? 20 : 0;
  4727. };
  4728. ChartInternal.prototype.hasCaches = function (ids) {
  4729. for (var i = 0; i < ids.length; i++) {
  4730. if (!(ids[i] in this.cache)) {
  4731. return false;
  4732. }
  4733. }
  4734. return true;
  4735. };
  4736. ChartInternal.prototype.addCache = function (id, target) {
  4737. this.cache[id] = this.cloneTarget(target);
  4738. };
  4739. ChartInternal.prototype.getCaches = function (ids) {
  4740. var targets = [],
  4741. i;
  4742. for (i = 0; i < ids.length; i++) {
  4743. if (ids[i] in this.cache) {
  4744. targets.push(this.cloneTarget(this.cache[ids[i]]));
  4745. }
  4746. }
  4747. return targets;
  4748. };
  4749. ChartInternal.prototype.categoryName = function (i) {
  4750. var config = this.config;
  4751. return i < config.axis_x_categories.length ? config.axis_x_categories[i] : i;
  4752. };
  4753. ChartInternal.prototype.generateTargetClass = function (targetId) {
  4754. return targetId || targetId === 0 ? ('-' + targetId).replace(/\s/g, '-') : '';
  4755. };
  4756. ChartInternal.prototype.generateClass = function (prefix, targetId) {
  4757. return " " + prefix + " " + prefix + this.generateTargetClass(targetId);
  4758. };
  4759. ChartInternal.prototype.classText = function (d) {
  4760. return this.generateClass(CLASS.text, d.index);
  4761. };
  4762. ChartInternal.prototype.classTexts = function (d) {
  4763. return this.generateClass(CLASS.texts, d.id);
  4764. };
  4765. ChartInternal.prototype.classShape = function (d) {
  4766. return this.generateClass(CLASS.shape, d.index);
  4767. };
  4768. ChartInternal.prototype.classShapes = function (d) {
  4769. return this.generateClass(CLASS.shapes, d.id);
  4770. };
  4771. ChartInternal.prototype.classLine = function (d) {
  4772. return this.classShape(d) + this.generateClass(CLASS.line, d.id);
  4773. };
  4774. ChartInternal.prototype.classLines = function (d) {
  4775. return this.classShapes(d) + this.generateClass(CLASS.lines, d.id);
  4776. };
  4777. ChartInternal.prototype.classCircle = function (d) {
  4778. return this.classShape(d) + this.generateClass(CLASS.circle, d.index);
  4779. };
  4780. ChartInternal.prototype.classCircles = function (d) {
  4781. return this.classShapes(d) + this.generateClass(CLASS.circles, d.id);
  4782. };
  4783. ChartInternal.prototype.classBar = function (d) {
  4784. return this.classShape(d) + this.generateClass(CLASS.bar, d.index);
  4785. };
  4786. ChartInternal.prototype.classBars = function (d) {
  4787. return this.classShapes(d) + this.generateClass(CLASS.bars, d.id);
  4788. };
  4789. ChartInternal.prototype.classArc = function (d) {
  4790. return this.classShape(d.data) + this.generateClass(CLASS.arc, d.data.id);
  4791. };
  4792. ChartInternal.prototype.classArcs = function (d) {
  4793. return this.classShapes(d.data) + this.generateClass(CLASS.arcs, d.data.id);
  4794. };
  4795. ChartInternal.prototype.classArea = function (d) {
  4796. return this.classShape(d) + this.generateClass(CLASS.area, d.id);
  4797. };
  4798. ChartInternal.prototype.classAreas = function (d) {
  4799. return this.classShapes(d) + this.generateClass(CLASS.areas, d.id);
  4800. };
  4801. ChartInternal.prototype.classRegion = function (d, i) {
  4802. return this.generateClass(CLASS.region, i) + ' ' + ('class' in d ? d['class'] : '');
  4803. };
  4804. ChartInternal.prototype.classEvent = function (d) {
  4805. return this.generateClass(CLASS.eventRect, d.index);
  4806. };
  4807. ChartInternal.prototype.classTarget = function (id) {
  4808. var $$ = this;
  4809. var additionalClassSuffix = $$.config.data_classes[id],
  4810. additionalClass = '';
  4811. if (additionalClassSuffix) {
  4812. additionalClass = ' ' + CLASS.target + '-' + additionalClassSuffix;
  4813. }
  4814. return $$.generateClass(CLASS.target, id) + additionalClass;
  4815. };
  4816. ChartInternal.prototype.classFocus = function (d) {
  4817. return this.classFocused(d) + this.classDefocused(d);
  4818. };
  4819. ChartInternal.prototype.classFocused = function (d) {
  4820. return ' ' + (this.focusedTargetIds.indexOf(d.id) >= 0 ? CLASS.focused : '');
  4821. };
  4822. ChartInternal.prototype.classDefocused = function (d) {
  4823. return ' ' + (this.defocusedTargetIds.indexOf(d.id) >= 0 ? CLASS.defocused : '');
  4824. };
  4825. ChartInternal.prototype.classChartText = function (d) {
  4826. return CLASS.chartText + this.classTarget(d.id);
  4827. };
  4828. ChartInternal.prototype.classChartLine = function (d) {
  4829. return CLASS.chartLine + this.classTarget(d.id);
  4830. };
  4831. ChartInternal.prototype.classChartBar = function (d) {
  4832. return CLASS.chartBar + this.classTarget(d.id);
  4833. };
  4834. ChartInternal.prototype.classChartArc = function (d) {
  4835. return CLASS.chartArc + this.classTarget(d.data.id);
  4836. };
  4837. ChartInternal.prototype.getTargetSelectorSuffix = function (targetId) {
  4838. return this.generateTargetClass(targetId).replace(/([?!@#$%^&*()_=+,.<>'":;\[\]\/|~`{}\\])/g, '\\$1');
  4839. };
  4840. ChartInternal.prototype.selectorTarget = function (id, prefix) {
  4841. return (prefix || '') + '.' + CLASS.target + this.getTargetSelectorSuffix(id);
  4842. };
  4843. ChartInternal.prototype.selectorTargets = function (ids, prefix) {
  4844. var $$ = this;
  4845. ids = ids || [];
  4846. return ids.length ? ids.map(function (id) {
  4847. return $$.selectorTarget(id, prefix);
  4848. }) : null;
  4849. };
  4850. ChartInternal.prototype.selectorLegend = function (id) {
  4851. return '.' + CLASS.legendItem + this.getTargetSelectorSuffix(id);
  4852. };
  4853. ChartInternal.prototype.selectorLegends = function (ids) {
  4854. var $$ = this;
  4855. return ids && ids.length ? ids.map(function (id) {
  4856. return $$.selectorLegend(id);
  4857. }) : null;
  4858. };
  4859. ChartInternal.prototype.getClipPath = function (id) {
  4860. var isIE9 = window.navigator.appVersion.toLowerCase().indexOf("msie 9.") >= 0;
  4861. return "url(" + (isIE9 ? "" : document.URL.split('#')[0]) + "#" + id + ")";
  4862. };
  4863. ChartInternal.prototype.appendClip = function (parent, id) {
  4864. return parent.append("clipPath").attr("id", id).append("rect");
  4865. };
  4866. ChartInternal.prototype.getAxisClipX = function (forHorizontal) {
  4867. // axis line width + padding for left
  4868. var left = Math.max(30, this.margin.left);
  4869. return forHorizontal ? -(1 + left) : -(left - 1);
  4870. };
  4871. ChartInternal.prototype.getAxisClipY = function (forHorizontal) {
  4872. return forHorizontal ? -20 : -this.margin.top;
  4873. };
  4874. ChartInternal.prototype.getXAxisClipX = function () {
  4875. var $$ = this;
  4876. return $$.getAxisClipX(!$$.config.axis_rotated);
  4877. };
  4878. ChartInternal.prototype.getXAxisClipY = function () {
  4879. var $$ = this;
  4880. return $$.getAxisClipY(!$$.config.axis_rotated);
  4881. };
  4882. ChartInternal.prototype.getYAxisClipX = function () {
  4883. var $$ = this;
  4884. return $$.config.axis_y_inner ? -1 : $$.getAxisClipX($$.config.axis_rotated);
  4885. };
  4886. ChartInternal.prototype.getYAxisClipY = function () {
  4887. var $$ = this;
  4888. return $$.getAxisClipY($$.config.axis_rotated);
  4889. };
  4890. ChartInternal.prototype.getAxisClipWidth = function (forHorizontal) {
  4891. var $$ = this,
  4892. left = Math.max(30, $$.margin.left),
  4893. right = Math.max(30, $$.margin.right); // width + axis line width + padding for left/right
  4894. return forHorizontal ? $$.width + 2 + left + right : $$.margin.left + 20;
  4895. };
  4896. ChartInternal.prototype.getAxisClipHeight = function (forHorizontal) {
  4897. // less than 20 is not enough to show the axis label 'outer' without legend
  4898. return (forHorizontal ? this.margin.bottom : this.margin.top + this.height) + 20;
  4899. };
  4900. ChartInternal.prototype.getXAxisClipWidth = function () {
  4901. var $$ = this;
  4902. return $$.getAxisClipWidth(!$$.config.axis_rotated);
  4903. };
  4904. ChartInternal.prototype.getXAxisClipHeight = function () {
  4905. var $$ = this;
  4906. return $$.getAxisClipHeight(!$$.config.axis_rotated);
  4907. };
  4908. ChartInternal.prototype.getYAxisClipWidth = function () {
  4909. var $$ = this;
  4910. return $$.getAxisClipWidth($$.config.axis_rotated) + ($$.config.axis_y_inner ? 20 : 0);
  4911. };
  4912. ChartInternal.prototype.getYAxisClipHeight = function () {
  4913. var $$ = this;
  4914. return $$.getAxisClipHeight($$.config.axis_rotated);
  4915. };
  4916. ChartInternal.prototype.generateColor = function () {
  4917. var $$ = this,
  4918. config = $$.config,
  4919. d3 = $$.d3,
  4920. colors = config.data_colors,
  4921. pattern = notEmpty(config.color_pattern) ? config.color_pattern : d3.schemeCategory10,
  4922. callback = config.data_color,
  4923. ids = [];
  4924. return function (d) {
  4925. var id = d.id || d.data && d.data.id || d,
  4926. color; // if callback function is provided
  4927. if (colors[id] instanceof Function) {
  4928. color = colors[id](d);
  4929. } // if specified, choose that color
  4930. else if (colors[id]) {
  4931. color = colors[id];
  4932. } // if not specified, choose from pattern
  4933. else {
  4934. if (ids.indexOf(id) < 0) {
  4935. ids.push(id);
  4936. }
  4937. color = pattern[ids.indexOf(id) % pattern.length];
  4938. colors[id] = color;
  4939. }
  4940. return callback instanceof Function ? callback(color, d) : color;
  4941. };
  4942. };
  4943. ChartInternal.prototype.generateLevelColor = function () {
  4944. var $$ = this,
  4945. config = $$.config,
  4946. colors = config.color_pattern,
  4947. threshold = config.color_threshold,
  4948. asValue = threshold.unit === 'value',
  4949. values = threshold.values && threshold.values.length ? threshold.values : [],
  4950. max = threshold.max || 100;
  4951. return notEmpty(config.color_threshold) ? function (value) {
  4952. var i,
  4953. v,
  4954. color = colors[colors.length - 1];
  4955. for (i = 0; i < values.length; i++) {
  4956. v = asValue ? value : value * 100 / max;
  4957. if (v < values[i]) {
  4958. color = colors[i];
  4959. break;
  4960. }
  4961. }
  4962. return color;
  4963. } : null;
  4964. };
  4965. ChartInternal.prototype.getDefaultConfig = function () {
  4966. var config = {
  4967. bindto: '#chart',
  4968. svg_classname: undefined,
  4969. size_width: undefined,
  4970. size_height: undefined,
  4971. padding_left: undefined,
  4972. padding_right: undefined,
  4973. padding_top: undefined,
  4974. padding_bottom: undefined,
  4975. resize_auto: true,
  4976. zoom_enabled: false,
  4977. zoom_initialRange: undefined,
  4978. zoom_type: 'scroll',
  4979. zoom_disableDefaultBehavior: false,
  4980. zoom_privileged: false,
  4981. zoom_rescale: false,
  4982. zoom_onzoom: function zoom_onzoom() {},
  4983. zoom_onzoomstart: function zoom_onzoomstart() {},
  4984. zoom_onzoomend: function zoom_onzoomend() {},
  4985. zoom_x_min: undefined,
  4986. zoom_x_max: undefined,
  4987. interaction_brighten: true,
  4988. interaction_enabled: true,
  4989. onmouseover: function onmouseover() {},
  4990. onmouseout: function onmouseout() {},
  4991. onresize: function onresize() {},
  4992. onresized: function onresized() {},
  4993. oninit: function oninit() {},
  4994. onrendered: function onrendered() {},
  4995. transition_duration: 350,
  4996. data_x: undefined,
  4997. data_xs: {},
  4998. data_xFormat: '%Y-%m-%d',
  4999. data_xLocaltime: true,
  5000. data_xSort: true,
  5001. data_idConverter: function data_idConverter(id) {
  5002. return id;
  5003. },
  5004. data_names: {},
  5005. data_classes: {},
  5006. data_groups: [],
  5007. data_axes: {},
  5008. data_type: undefined,
  5009. data_types: {},
  5010. data_labels: {},
  5011. data_order: 'desc',
  5012. data_regions: {},
  5013. data_color: undefined,
  5014. data_colors: {},
  5015. data_hide: false,
  5016. data_filter: undefined,
  5017. data_selection_enabled: false,
  5018. data_selection_grouped: false,
  5019. data_selection_isselectable: function data_selection_isselectable() {
  5020. return true;
  5021. },
  5022. data_selection_multiple: true,
  5023. data_selection_draggable: false,
  5024. data_onclick: function data_onclick() {},
  5025. data_onmouseover: function data_onmouseover() {},
  5026. data_onmouseout: function data_onmouseout() {},
  5027. data_onselected: function data_onselected() {},
  5028. data_onunselected: function data_onunselected() {},
  5029. data_url: undefined,
  5030. data_headers: undefined,
  5031. data_json: undefined,
  5032. data_rows: undefined,
  5033. data_columns: undefined,
  5034. data_mimeType: undefined,
  5035. data_keys: undefined,
  5036. // configuration for no plot-able data supplied.
  5037. data_empty_label_text: "",
  5038. // subchart
  5039. subchart_show: false,
  5040. subchart_size_height: 60,
  5041. subchart_axis_x_show: true,
  5042. subchart_onbrush: function subchart_onbrush() {},
  5043. // color
  5044. color_pattern: [],
  5045. color_threshold: {},
  5046. // legend
  5047. legend_show: true,
  5048. legend_hide: false,
  5049. legend_position: 'bottom',
  5050. legend_inset_anchor: 'top-left',
  5051. legend_inset_x: 10,
  5052. legend_inset_y: 0,
  5053. legend_inset_step: undefined,
  5054. legend_item_onclick: undefined,
  5055. legend_item_onmouseover: undefined,
  5056. legend_item_onmouseout: undefined,
  5057. legend_equally: false,
  5058. legend_padding: 0,
  5059. legend_item_tile_width: 10,
  5060. legend_item_tile_height: 10,
  5061. // axis
  5062. axis_rotated: false,
  5063. axis_x_show: true,
  5064. axis_x_type: 'indexed',
  5065. axis_x_localtime: true,
  5066. axis_x_categories: [],
  5067. axis_x_tick_centered: false,
  5068. axis_x_tick_format: undefined,
  5069. axis_x_tick_culling: {},
  5070. axis_x_tick_culling_max: 10,
  5071. axis_x_tick_count: undefined,
  5072. axis_x_tick_fit: true,
  5073. axis_x_tick_values: null,
  5074. axis_x_tick_rotate: 0,
  5075. axis_x_tick_outer: true,
  5076. axis_x_tick_multiline: true,
  5077. axis_x_tick_multilineMax: 0,
  5078. axis_x_tick_width: null,
  5079. axis_x_max: undefined,
  5080. axis_x_min: undefined,
  5081. axis_x_padding: {},
  5082. axis_x_height: undefined,
  5083. axis_x_selection: undefined,
  5084. axis_x_label: {},
  5085. axis_x_inner: undefined,
  5086. axis_y_show: true,
  5087. axis_y_type: undefined,
  5088. axis_y_max: undefined,
  5089. axis_y_min: undefined,
  5090. axis_y_inverted: false,
  5091. axis_y_center: undefined,
  5092. axis_y_inner: undefined,
  5093. axis_y_label: {},
  5094. axis_y_tick_format: undefined,
  5095. axis_y_tick_outer: true,
  5096. axis_y_tick_values: null,
  5097. axis_y_tick_rotate: 0,
  5098. axis_y_tick_count: undefined,
  5099. axis_y_tick_time_type: undefined,
  5100. axis_y_tick_time_interval: undefined,
  5101. axis_y_padding: {},
  5102. axis_y_default: undefined,
  5103. axis_y2_show: false,
  5104. axis_y2_max: undefined,
  5105. axis_y2_min: undefined,
  5106. axis_y2_inverted: false,
  5107. axis_y2_center: undefined,
  5108. axis_y2_inner: undefined,
  5109. axis_y2_label: {},
  5110. axis_y2_tick_format: undefined,
  5111. axis_y2_tick_outer: true,
  5112. axis_y2_tick_values: null,
  5113. axis_y2_tick_count: undefined,
  5114. axis_y2_padding: {},
  5115. axis_y2_default: undefined,
  5116. // grid
  5117. grid_x_show: false,
  5118. grid_x_type: 'tick',
  5119. grid_x_lines: [],
  5120. grid_y_show: false,
  5121. // not used
  5122. // grid_y_type: 'tick',
  5123. grid_y_lines: [],
  5124. grid_y_ticks: 10,
  5125. grid_focus_show: true,
  5126. grid_lines_front: true,
  5127. // point - point of each data
  5128. point_show: true,
  5129. point_r: 2.5,
  5130. point_sensitivity: 10,
  5131. point_focus_expand_enabled: true,
  5132. point_focus_expand_r: undefined,
  5133. point_select_r: undefined,
  5134. // line
  5135. line_connectNull: false,
  5136. line_step_type: 'step',
  5137. // bar
  5138. bar_width: undefined,
  5139. bar_width_ratio: 0.6,
  5140. bar_width_max: undefined,
  5141. bar_zerobased: true,
  5142. bar_space: 0,
  5143. // area
  5144. area_zerobased: true,
  5145. area_above: false,
  5146. // pie
  5147. pie_label_show: true,
  5148. pie_label_format: undefined,
  5149. pie_label_threshold: 0.05,
  5150. pie_label_ratio: undefined,
  5151. pie_expand: {},
  5152. pie_expand_duration: 50,
  5153. // gauge
  5154. gauge_fullCircle: false,
  5155. gauge_label_show: true,
  5156. gauge_labelLine_show: true,
  5157. gauge_label_format: undefined,
  5158. gauge_min: 0,
  5159. gauge_max: 100,
  5160. gauge_startingAngle: -1 * Math.PI / 2,
  5161. gauge_label_extents: undefined,
  5162. gauge_units: undefined,
  5163. gauge_width: undefined,
  5164. gauge_arcs_minWidth: 5,
  5165. gauge_expand: {},
  5166. gauge_expand_duration: 50,
  5167. // donut
  5168. donut_label_show: true,
  5169. donut_label_format: undefined,
  5170. donut_label_threshold: 0.05,
  5171. donut_label_ratio: undefined,
  5172. donut_width: undefined,
  5173. donut_title: "",
  5174. donut_expand: {},
  5175. donut_expand_duration: 50,
  5176. // spline
  5177. spline_interpolation_type: 'cardinal',
  5178. // region - region to change style
  5179. regions: [],
  5180. // tooltip - show when mouseover on each data
  5181. tooltip_show: true,
  5182. tooltip_grouped: true,
  5183. tooltip_order: undefined,
  5184. tooltip_format_title: undefined,
  5185. tooltip_format_name: undefined,
  5186. tooltip_format_value: undefined,
  5187. tooltip_position: undefined,
  5188. tooltip_contents: function tooltip_contents(d, defaultTitleFormat, defaultValueFormat, color) {
  5189. return this.getTooltipContent ? this.getTooltipContent(d, defaultTitleFormat, defaultValueFormat, color) : '';
  5190. },
  5191. tooltip_init_show: false,
  5192. tooltip_init_x: 0,
  5193. tooltip_init_position: {
  5194. top: '0px',
  5195. left: '50px'
  5196. },
  5197. tooltip_onshow: function tooltip_onshow() {},
  5198. tooltip_onhide: function tooltip_onhide() {},
  5199. // title
  5200. title_text: undefined,
  5201. title_padding: {
  5202. top: 0,
  5203. right: 0,
  5204. bottom: 0,
  5205. left: 0
  5206. },
  5207. title_position: 'top-center'
  5208. };
  5209. Object.keys(this.additionalConfig).forEach(function (key) {
  5210. config[key] = this.additionalConfig[key];
  5211. }, this);
  5212. return config;
  5213. };
  5214. ChartInternal.prototype.additionalConfig = {};
  5215. ChartInternal.prototype.loadConfig = function (config) {
  5216. var this_config = this.config,
  5217. target,
  5218. keys,
  5219. read;
  5220. function find() {
  5221. var key = keys.shift(); // console.log("key =>", key, ", target =>", target);
  5222. if (key && target && _typeof(target) === 'object' && key in target) {
  5223. target = target[key];
  5224. return find();
  5225. } else if (!key) {
  5226. return target;
  5227. } else {
  5228. return undefined;
  5229. }
  5230. }
  5231. Object.keys(this_config).forEach(function (key) {
  5232. target = config;
  5233. keys = key.split('_');
  5234. read = find(); // console.log("CONFIG : ", key, read);
  5235. if (isDefined(read)) {
  5236. this_config[key] = read;
  5237. }
  5238. });
  5239. };
  5240. ChartInternal.prototype.convertUrlToData = function (url, mimeType, headers, keys, done) {
  5241. var $$ = this,
  5242. type = mimeType ? mimeType : 'csv',
  5243. f,
  5244. converter;
  5245. if (type === 'json') {
  5246. f = $$.d3.json;
  5247. converter = $$.convertJsonToData;
  5248. } else if (type === 'tsv') {
  5249. f = $$.d3.tsv;
  5250. converter = $$.convertXsvToData;
  5251. } else {
  5252. f = $$.d3.csv;
  5253. converter = $$.convertXsvToData;
  5254. }
  5255. f(url, headers).then(function (data) {
  5256. done.call($$, converter.call($$, data, keys));
  5257. }).catch(function (error) {
  5258. throw error;
  5259. });
  5260. };
  5261. ChartInternal.prototype.convertXsvToData = function (xsv) {
  5262. var keys = xsv.columns,
  5263. rows = xsv;
  5264. if (rows.length === 0) {
  5265. return {
  5266. keys: keys,
  5267. rows: [keys.reduce(function (row, key) {
  5268. return Object.assign(row, _defineProperty({}, key, null));
  5269. }, {})]
  5270. };
  5271. } else {
  5272. // [].concat() is to convert result into a plain array otherwise
  5273. // test is not happy because rows have properties.
  5274. return {
  5275. keys: keys,
  5276. rows: [].concat(xsv)
  5277. };
  5278. }
  5279. };
  5280. ChartInternal.prototype.convertJsonToData = function (json, keys) {
  5281. var $$ = this,
  5282. new_rows = [],
  5283. targetKeys,
  5284. data;
  5285. if (keys) {
  5286. // when keys specified, json would be an array that includes objects
  5287. if (keys.x) {
  5288. targetKeys = keys.value.concat(keys.x);
  5289. $$.config.data_x = keys.x;
  5290. } else {
  5291. targetKeys = keys.value;
  5292. }
  5293. new_rows.push(targetKeys);
  5294. json.forEach(function (o) {
  5295. var new_row = [];
  5296. targetKeys.forEach(function (key) {
  5297. // convert undefined to null because undefined data will be removed in convertDataToTargets()
  5298. var v = $$.findValueInJson(o, key);
  5299. if (isUndefined(v)) {
  5300. v = null;
  5301. }
  5302. new_row.push(v);
  5303. });
  5304. new_rows.push(new_row);
  5305. });
  5306. data = $$.convertRowsToData(new_rows);
  5307. } else {
  5308. Object.keys(json).forEach(function (key) {
  5309. new_rows.push([key].concat(json[key]));
  5310. });
  5311. data = $$.convertColumnsToData(new_rows);
  5312. }
  5313. return data;
  5314. };
  5315. ChartInternal.prototype.findValueInJson = function (object, path) {
  5316. path = path.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties (replace [] with .)
  5317. path = path.replace(/^\./, ''); // strip a leading dot
  5318. var pathArray = path.split('.');
  5319. for (var i = 0; i < pathArray.length; ++i) {
  5320. var k = pathArray[i];
  5321. if (k in object) {
  5322. object = object[k];
  5323. } else {
  5324. return;
  5325. }
  5326. }
  5327. return object;
  5328. };
  5329. /**
  5330. * Converts the rows to normalized data.
  5331. * @param {any[][]} rows The row data
  5332. * @return {Object}
  5333. */
  5334. ChartInternal.prototype.convertRowsToData = function (rows) {
  5335. var newRows = [];
  5336. var keys = rows[0];
  5337. for (var i = 1; i < rows.length; i++) {
  5338. var newRow = {};
  5339. for (var j = 0; j < rows[i].length; j++) {
  5340. if (isUndefined(rows[i][j])) {
  5341. throw new Error("Source data is missing a component at (" + i + "," + j + ")!");
  5342. }
  5343. newRow[keys[j]] = rows[i][j];
  5344. }
  5345. newRows.push(newRow);
  5346. }
  5347. return {
  5348. keys: keys,
  5349. rows: newRows
  5350. };
  5351. };
  5352. /**
  5353. * Converts the columns to normalized data.
  5354. * @param {any[][]} columns The column data
  5355. * @return {Object}
  5356. */
  5357. ChartInternal.prototype.convertColumnsToData = function (columns) {
  5358. var newRows = [];
  5359. var keys = [];
  5360. for (var i = 0; i < columns.length; i++) {
  5361. var key = columns[i][0];
  5362. for (var j = 1; j < columns[i].length; j++) {
  5363. if (isUndefined(newRows[j - 1])) {
  5364. newRows[j - 1] = {};
  5365. }
  5366. if (isUndefined(columns[i][j])) {
  5367. throw new Error("Source data is missing a component at (" + i + "," + j + ")!");
  5368. }
  5369. newRows[j - 1][key] = columns[i][j];
  5370. }
  5371. keys.push(key);
  5372. }
  5373. return {
  5374. keys: keys,
  5375. rows: newRows
  5376. };
  5377. };
  5378. /**
  5379. * Converts the data format into the target format.
  5380. * @param {!Object} data
  5381. * @param {!Array} data.keys Ordered list of target IDs.
  5382. * @param {!Array} data.rows Rows of data to convert.
  5383. * @param {boolean} appendXs True to append to $$.data.xs, False to replace.
  5384. * @return {!Array}
  5385. */
  5386. ChartInternal.prototype.convertDataToTargets = function (data, appendXs) {
  5387. var $$ = this,
  5388. config = $$.config,
  5389. targets,
  5390. ids,
  5391. xs,
  5392. keys; // handles format where keys are not orderly provided
  5393. if (isArray(data)) {
  5394. keys = Object.keys(data[0]);
  5395. } else {
  5396. keys = data.keys;
  5397. data = data.rows;
  5398. }
  5399. ids = keys.filter($$.isNotX, $$);
  5400. xs = keys.filter($$.isX, $$); // save x for update data by load when custom x and c3.x API
  5401. ids.forEach(function (id) {
  5402. var xKey = $$.getXKey(id);
  5403. if ($$.isCustomX() || $$.isTimeSeries()) {
  5404. // if included in input data
  5405. if (xs.indexOf(xKey) >= 0) {
  5406. $$.data.xs[id] = (appendXs && $$.data.xs[id] ? $$.data.xs[id] : []).concat(data.map(function (d) {
  5407. return d[xKey];
  5408. }).filter(isValue).map(function (rawX, i) {
  5409. return $$.generateTargetX(rawX, id, i);
  5410. }));
  5411. } // if not included in input data, find from preloaded data of other id's x
  5412. else if (config.data_x) {
  5413. $$.data.xs[id] = $$.getOtherTargetXs();
  5414. } // if not included in input data, find from preloaded data
  5415. else if (notEmpty(config.data_xs)) {
  5416. $$.data.xs[id] = $$.getXValuesOfXKey(xKey, $$.data.targets);
  5417. } // MEMO: if no x included, use same x of current will be used
  5418. } else {
  5419. $$.data.xs[id] = data.map(function (d, i) {
  5420. return i;
  5421. });
  5422. }
  5423. }); // check x is defined
  5424. ids.forEach(function (id) {
  5425. if (!$$.data.xs[id]) {
  5426. throw new Error('x is not defined for id = "' + id + '".');
  5427. }
  5428. }); // convert to target
  5429. targets = ids.map(function (id, index) {
  5430. var convertedId = config.data_idConverter(id);
  5431. return {
  5432. id: convertedId,
  5433. id_org: id,
  5434. values: data.map(function (d, i) {
  5435. var xKey = $$.getXKey(id),
  5436. rawX = d[xKey],
  5437. value = d[id] !== null && !isNaN(d[id]) ? +d[id] : null,
  5438. x; // use x as categories if custom x and categorized
  5439. if ($$.isCustomX() && $$.isCategorized() && !isUndefined(rawX)) {
  5440. if (index === 0 && i === 0) {
  5441. config.axis_x_categories = [];
  5442. }
  5443. x = config.axis_x_categories.indexOf(rawX);
  5444. if (x === -1) {
  5445. x = config.axis_x_categories.length;
  5446. config.axis_x_categories.push(rawX);
  5447. }
  5448. } else {
  5449. x = $$.generateTargetX(rawX, id, i);
  5450. } // mark as x = undefined if value is undefined and filter to remove after mapped
  5451. if (isUndefined(d[id]) || $$.data.xs[id].length <= i) {
  5452. x = undefined;
  5453. }
  5454. return {
  5455. x: x,
  5456. value: value,
  5457. id: convertedId
  5458. };
  5459. }).filter(function (v) {
  5460. return isDefined(v.x);
  5461. })
  5462. };
  5463. }); // finish targets
  5464. targets.forEach(function (t) {
  5465. var i; // sort values by its x
  5466. if (config.data_xSort) {
  5467. t.values = t.values.sort(function (v1, v2) {
  5468. var x1 = v1.x || v1.x === 0 ? v1.x : Infinity,
  5469. x2 = v2.x || v2.x === 0 ? v2.x : Infinity;
  5470. return x1 - x2;
  5471. });
  5472. } // indexing each value
  5473. i = 0;
  5474. t.values.forEach(function (v) {
  5475. v.index = i++;
  5476. }); // this needs to be sorted because its index and value.index is identical
  5477. $$.data.xs[t.id].sort(function (v1, v2) {
  5478. return v1 - v2;
  5479. });
  5480. }); // cache information about values
  5481. $$.hasNegativeValue = $$.hasNegativeValueInTargets(targets);
  5482. $$.hasPositiveValue = $$.hasPositiveValueInTargets(targets); // set target types
  5483. if (config.data_type) {
  5484. $$.setTargetType($$.mapToIds(targets).filter(function (id) {
  5485. return !(id in config.data_types);
  5486. }), config.data_type);
  5487. } // cache as original id keyed
  5488. targets.forEach(function (d) {
  5489. $$.addCache(d.id_org, d);
  5490. });
  5491. return targets;
  5492. };
  5493. ChartInternal.prototype.isX = function (key) {
  5494. var $$ = this,
  5495. config = $$.config;
  5496. return config.data_x && key === config.data_x || notEmpty(config.data_xs) && hasValue(config.data_xs, key);
  5497. };
  5498. ChartInternal.prototype.isNotX = function (key) {
  5499. return !this.isX(key);
  5500. };
  5501. ChartInternal.prototype.getXKey = function (id) {
  5502. var $$ = this,
  5503. config = $$.config;
  5504. return config.data_x ? config.data_x : notEmpty(config.data_xs) ? config.data_xs[id] : null;
  5505. };
  5506. ChartInternal.prototype.getXValuesOfXKey = function (key, targets) {
  5507. var $$ = this,
  5508. xValues,
  5509. ids = targets && notEmpty(targets) ? $$.mapToIds(targets) : [];
  5510. ids.forEach(function (id) {
  5511. if ($$.getXKey(id) === key) {
  5512. xValues = $$.data.xs[id];
  5513. }
  5514. });
  5515. return xValues;
  5516. };
  5517. ChartInternal.prototype.getXValue = function (id, i) {
  5518. var $$ = this;
  5519. return id in $$.data.xs && $$.data.xs[id] && isValue($$.data.xs[id][i]) ? $$.data.xs[id][i] : i;
  5520. };
  5521. ChartInternal.prototype.getOtherTargetXs = function () {
  5522. var $$ = this,
  5523. idsForX = Object.keys($$.data.xs);
  5524. return idsForX.length ? $$.data.xs[idsForX[0]] : null;
  5525. };
  5526. ChartInternal.prototype.getOtherTargetX = function (index) {
  5527. var xs = this.getOtherTargetXs();
  5528. return xs && index < xs.length ? xs[index] : null;
  5529. };
  5530. ChartInternal.prototype.addXs = function (xs) {
  5531. var $$ = this;
  5532. Object.keys(xs).forEach(function (id) {
  5533. $$.config.data_xs[id] = xs[id];
  5534. });
  5535. };
  5536. ChartInternal.prototype.addName = function (data) {
  5537. var $$ = this,
  5538. name;
  5539. if (data) {
  5540. name = $$.config.data_names[data.id];
  5541. data.name = name !== undefined ? name : data.id;
  5542. }
  5543. return data;
  5544. };
  5545. ChartInternal.prototype.getValueOnIndex = function (values, index) {
  5546. var valueOnIndex = values.filter(function (v) {
  5547. return v.index === index;
  5548. });
  5549. return valueOnIndex.length ? valueOnIndex[0] : null;
  5550. };
  5551. ChartInternal.prototype.updateTargetX = function (targets, x) {
  5552. var $$ = this;
  5553. targets.forEach(function (t) {
  5554. t.values.forEach(function (v, i) {
  5555. v.x = $$.generateTargetX(x[i], t.id, i);
  5556. });
  5557. $$.data.xs[t.id] = x;
  5558. });
  5559. };
  5560. ChartInternal.prototype.updateTargetXs = function (targets, xs) {
  5561. var $$ = this;
  5562. targets.forEach(function (t) {
  5563. if (xs[t.id]) {
  5564. $$.updateTargetX([t], xs[t.id]);
  5565. }
  5566. });
  5567. };
  5568. ChartInternal.prototype.generateTargetX = function (rawX, id, index) {
  5569. var $$ = this,
  5570. x;
  5571. if ($$.isTimeSeries()) {
  5572. x = rawX ? $$.parseDate(rawX) : $$.parseDate($$.getXValue(id, index));
  5573. } else if ($$.isCustomX() && !$$.isCategorized()) {
  5574. x = isValue(rawX) ? +rawX : $$.getXValue(id, index);
  5575. } else {
  5576. x = index;
  5577. }
  5578. return x;
  5579. };
  5580. ChartInternal.prototype.cloneTarget = function (target) {
  5581. return {
  5582. id: target.id,
  5583. id_org: target.id_org,
  5584. values: target.values.map(function (d) {
  5585. return {
  5586. x: d.x,
  5587. value: d.value,
  5588. id: d.id
  5589. };
  5590. })
  5591. };
  5592. };
  5593. ChartInternal.prototype.getMaxDataCount = function () {
  5594. var $$ = this;
  5595. return $$.d3.max($$.data.targets, function (t) {
  5596. return t.values.length;
  5597. });
  5598. };
  5599. ChartInternal.prototype.mapToIds = function (targets) {
  5600. return targets.map(function (d) {
  5601. return d.id;
  5602. });
  5603. };
  5604. ChartInternal.prototype.mapToTargetIds = function (ids) {
  5605. var $$ = this;
  5606. return ids ? [].concat(ids) : $$.mapToIds($$.data.targets);
  5607. };
  5608. ChartInternal.prototype.hasTarget = function (targets, id) {
  5609. var ids = this.mapToIds(targets),
  5610. i;
  5611. for (i = 0; i < ids.length; i++) {
  5612. if (ids[i] === id) {
  5613. return true;
  5614. }
  5615. }
  5616. return false;
  5617. };
  5618. ChartInternal.prototype.isTargetToShow = function (targetId) {
  5619. return this.hiddenTargetIds.indexOf(targetId) < 0;
  5620. };
  5621. ChartInternal.prototype.isLegendToShow = function (targetId) {
  5622. return this.hiddenLegendIds.indexOf(targetId) < 0;
  5623. };
  5624. ChartInternal.prototype.filterTargetsToShow = function (targets) {
  5625. var $$ = this;
  5626. return targets.filter(function (t) {
  5627. return $$.isTargetToShow(t.id);
  5628. });
  5629. };
  5630. ChartInternal.prototype.mapTargetsToUniqueXs = function (targets) {
  5631. var $$ = this;
  5632. var xs = $$.d3.set($$.d3.merge(targets.map(function (t) {
  5633. return t.values.map(function (v) {
  5634. return +v.x;
  5635. });
  5636. }))).values();
  5637. xs = $$.isTimeSeries() ? xs.map(function (x) {
  5638. return new Date(+x);
  5639. }) : xs.map(function (x) {
  5640. return +x;
  5641. });
  5642. return xs.sort(function (a, b) {
  5643. return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
  5644. });
  5645. };
  5646. ChartInternal.prototype.addHiddenTargetIds = function (targetIds) {
  5647. targetIds = targetIds instanceof Array ? targetIds : new Array(targetIds);
  5648. for (var i = 0; i < targetIds.length; i++) {
  5649. if (this.hiddenTargetIds.indexOf(targetIds[i]) < 0) {
  5650. this.hiddenTargetIds = this.hiddenTargetIds.concat(targetIds[i]);
  5651. }
  5652. }
  5653. };
  5654. ChartInternal.prototype.removeHiddenTargetIds = function (targetIds) {
  5655. this.hiddenTargetIds = this.hiddenTargetIds.filter(function (id) {
  5656. return targetIds.indexOf(id) < 0;
  5657. });
  5658. };
  5659. ChartInternal.prototype.addHiddenLegendIds = function (targetIds) {
  5660. targetIds = targetIds instanceof Array ? targetIds : new Array(targetIds);
  5661. for (var i = 0; i < targetIds.length; i++) {
  5662. if (this.hiddenLegendIds.indexOf(targetIds[i]) < 0) {
  5663. this.hiddenLegendIds = this.hiddenLegendIds.concat(targetIds[i]);
  5664. }
  5665. }
  5666. };
  5667. ChartInternal.prototype.removeHiddenLegendIds = function (targetIds) {
  5668. this.hiddenLegendIds = this.hiddenLegendIds.filter(function (id) {
  5669. return targetIds.indexOf(id) < 0;
  5670. });
  5671. };
  5672. ChartInternal.prototype.getValuesAsIdKeyed = function (targets) {
  5673. var ys = {};
  5674. targets.forEach(function (t) {
  5675. ys[t.id] = [];
  5676. t.values.forEach(function (v) {
  5677. ys[t.id].push(v.value);
  5678. });
  5679. });
  5680. return ys;
  5681. };
  5682. ChartInternal.prototype.checkValueInTargets = function (targets, checker) {
  5683. var ids = Object.keys(targets),
  5684. i,
  5685. j,
  5686. values;
  5687. for (i = 0; i < ids.length; i++) {
  5688. values = targets[ids[i]].values;
  5689. for (j = 0; j < values.length; j++) {
  5690. if (checker(values[j].value)) {
  5691. return true;
  5692. }
  5693. }
  5694. }
  5695. return false;
  5696. };
  5697. ChartInternal.prototype.hasNegativeValueInTargets = function (targets) {
  5698. return this.checkValueInTargets(targets, function (v) {
  5699. return v < 0;
  5700. });
  5701. };
  5702. ChartInternal.prototype.hasPositiveValueInTargets = function (targets) {
  5703. return this.checkValueInTargets(targets, function (v) {
  5704. return v > 0;
  5705. });
  5706. };
  5707. ChartInternal.prototype.isOrderDesc = function () {
  5708. var config = this.config;
  5709. return typeof config.data_order === 'string' && config.data_order.toLowerCase() === 'desc';
  5710. };
  5711. ChartInternal.prototype.isOrderAsc = function () {
  5712. var config = this.config;
  5713. return typeof config.data_order === 'string' && config.data_order.toLowerCase() === 'asc';
  5714. };
  5715. ChartInternal.prototype.getOrderFunction = function () {
  5716. var $$ = this,
  5717. config = $$.config,
  5718. orderAsc = $$.isOrderAsc(),
  5719. orderDesc = $$.isOrderDesc();
  5720. if (orderAsc || orderDesc) {
  5721. var reducer = function reducer(p, c) {
  5722. return p + Math.abs(c.value);
  5723. };
  5724. return function (t1, t2) {
  5725. var t1Sum = t1.values.reduce(reducer, 0),
  5726. t2Sum = t2.values.reduce(reducer, 0);
  5727. return orderAsc ? t2Sum - t1Sum : t1Sum - t2Sum;
  5728. };
  5729. } else if (isFunction(config.data_order)) {
  5730. return config.data_order;
  5731. } else if (isArray(config.data_order)) {
  5732. var order = config.data_order;
  5733. return function (t1, t2) {
  5734. return order.indexOf(t1.id) - order.indexOf(t2.id);
  5735. };
  5736. }
  5737. };
  5738. ChartInternal.prototype.orderTargets = function (targets) {
  5739. var fct = this.getOrderFunction();
  5740. if (fct) {
  5741. targets.sort(fct);
  5742. }
  5743. return targets;
  5744. };
  5745. ChartInternal.prototype.filterByX = function (targets, x) {
  5746. return this.d3.merge(targets.map(function (t) {
  5747. return t.values;
  5748. })).filter(function (v) {
  5749. return v.x - x === 0;
  5750. });
  5751. };
  5752. ChartInternal.prototype.filterRemoveNull = function (data) {
  5753. return data.filter(function (d) {
  5754. return isValue(d.value);
  5755. });
  5756. };
  5757. ChartInternal.prototype.filterByXDomain = function (targets, xDomain) {
  5758. return targets.map(function (t) {
  5759. return {
  5760. id: t.id,
  5761. id_org: t.id_org,
  5762. values: t.values.filter(function (v) {
  5763. return xDomain[0] <= v.x && v.x <= xDomain[1];
  5764. })
  5765. };
  5766. });
  5767. };
  5768. ChartInternal.prototype.hasDataLabel = function () {
  5769. var config = this.config;
  5770. if (typeof config.data_labels === 'boolean' && config.data_labels) {
  5771. return true;
  5772. } else if (_typeof(config.data_labels) === 'object' && notEmpty(config.data_labels)) {
  5773. return true;
  5774. }
  5775. return false;
  5776. };
  5777. ChartInternal.prototype.getDataLabelLength = function (min, max, key) {
  5778. var $$ = this,
  5779. lengths = [0, 0],
  5780. paddingCoef = 1.3;
  5781. $$.selectChart.select('svg').selectAll('.dummy').data([min, max]).enter().append('text').text(function (d) {
  5782. return $$.dataLabelFormat(d.id)(d);
  5783. }).each(function (d, i) {
  5784. lengths[i] = this.getBoundingClientRect()[key] * paddingCoef;
  5785. }).remove();
  5786. return lengths;
  5787. };
  5788. /**
  5789. * Returns true if the given data point is not arc type, otherwise false.
  5790. * @param {Object} d The data point
  5791. * @return {boolean}
  5792. */
  5793. ChartInternal.prototype.isNoneArc = function (d) {
  5794. return this.hasTarget(this.data.targets, d.id);
  5795. };
  5796. /**
  5797. * Returns true if the given data point is arc type, otherwise false.
  5798. * @param {Object} d The data point
  5799. * @return {boolean}
  5800. */
  5801. ChartInternal.prototype.isArc = function (d) {
  5802. return 'data' in d && this.hasTarget(this.data.targets, d.data.id);
  5803. };
  5804. ChartInternal.prototype.findClosestFromTargets = function (targets, pos) {
  5805. var $$ = this,
  5806. candidates; // map to array of closest points of each target
  5807. candidates = targets.map(function (target) {
  5808. return $$.findClosest(target.values, pos);
  5809. }); // decide closest point and return
  5810. return $$.findClosest(candidates, pos);
  5811. };
  5812. ChartInternal.prototype.findClosest = function (values, pos) {
  5813. var $$ = this,
  5814. minDist = $$.config.point_sensitivity,
  5815. closest; // find mouseovering bar
  5816. values.filter(function (v) {
  5817. return v && $$.isBarType(v.id);
  5818. }).forEach(function (v) {
  5819. var shape = $$.main.select('.' + CLASS.bars + $$.getTargetSelectorSuffix(v.id) + ' .' + CLASS.bar + '-' + v.index).node();
  5820. if (!closest && $$.isWithinBar($$.d3.mouse(shape), shape)) {
  5821. closest = v;
  5822. }
  5823. }); // find closest point from non-bar
  5824. values.filter(function (v) {
  5825. return v && !$$.isBarType(v.id);
  5826. }).forEach(function (v) {
  5827. var d = $$.dist(v, pos);
  5828. if (d < minDist) {
  5829. minDist = d;
  5830. closest = v;
  5831. }
  5832. });
  5833. return closest;
  5834. };
  5835. ChartInternal.prototype.dist = function (data, pos) {
  5836. var $$ = this,
  5837. config = $$.config,
  5838. xIndex = config.axis_rotated ? 1 : 0,
  5839. yIndex = config.axis_rotated ? 0 : 1,
  5840. y = $$.circleY(data, data.index),
  5841. x = $$.x(data.x);
  5842. return Math.sqrt(Math.pow(x - pos[xIndex], 2) + Math.pow(y - pos[yIndex], 2));
  5843. };
  5844. ChartInternal.prototype.convertValuesToStep = function (values) {
  5845. var converted = [].concat(values),
  5846. i;
  5847. if (!this.isCategorized()) {
  5848. return values;
  5849. }
  5850. for (i = values.length + 1; 0 < i; i--) {
  5851. converted[i] = converted[i - 1];
  5852. }
  5853. converted[0] = {
  5854. x: converted[0].x - 1,
  5855. value: converted[0].value,
  5856. id: converted[0].id
  5857. };
  5858. converted[values.length + 1] = {
  5859. x: converted[values.length].x + 1,
  5860. value: converted[values.length].value,
  5861. id: converted[values.length].id
  5862. };
  5863. return converted;
  5864. };
  5865. ChartInternal.prototype.updateDataAttributes = function (name, attrs) {
  5866. var $$ = this,
  5867. config = $$.config,
  5868. current = config['data_' + name];
  5869. if (typeof attrs === 'undefined') {
  5870. return current;
  5871. }
  5872. Object.keys(attrs).forEach(function (id) {
  5873. current[id] = attrs[id];
  5874. });
  5875. $$.redraw({
  5876. withLegend: true
  5877. });
  5878. return current;
  5879. };
  5880. ChartInternal.prototype.load = function (targets, args) {
  5881. var $$ = this;
  5882. if (targets) {
  5883. // filter loading targets if needed
  5884. if (args.filter) {
  5885. targets = targets.filter(args.filter);
  5886. } // set type if args.types || args.type specified
  5887. if (args.type || args.types) {
  5888. targets.forEach(function (t) {
  5889. var type = args.types && args.types[t.id] ? args.types[t.id] : args.type;
  5890. $$.setTargetType(t.id, type);
  5891. });
  5892. } // Update/Add data
  5893. $$.data.targets.forEach(function (d) {
  5894. for (var i = 0; i < targets.length; i++) {
  5895. if (d.id === targets[i].id) {
  5896. d.values = targets[i].values;
  5897. targets.splice(i, 1);
  5898. break;
  5899. }
  5900. }
  5901. });
  5902. $$.data.targets = $$.data.targets.concat(targets); // add remained
  5903. } // Set targets
  5904. $$.updateTargets($$.data.targets); // Redraw with new targets
  5905. $$.redraw({
  5906. withUpdateOrgXDomain: true,
  5907. withUpdateXDomain: true,
  5908. withLegend: true
  5909. });
  5910. if (args.done) {
  5911. args.done();
  5912. }
  5913. };
  5914. ChartInternal.prototype.loadFromArgs = function (args) {
  5915. var $$ = this;
  5916. if (args.data) {
  5917. $$.load($$.convertDataToTargets(args.data), args);
  5918. } else if (args.url) {
  5919. $$.convertUrlToData(args.url, args.mimeType, args.headers, args.keys, function (data) {
  5920. $$.load($$.convertDataToTargets(data), args);
  5921. });
  5922. } else if (args.json) {
  5923. $$.load($$.convertDataToTargets($$.convertJsonToData(args.json, args.keys)), args);
  5924. } else if (args.rows) {
  5925. $$.load($$.convertDataToTargets($$.convertRowsToData(args.rows)), args);
  5926. } else if (args.columns) {
  5927. $$.load($$.convertDataToTargets($$.convertColumnsToData(args.columns)), args);
  5928. } else {
  5929. $$.load(null, args);
  5930. }
  5931. };
  5932. ChartInternal.prototype.unload = function (targetIds, done) {
  5933. var $$ = this;
  5934. if (!done) {
  5935. done = function done() {};
  5936. } // filter existing target
  5937. targetIds = targetIds.filter(function (id) {
  5938. return $$.hasTarget($$.data.targets, id);
  5939. }); // If no target, call done and return
  5940. if (!targetIds || targetIds.length === 0) {
  5941. done();
  5942. return;
  5943. }
  5944. $$.svg.selectAll(targetIds.map(function (id) {
  5945. return $$.selectorTarget(id);
  5946. })).transition().style('opacity', 0).remove().call($$.endall, done);
  5947. targetIds.forEach(function (id) {
  5948. // Reset fadein for future load
  5949. $$.withoutFadeIn[id] = false; // Remove target's elements
  5950. if ($$.legend) {
  5951. $$.legend.selectAll('.' + CLASS.legendItem + $$.getTargetSelectorSuffix(id)).remove();
  5952. } // Remove target
  5953. $$.data.targets = $$.data.targets.filter(function (t) {
  5954. return t.id !== id;
  5955. });
  5956. });
  5957. };
  5958. ChartInternal.prototype.getYDomainMin = function (targets) {
  5959. var $$ = this,
  5960. config = $$.config,
  5961. ids = $$.mapToIds(targets),
  5962. ys = $$.getValuesAsIdKeyed(targets),
  5963. j,
  5964. k,
  5965. baseId,
  5966. idsInGroup,
  5967. id,
  5968. hasNegativeValue;
  5969. if (config.data_groups.length > 0) {
  5970. hasNegativeValue = $$.hasNegativeValueInTargets(targets);
  5971. for (j = 0; j < config.data_groups.length; j++) {
  5972. // Determine baseId
  5973. idsInGroup = config.data_groups[j].filter(function (id) {
  5974. return ids.indexOf(id) >= 0;
  5975. });
  5976. if (idsInGroup.length === 0) {
  5977. continue;
  5978. }
  5979. baseId = idsInGroup[0]; // Consider negative values
  5980. if (hasNegativeValue && ys[baseId]) {
  5981. ys[baseId].forEach(function (v, i) {
  5982. ys[baseId][i] = v < 0 ? v : 0;
  5983. });
  5984. } // Compute min
  5985. for (k = 1; k < idsInGroup.length; k++) {
  5986. id = idsInGroup[k];
  5987. if (!ys[id]) {
  5988. continue;
  5989. }
  5990. ys[id].forEach(function (v, i) {
  5991. if ($$.axis.getId(id) === $$.axis.getId(baseId) && ys[baseId] && !(hasNegativeValue && +v > 0)) {
  5992. ys[baseId][i] += +v;
  5993. }
  5994. });
  5995. }
  5996. }
  5997. }
  5998. return $$.d3.min(Object.keys(ys).map(function (key) {
  5999. return $$.d3.min(ys[key]);
  6000. }));
  6001. };
  6002. ChartInternal.prototype.getYDomainMax = function (targets) {
  6003. var $$ = this,
  6004. config = $$.config,
  6005. ids = $$.mapToIds(targets),
  6006. ys = $$.getValuesAsIdKeyed(targets),
  6007. j,
  6008. k,
  6009. baseId,
  6010. idsInGroup,
  6011. id,
  6012. hasPositiveValue;
  6013. if (config.data_groups.length > 0) {
  6014. hasPositiveValue = $$.hasPositiveValueInTargets(targets);
  6015. for (j = 0; j < config.data_groups.length; j++) {
  6016. // Determine baseId
  6017. idsInGroup = config.data_groups[j].filter(function (id) {
  6018. return ids.indexOf(id) >= 0;
  6019. });
  6020. if (idsInGroup.length === 0) {
  6021. continue;
  6022. }
  6023. baseId = idsInGroup[0]; // Consider positive values
  6024. if (hasPositiveValue && ys[baseId]) {
  6025. ys[baseId].forEach(function (v, i) {
  6026. ys[baseId][i] = v > 0 ? v : 0;
  6027. });
  6028. } // Compute max
  6029. for (k = 1; k < idsInGroup.length; k++) {
  6030. id = idsInGroup[k];
  6031. if (!ys[id]) {
  6032. continue;
  6033. }
  6034. ys[id].forEach(function (v, i) {
  6035. if ($$.axis.getId(id) === $$.axis.getId(baseId) && ys[baseId] && !(hasPositiveValue && +v < 0)) {
  6036. ys[baseId][i] += +v;
  6037. }
  6038. });
  6039. }
  6040. }
  6041. }
  6042. return $$.d3.max(Object.keys(ys).map(function (key) {
  6043. return $$.d3.max(ys[key]);
  6044. }));
  6045. };
  6046. ChartInternal.prototype.getYDomain = function (targets, axisId, xDomain) {
  6047. var $$ = this,
  6048. config = $$.config,
  6049. targetsByAxisId = targets.filter(function (t) {
  6050. return $$.axis.getId(t.id) === axisId;
  6051. }),
  6052. yTargets = xDomain ? $$.filterByXDomain(targetsByAxisId, xDomain) : targetsByAxisId,
  6053. yMin = axisId === 'y2' ? config.axis_y2_min : config.axis_y_min,
  6054. yMax = axisId === 'y2' ? config.axis_y2_max : config.axis_y_max,
  6055. yDomainMin = $$.getYDomainMin(yTargets),
  6056. yDomainMax = $$.getYDomainMax(yTargets),
  6057. domain,
  6058. domainLength,
  6059. padding,
  6060. padding_top,
  6061. padding_bottom,
  6062. center = axisId === 'y2' ? config.axis_y2_center : config.axis_y_center,
  6063. yDomainAbs,
  6064. lengths,
  6065. diff,
  6066. ratio,
  6067. isAllPositive,
  6068. isAllNegative,
  6069. isZeroBased = $$.hasType('bar', yTargets) && config.bar_zerobased || $$.hasType('area', yTargets) && config.area_zerobased,
  6070. isInverted = axisId === 'y2' ? config.axis_y2_inverted : config.axis_y_inverted,
  6071. showHorizontalDataLabel = $$.hasDataLabel() && config.axis_rotated,
  6072. showVerticalDataLabel = $$.hasDataLabel() && !config.axis_rotated; // MEMO: avoid inverting domain unexpectedly
  6073. yDomainMin = isValue(yMin) ? yMin : isValue(yMax) ? yDomainMin < yMax ? yDomainMin : yMax - 10 : yDomainMin;
  6074. yDomainMax = isValue(yMax) ? yMax : isValue(yMin) ? yMin < yDomainMax ? yDomainMax : yMin + 10 : yDomainMax;
  6075. if (yTargets.length === 0) {
  6076. // use current domain if target of axisId is none
  6077. return axisId === 'y2' ? $$.y2.domain() : $$.y.domain();
  6078. }
  6079. if (isNaN(yDomainMin)) {
  6080. // set minimum to zero when not number
  6081. yDomainMin = 0;
  6082. }
  6083. if (isNaN(yDomainMax)) {
  6084. // set maximum to have same value as yDomainMin
  6085. yDomainMax = yDomainMin;
  6086. }
  6087. if (yDomainMin === yDomainMax) {
  6088. yDomainMin < 0 ? yDomainMax = 0 : yDomainMin = 0;
  6089. }
  6090. isAllPositive = yDomainMin >= 0 && yDomainMax >= 0;
  6091. isAllNegative = yDomainMin <= 0 && yDomainMax <= 0; // Cancel zerobased if axis_*_min / axis_*_max specified
  6092. if (isValue(yMin) && isAllPositive || isValue(yMax) && isAllNegative) {
  6093. isZeroBased = false;
  6094. } // Bar/Area chart should be 0-based if all positive|negative
  6095. if (isZeroBased) {
  6096. if (isAllPositive) {
  6097. yDomainMin = 0;
  6098. }
  6099. if (isAllNegative) {
  6100. yDomainMax = 0;
  6101. }
  6102. }
  6103. domainLength = Math.abs(yDomainMax - yDomainMin);
  6104. padding = padding_top = padding_bottom = domainLength * 0.1;
  6105. if (typeof center !== 'undefined') {
  6106. yDomainAbs = Math.max(Math.abs(yDomainMin), Math.abs(yDomainMax));
  6107. yDomainMax = center + yDomainAbs;
  6108. yDomainMin = center - yDomainAbs;
  6109. } // add padding for data label
  6110. if (showHorizontalDataLabel) {
  6111. lengths = $$.getDataLabelLength(yDomainMin, yDomainMax, 'width');
  6112. diff = diffDomain($$.y.range());
  6113. ratio = [lengths[0] / diff, lengths[1] / diff];
  6114. padding_top += domainLength * (ratio[1] / (1 - ratio[0] - ratio[1]));
  6115. padding_bottom += domainLength * (ratio[0] / (1 - ratio[0] - ratio[1]));
  6116. } else if (showVerticalDataLabel) {
  6117. lengths = $$.getDataLabelLength(yDomainMin, yDomainMax, 'height');
  6118. padding_top += $$.axis.convertPixelsToAxisPadding(lengths[1], domainLength);
  6119. padding_bottom += $$.axis.convertPixelsToAxisPadding(lengths[0], domainLength);
  6120. }
  6121. if (axisId === 'y' && notEmpty(config.axis_y_padding)) {
  6122. padding_top = $$.axis.getPadding(config.axis_y_padding, 'top', padding_top, domainLength);
  6123. padding_bottom = $$.axis.getPadding(config.axis_y_padding, 'bottom', padding_bottom, domainLength);
  6124. }
  6125. if (axisId === 'y2' && notEmpty(config.axis_y2_padding)) {
  6126. padding_top = $$.axis.getPadding(config.axis_y2_padding, 'top', padding_top, domainLength);
  6127. padding_bottom = $$.axis.getPadding(config.axis_y2_padding, 'bottom', padding_bottom, domainLength);
  6128. } // Bar/Area chart should be 0-based if all positive|negative
  6129. if (isZeroBased) {
  6130. if (isAllPositive) {
  6131. padding_bottom = yDomainMin;
  6132. }
  6133. if (isAllNegative) {
  6134. padding_top = -yDomainMax;
  6135. }
  6136. }
  6137. domain = [yDomainMin - padding_bottom, yDomainMax + padding_top];
  6138. return isInverted ? domain.reverse() : domain;
  6139. };
  6140. ChartInternal.prototype.getXDomainMin = function (targets) {
  6141. var $$ = this,
  6142. config = $$.config;
  6143. return isDefined(config.axis_x_min) ? $$.isTimeSeries() ? this.parseDate(config.axis_x_min) : config.axis_x_min : $$.d3.min(targets, function (t) {
  6144. return $$.d3.min(t.values, function (v) {
  6145. return v.x;
  6146. });
  6147. });
  6148. };
  6149. ChartInternal.prototype.getXDomainMax = function (targets) {
  6150. var $$ = this,
  6151. config = $$.config;
  6152. return isDefined(config.axis_x_max) ? $$.isTimeSeries() ? this.parseDate(config.axis_x_max) : config.axis_x_max : $$.d3.max(targets, function (t) {
  6153. return $$.d3.max(t.values, function (v) {
  6154. return v.x;
  6155. });
  6156. });
  6157. };
  6158. ChartInternal.prototype.getXDomainPadding = function (domain) {
  6159. var $$ = this,
  6160. config = $$.config,
  6161. diff = domain[1] - domain[0],
  6162. maxDataCount,
  6163. padding,
  6164. paddingLeft,
  6165. paddingRight;
  6166. if ($$.isCategorized()) {
  6167. padding = 0;
  6168. } else if ($$.hasType('bar')) {
  6169. maxDataCount = $$.getMaxDataCount();
  6170. padding = maxDataCount > 1 ? diff / (maxDataCount - 1) / 2 : 0.5;
  6171. } else {
  6172. padding = diff * 0.01;
  6173. }
  6174. if (_typeof(config.axis_x_padding) === 'object' && notEmpty(config.axis_x_padding)) {
  6175. paddingLeft = isValue(config.axis_x_padding.left) ? config.axis_x_padding.left : padding;
  6176. paddingRight = isValue(config.axis_x_padding.right) ? config.axis_x_padding.right : padding;
  6177. } else if (typeof config.axis_x_padding === 'number') {
  6178. paddingLeft = paddingRight = config.axis_x_padding;
  6179. } else {
  6180. paddingLeft = paddingRight = padding;
  6181. }
  6182. return {
  6183. left: paddingLeft,
  6184. right: paddingRight
  6185. };
  6186. };
  6187. ChartInternal.prototype.getXDomain = function (targets) {
  6188. var $$ = this,
  6189. xDomain = [$$.getXDomainMin(targets), $$.getXDomainMax(targets)],
  6190. firstX = xDomain[0],
  6191. lastX = xDomain[1],
  6192. padding = $$.getXDomainPadding(xDomain),
  6193. min = 0,
  6194. max = 0; // show center of x domain if min and max are the same
  6195. if (firstX - lastX === 0 && !$$.isCategorized()) {
  6196. if ($$.isTimeSeries()) {
  6197. firstX = new Date(firstX.getTime() * 0.5);
  6198. lastX = new Date(lastX.getTime() * 1.5);
  6199. } else {
  6200. firstX = firstX === 0 ? 1 : firstX * 0.5;
  6201. lastX = lastX === 0 ? -1 : lastX * 1.5;
  6202. }
  6203. }
  6204. if (firstX || firstX === 0) {
  6205. min = $$.isTimeSeries() ? new Date(firstX.getTime() - padding.left) : firstX - padding.left;
  6206. }
  6207. if (lastX || lastX === 0) {
  6208. max = $$.isTimeSeries() ? new Date(lastX.getTime() + padding.right) : lastX + padding.right;
  6209. }
  6210. return [min, max];
  6211. };
  6212. ChartInternal.prototype.updateXDomain = function (targets, withUpdateXDomain, withUpdateOrgXDomain, withTrim, domain) {
  6213. var $$ = this,
  6214. config = $$.config;
  6215. if (withUpdateOrgXDomain) {
  6216. $$.x.domain(domain ? domain : $$.d3.extent($$.getXDomain(targets)));
  6217. $$.orgXDomain = $$.x.domain();
  6218. if (config.zoom_enabled) {
  6219. $$.zoom.update();
  6220. }
  6221. $$.subX.domain($$.x.domain());
  6222. if ($$.brush) {
  6223. $$.brush.updateScale($$.subX);
  6224. }
  6225. }
  6226. if (withUpdateXDomain) {
  6227. $$.x.domain(domain ? domain : !$$.brush || $$.brush.empty() ? $$.orgXDomain : $$.brush.selectionAsValue());
  6228. } // Trim domain when too big by zoom mousemove event
  6229. if (withTrim) {
  6230. $$.x.domain($$.trimXDomain($$.x.orgDomain()));
  6231. }
  6232. return $$.x.domain();
  6233. };
  6234. ChartInternal.prototype.trimXDomain = function (domain) {
  6235. var zoomDomain = this.getZoomDomain(),
  6236. min = zoomDomain[0],
  6237. max = zoomDomain[1];
  6238. if (domain[0] <= min) {
  6239. domain[1] = +domain[1] + (min - domain[0]);
  6240. domain[0] = min;
  6241. }
  6242. if (max <= domain[1]) {
  6243. domain[0] = +domain[0] - (domain[1] - max);
  6244. domain[1] = max;
  6245. }
  6246. return domain;
  6247. };
  6248. ChartInternal.prototype.drag = function (mouse) {
  6249. var $$ = this,
  6250. config = $$.config,
  6251. main = $$.main,
  6252. d3 = $$.d3;
  6253. var sx, sy, mx, my, minX, maxX, minY, maxY;
  6254. if ($$.hasArcType()) {
  6255. return;
  6256. }
  6257. if (!config.data_selection_enabled) {
  6258. return;
  6259. } // do nothing if not selectable
  6260. if (!config.data_selection_multiple) {
  6261. return;
  6262. } // skip when single selection because drag is used for multiple selection
  6263. sx = $$.dragStart[0];
  6264. sy = $$.dragStart[1];
  6265. mx = mouse[0];
  6266. my = mouse[1];
  6267. minX = Math.min(sx, mx);
  6268. maxX = Math.max(sx, mx);
  6269. minY = config.data_selection_grouped ? $$.margin.top : Math.min(sy, my);
  6270. maxY = config.data_selection_grouped ? $$.height : Math.max(sy, my);
  6271. main.select('.' + CLASS.dragarea).attr('x', minX).attr('y', minY).attr('width', maxX - minX).attr('height', maxY - minY); // TODO: binary search when multiple xs
  6272. main.selectAll('.' + CLASS.shapes).selectAll('.' + CLASS.shape).filter(function (d) {
  6273. return config.data_selection_isselectable(d);
  6274. }).each(function (d, i) {
  6275. var shape = d3.select(this),
  6276. isSelected = shape.classed(CLASS.SELECTED),
  6277. isIncluded = shape.classed(CLASS.INCLUDED),
  6278. _x,
  6279. _y,
  6280. _w,
  6281. _h,
  6282. toggle,
  6283. isWithin = false,
  6284. box;
  6285. if (shape.classed(CLASS.circle)) {
  6286. _x = shape.attr("cx") * 1;
  6287. _y = shape.attr("cy") * 1;
  6288. toggle = $$.togglePoint;
  6289. isWithin = minX < _x && _x < maxX && minY < _y && _y < maxY;
  6290. } else if (shape.classed(CLASS.bar)) {
  6291. box = getPathBox(this);
  6292. _x = box.x;
  6293. _y = box.y;
  6294. _w = box.width;
  6295. _h = box.height;
  6296. toggle = $$.togglePath;
  6297. isWithin = !(maxX < _x || _x + _w < minX) && !(maxY < _y || _y + _h < minY);
  6298. } else {
  6299. // line/area selection not supported yet
  6300. return;
  6301. }
  6302. if (isWithin ^ isIncluded) {
  6303. shape.classed(CLASS.INCLUDED, !isIncluded); // TODO: included/unincluded callback here
  6304. shape.classed(CLASS.SELECTED, !isSelected);
  6305. toggle.call($$, !isSelected, shape, d, i);
  6306. }
  6307. });
  6308. };
  6309. ChartInternal.prototype.dragstart = function (mouse) {
  6310. var $$ = this,
  6311. config = $$.config;
  6312. if ($$.hasArcType()) {
  6313. return;
  6314. }
  6315. if (!config.data_selection_enabled) {
  6316. return;
  6317. } // do nothing if not selectable
  6318. $$.dragStart = mouse;
  6319. $$.main.select('.' + CLASS.chart).append('rect').attr('class', CLASS.dragarea).style('opacity', 0.1);
  6320. $$.dragging = true;
  6321. };
  6322. ChartInternal.prototype.dragend = function () {
  6323. var $$ = this,
  6324. config = $$.config;
  6325. if ($$.hasArcType()) {
  6326. return;
  6327. }
  6328. if (!config.data_selection_enabled) {
  6329. return;
  6330. } // do nothing if not selectable
  6331. $$.main.select('.' + CLASS.dragarea).transition().duration(100).style('opacity', 0).remove();
  6332. $$.main.selectAll('.' + CLASS.shape).classed(CLASS.INCLUDED, false);
  6333. $$.dragging = false;
  6334. };
  6335. ChartInternal.prototype.getYFormat = function (forArc) {
  6336. var $$ = this,
  6337. formatForY = forArc && !$$.hasType('gauge') ? $$.defaultArcValueFormat : $$.yFormat,
  6338. formatForY2 = forArc && !$$.hasType('gauge') ? $$.defaultArcValueFormat : $$.y2Format;
  6339. return function (v, ratio, id) {
  6340. var format = $$.axis.getId(id) === 'y2' ? formatForY2 : formatForY;
  6341. return format.call($$, v, ratio);
  6342. };
  6343. };
  6344. ChartInternal.prototype.yFormat = function (v) {
  6345. var $$ = this,
  6346. config = $$.config,
  6347. format = config.axis_y_tick_format ? config.axis_y_tick_format : $$.defaultValueFormat;
  6348. return format(v);
  6349. };
  6350. ChartInternal.prototype.y2Format = function (v) {
  6351. var $$ = this,
  6352. config = $$.config,
  6353. format = config.axis_y2_tick_format ? config.axis_y2_tick_format : $$.defaultValueFormat;
  6354. return format(v);
  6355. };
  6356. ChartInternal.prototype.defaultValueFormat = function (v) {
  6357. return isValue(v) ? +v : "";
  6358. };
  6359. ChartInternal.prototype.defaultArcValueFormat = function (v, ratio) {
  6360. return (ratio * 100).toFixed(1) + '%';
  6361. };
  6362. ChartInternal.prototype.dataLabelFormat = function (targetId) {
  6363. var $$ = this,
  6364. data_labels = $$.config.data_labels,
  6365. format,
  6366. defaultFormat = function defaultFormat(v) {
  6367. return isValue(v) ? +v : "";
  6368. }; // find format according to axis id
  6369. if (typeof data_labels.format === 'function') {
  6370. format = data_labels.format;
  6371. } else if (_typeof(data_labels.format) === 'object') {
  6372. if (data_labels.format[targetId]) {
  6373. format = data_labels.format[targetId] === true ? defaultFormat : data_labels.format[targetId];
  6374. } else {
  6375. format = function format() {
  6376. return '';
  6377. };
  6378. }
  6379. } else {
  6380. format = defaultFormat;
  6381. }
  6382. return format;
  6383. };
  6384. ChartInternal.prototype.initGrid = function () {
  6385. var $$ = this,
  6386. config = $$.config,
  6387. d3 = $$.d3;
  6388. $$.grid = $$.main.append('g').attr("clip-path", $$.clipPathForGrid).attr('class', CLASS.grid);
  6389. if (config.grid_x_show) {
  6390. $$.grid.append("g").attr("class", CLASS.xgrids);
  6391. }
  6392. if (config.grid_y_show) {
  6393. $$.grid.append('g').attr('class', CLASS.ygrids);
  6394. }
  6395. if (config.grid_focus_show) {
  6396. $$.grid.append('g').attr("class", CLASS.xgridFocus).append('line').attr('class', CLASS.xgridFocus);
  6397. }
  6398. $$.xgrid = d3.selectAll([]);
  6399. if (!config.grid_lines_front) {
  6400. $$.initGridLines();
  6401. }
  6402. };
  6403. ChartInternal.prototype.initGridLines = function () {
  6404. var $$ = this,
  6405. d3 = $$.d3;
  6406. $$.gridLines = $$.main.append('g').attr("clip-path", $$.clipPathForGrid).attr('class', CLASS.grid + ' ' + CLASS.gridLines);
  6407. $$.gridLines.append('g').attr("class", CLASS.xgridLines);
  6408. $$.gridLines.append('g').attr('class', CLASS.ygridLines);
  6409. $$.xgridLines = d3.selectAll([]);
  6410. };
  6411. ChartInternal.prototype.updateXGrid = function (withoutUpdate) {
  6412. var $$ = this,
  6413. config = $$.config,
  6414. d3 = $$.d3,
  6415. xgridData = $$.generateGridData(config.grid_x_type, $$.x),
  6416. tickOffset = $$.isCategorized() ? $$.xAxis.tickOffset() : 0;
  6417. $$.xgridAttr = config.axis_rotated ? {
  6418. 'x1': 0,
  6419. 'x2': $$.width,
  6420. 'y1': function y1(d) {
  6421. return $$.x(d) - tickOffset;
  6422. },
  6423. 'y2': function y2(d) {
  6424. return $$.x(d) - tickOffset;
  6425. }
  6426. } : {
  6427. 'x1': function x1(d) {
  6428. return $$.x(d) + tickOffset;
  6429. },
  6430. 'x2': function x2(d) {
  6431. return $$.x(d) + tickOffset;
  6432. },
  6433. 'y1': 0,
  6434. 'y2': $$.height
  6435. };
  6436. $$.xgridAttr.opacity = function () {
  6437. var pos = +d3.select(this).attr(config.axis_rotated ? 'y1' : 'x1');
  6438. return pos === (config.axis_rotated ? $$.height : 0) ? 0 : 1;
  6439. };
  6440. var xgrid = $$.main.select('.' + CLASS.xgrids).selectAll('.' + CLASS.xgrid).data(xgridData);
  6441. var xgridEnter = xgrid.enter().append('line').attr("class", CLASS.xgrid).attr('x1', $$.xgridAttr.x1).attr('x2', $$.xgridAttr.x2).attr('y1', $$.xgridAttr.y1).attr('y2', $$.xgridAttr.y2).style("opacity", 0);
  6442. $$.xgrid = xgridEnter.merge(xgrid);
  6443. if (!withoutUpdate) {
  6444. $$.xgrid.attr('x1', $$.xgridAttr.x1).attr('x2', $$.xgridAttr.x2).attr('y1', $$.xgridAttr.y1).attr('y2', $$.xgridAttr.y2).style("opacity", $$.xgridAttr.opacity);
  6445. }
  6446. xgrid.exit().remove();
  6447. };
  6448. ChartInternal.prototype.updateYGrid = function () {
  6449. var $$ = this,
  6450. config = $$.config,
  6451. gridValues = $$.yAxis.tickValues() || $$.y.ticks(config.grid_y_ticks);
  6452. var ygrid = $$.main.select('.' + CLASS.ygrids).selectAll('.' + CLASS.ygrid).data(gridValues);
  6453. var ygridEnter = ygrid.enter().append('line') // TODO: x1, x2, y1, y2, opacity need to be set here maybe
  6454. .attr('class', CLASS.ygrid);
  6455. $$.ygrid = ygridEnter.merge(ygrid);
  6456. $$.ygrid.attr("x1", config.axis_rotated ? $$.y : 0).attr("x2", config.axis_rotated ? $$.y : $$.width).attr("y1", config.axis_rotated ? 0 : $$.y).attr("y2", config.axis_rotated ? $$.height : $$.y);
  6457. ygrid.exit().remove();
  6458. $$.smoothLines($$.ygrid, 'grid');
  6459. };
  6460. ChartInternal.prototype.gridTextAnchor = function (d) {
  6461. return d.position ? d.position : "end";
  6462. };
  6463. ChartInternal.prototype.gridTextDx = function (d) {
  6464. return d.position === 'start' ? 4 : d.position === 'middle' ? 0 : -4;
  6465. };
  6466. ChartInternal.prototype.xGridTextX = function (d) {
  6467. return d.position === 'start' ? -this.height : d.position === 'middle' ? -this.height / 2 : 0;
  6468. };
  6469. ChartInternal.prototype.yGridTextX = function (d) {
  6470. return d.position === 'start' ? 0 : d.position === 'middle' ? this.width / 2 : this.width;
  6471. };
  6472. ChartInternal.prototype.updateGrid = function (duration) {
  6473. var $$ = this,
  6474. main = $$.main,
  6475. config = $$.config,
  6476. xgridLine,
  6477. xgridLineEnter,
  6478. ygridLine,
  6479. ygridLineEnter,
  6480. xv = $$.xv.bind($$),
  6481. yv = $$.yv.bind($$),
  6482. xGridTextX = $$.xGridTextX.bind($$),
  6483. yGridTextX = $$.yGridTextX.bind($$); // hide if arc type
  6484. $$.grid.style('visibility', $$.hasArcType() ? 'hidden' : 'visible');
  6485. main.select('line.' + CLASS.xgridFocus).style("visibility", "hidden");
  6486. if (config.grid_x_show) {
  6487. $$.updateXGrid();
  6488. }
  6489. xgridLine = main.select('.' + CLASS.xgridLines).selectAll('.' + CLASS.xgridLine).data(config.grid_x_lines); // enter
  6490. xgridLineEnter = xgridLine.enter().append('g').attr("class", function (d) {
  6491. return CLASS.xgridLine + (d['class'] ? ' ' + d['class'] : '');
  6492. });
  6493. xgridLineEnter.append('line').attr("x1", config.axis_rotated ? 0 : xv).attr("x2", config.axis_rotated ? $$.width : xv).attr("y1", config.axis_rotated ? xv : 0).attr("y2", config.axis_rotated ? xv : $$.height).style("opacity", 0);
  6494. xgridLineEnter.append('text').attr("text-anchor", $$.gridTextAnchor).attr("transform", config.axis_rotated ? "" : "rotate(-90)").attr("x", config.axis_rotated ? yGridTextX : xGridTextX).attr("y", xv).attr('dx', $$.gridTextDx).attr('dy', -5).style("opacity", 0); // udpate
  6495. $$.xgridLines = xgridLineEnter.merge(xgridLine); // done in d3.transition() of the end of this function
  6496. // exit
  6497. xgridLine.exit().transition().duration(duration).style("opacity", 0).remove(); // Y-Grid
  6498. if (config.grid_y_show) {
  6499. $$.updateYGrid();
  6500. }
  6501. ygridLine = main.select('.' + CLASS.ygridLines).selectAll('.' + CLASS.ygridLine).data(config.grid_y_lines); // enter
  6502. ygridLineEnter = ygridLine.enter().append('g').attr("class", function (d) {
  6503. return CLASS.ygridLine + (d['class'] ? ' ' + d['class'] : '');
  6504. });
  6505. ygridLineEnter.append('line').attr("x1", config.axis_rotated ? yv : 0).attr("x2", config.axis_rotated ? yv : $$.width).attr("y1", config.axis_rotated ? 0 : yv).attr("y2", config.axis_rotated ? $$.height : yv).style("opacity", 0);
  6506. ygridLineEnter.append('text').attr("text-anchor", $$.gridTextAnchor).attr("transform", config.axis_rotated ? "rotate(-90)" : "").attr("x", config.axis_rotated ? xGridTextX : yGridTextX).attr("y", yv).attr('dx', $$.gridTextDx).attr('dy', -5).style("opacity", 0); // update
  6507. $$.ygridLines = ygridLineEnter.merge(ygridLine);
  6508. $$.ygridLines.select('line').transition().duration(duration).attr("x1", config.axis_rotated ? yv : 0).attr("x2", config.axis_rotated ? yv : $$.width).attr("y1", config.axis_rotated ? 0 : yv).attr("y2", config.axis_rotated ? $$.height : yv).style("opacity", 1);
  6509. $$.ygridLines.select('text').transition().duration(duration).attr("x", config.axis_rotated ? $$.xGridTextX.bind($$) : $$.yGridTextX.bind($$)).attr("y", yv).text(function (d) {
  6510. return d.text;
  6511. }).style("opacity", 1); // exit
  6512. ygridLine.exit().transition().duration(duration).style("opacity", 0).remove();
  6513. };
  6514. ChartInternal.prototype.redrawGrid = function (withTransition, transition) {
  6515. var $$ = this,
  6516. config = $$.config,
  6517. xv = $$.xv.bind($$),
  6518. lines = $$.xgridLines.select('line'),
  6519. texts = $$.xgridLines.select('text');
  6520. return [(withTransition ? lines.transition(transition) : lines).attr("x1", config.axis_rotated ? 0 : xv).attr("x2", config.axis_rotated ? $$.width : xv).attr("y1", config.axis_rotated ? xv : 0).attr("y2", config.axis_rotated ? xv : $$.height).style("opacity", 1), (withTransition ? texts.transition(transition) : texts).attr("x", config.axis_rotated ? $$.yGridTextX.bind($$) : $$.xGridTextX.bind($$)).attr("y", xv).text(function (d) {
  6521. return d.text;
  6522. }).style("opacity", 1)];
  6523. };
  6524. ChartInternal.prototype.showXGridFocus = function (selectedData) {
  6525. var $$ = this,
  6526. config = $$.config,
  6527. dataToShow = selectedData.filter(function (d) {
  6528. return d && isValue(d.value);
  6529. }),
  6530. focusEl = $$.main.selectAll('line.' + CLASS.xgridFocus),
  6531. xx = $$.xx.bind($$);
  6532. if (!config.tooltip_show) {
  6533. return;
  6534. } // Hide when scatter plot exists
  6535. if ($$.hasType('scatter') || $$.hasArcType()) {
  6536. return;
  6537. }
  6538. focusEl.style("visibility", "visible").data([dataToShow[0]]).attr(config.axis_rotated ? 'y1' : 'x1', xx).attr(config.axis_rotated ? 'y2' : 'x2', xx);
  6539. $$.smoothLines(focusEl, 'grid');
  6540. };
  6541. ChartInternal.prototype.hideXGridFocus = function () {
  6542. this.main.select('line.' + CLASS.xgridFocus).style("visibility", "hidden");
  6543. };
  6544. ChartInternal.prototype.updateXgridFocus = function () {
  6545. var $$ = this,
  6546. config = $$.config;
  6547. $$.main.select('line.' + CLASS.xgridFocus).attr("x1", config.axis_rotated ? 0 : -10).attr("x2", config.axis_rotated ? $$.width : -10).attr("y1", config.axis_rotated ? -10 : 0).attr("y2", config.axis_rotated ? -10 : $$.height);
  6548. };
  6549. ChartInternal.prototype.generateGridData = function (type, scale) {
  6550. var $$ = this,
  6551. gridData = [],
  6552. xDomain,
  6553. firstYear,
  6554. lastYear,
  6555. i,
  6556. tickNum = $$.main.select("." + CLASS.axisX).selectAll('.tick').size();
  6557. if (type === 'year') {
  6558. xDomain = $$.getXDomain();
  6559. firstYear = xDomain[0].getFullYear();
  6560. lastYear = xDomain[1].getFullYear();
  6561. for (i = firstYear; i <= lastYear; i++) {
  6562. gridData.push(new Date(i + '-01-01 00:00:00'));
  6563. }
  6564. } else {
  6565. gridData = scale.ticks(10);
  6566. if (gridData.length > tickNum) {
  6567. // use only int
  6568. gridData = gridData.filter(function (d) {
  6569. return ("" + d).indexOf('.') < 0;
  6570. });
  6571. }
  6572. }
  6573. return gridData;
  6574. };
  6575. ChartInternal.prototype.getGridFilterToRemove = function (params) {
  6576. return params ? function (line) {
  6577. var found = false;
  6578. [].concat(params).forEach(function (param) {
  6579. if ('value' in param && line.value === param.value || 'class' in param && line['class'] === param['class']) {
  6580. found = true;
  6581. }
  6582. });
  6583. return found;
  6584. } : function () {
  6585. return true;
  6586. };
  6587. };
  6588. ChartInternal.prototype.removeGridLines = function (params, forX) {
  6589. var $$ = this,
  6590. config = $$.config,
  6591. toRemove = $$.getGridFilterToRemove(params),
  6592. toShow = function toShow(line) {
  6593. return !toRemove(line);
  6594. },
  6595. classLines = forX ? CLASS.xgridLines : CLASS.ygridLines,
  6596. classLine = forX ? CLASS.xgridLine : CLASS.ygridLine;
  6597. $$.main.select('.' + classLines).selectAll('.' + classLine).filter(toRemove).transition().duration(config.transition_duration).style('opacity', 0).remove();
  6598. if (forX) {
  6599. config.grid_x_lines = config.grid_x_lines.filter(toShow);
  6600. } else {
  6601. config.grid_y_lines = config.grid_y_lines.filter(toShow);
  6602. }
  6603. };
  6604. ChartInternal.prototype.initEventRect = function () {
  6605. var $$ = this,
  6606. config = $$.config;
  6607. $$.main.select('.' + CLASS.chart).append("g").attr("class", CLASS.eventRects).style('fill-opacity', 0);
  6608. $$.eventRect = $$.main.select('.' + CLASS.eventRects).append('rect').attr('class', CLASS.eventRect); // event rect handle zoom event as well
  6609. if (config.zoom_enabled && $$.zoom) {
  6610. $$.eventRect.call($$.zoom).on("dblclick.zoom", null);
  6611. if (config.zoom_initialRange) {
  6612. // WORKAROUND: Add transition to apply transform immediately when no subchart
  6613. $$.eventRect.transition().duration(0).call($$.zoom.transform, $$.zoomTransform(config.zoom_initialRange));
  6614. }
  6615. }
  6616. };
  6617. ChartInternal.prototype.redrawEventRect = function () {
  6618. var $$ = this,
  6619. d3 = $$.d3,
  6620. config = $$.config,
  6621. x,
  6622. y,
  6623. w,
  6624. h; // TODO: rotated not supported yet
  6625. x = 0;
  6626. y = 0;
  6627. w = $$.width;
  6628. h = $$.height;
  6629. function mouseout() {
  6630. $$.svg.select('.' + CLASS.eventRect).style('cursor', null);
  6631. $$.hideXGridFocus();
  6632. $$.hideTooltip();
  6633. $$.unexpandCircles();
  6634. $$.unexpandBars();
  6635. } // rects for mouseover
  6636. $$.main.select('.' + CLASS.eventRects).style('cursor', config.zoom_enabled ? config.axis_rotated ? 'ns-resize' : 'ew-resize' : null);
  6637. $$.eventRect.attr('x', x).attr('y', y).attr('width', w).attr('height', h).on('mouseout', config.interaction_enabled ? function () {
  6638. if (!config) {
  6639. return;
  6640. } // chart is destroyed
  6641. if ($$.hasArcType()) {
  6642. return;
  6643. }
  6644. mouseout();
  6645. } : null).on('mousemove', config.interaction_enabled ? function () {
  6646. var targetsToShow, mouse, closest, sameXData, selectedData;
  6647. if ($$.dragging) {
  6648. return;
  6649. } // do nothing when dragging
  6650. if ($$.hasArcType(targetsToShow)) {
  6651. return;
  6652. }
  6653. targetsToShow = $$.filterTargetsToShow($$.data.targets);
  6654. mouse = d3.mouse(this);
  6655. closest = $$.findClosestFromTargets(targetsToShow, mouse);
  6656. if ($$.mouseover && (!closest || closest.id !== $$.mouseover.id)) {
  6657. config.data_onmouseout.call($$.api, $$.mouseover);
  6658. $$.mouseover = undefined;
  6659. }
  6660. if (!closest) {
  6661. mouseout();
  6662. return;
  6663. }
  6664. if ($$.isScatterType(closest) || !config.tooltip_grouped) {
  6665. sameXData = [closest];
  6666. } else {
  6667. sameXData = $$.filterByX(targetsToShow, closest.x);
  6668. } // show tooltip when cursor is close to some point
  6669. selectedData = sameXData.map(function (d) {
  6670. return $$.addName(d);
  6671. });
  6672. $$.showTooltip(selectedData, this); // expand points
  6673. if (config.point_focus_expand_enabled) {
  6674. $$.unexpandCircles();
  6675. selectedData.forEach(function (d) {
  6676. $$.expandCircles(d.index, d.id, false);
  6677. });
  6678. }
  6679. $$.expandBars(closest.index, closest.id, true); // Show xgrid focus line
  6680. $$.showXGridFocus(selectedData); // Show cursor as pointer if point is close to mouse position
  6681. if ($$.isBarType(closest.id) || $$.dist(closest, mouse) < config.point_sensitivity) {
  6682. $$.svg.select('.' + CLASS.eventRect).style('cursor', 'pointer');
  6683. if (!$$.mouseover) {
  6684. config.data_onmouseover.call($$.api, closest);
  6685. $$.mouseover = closest;
  6686. }
  6687. }
  6688. } : null).on('click', config.interaction_enabled ? function () {
  6689. var targetsToShow, mouse, closest, sameXData;
  6690. if ($$.hasArcType(targetsToShow)) {
  6691. return;
  6692. }
  6693. targetsToShow = $$.filterTargetsToShow($$.data.targets);
  6694. mouse = d3.mouse(this);
  6695. closest = $$.findClosestFromTargets(targetsToShow, mouse);
  6696. if (!closest) {
  6697. return;
  6698. } // select if selection enabled
  6699. if ($$.isBarType(closest.id) || $$.dist(closest, mouse) < config.point_sensitivity) {
  6700. if ($$.isScatterType(closest) || !config.data_selection_grouped) {
  6701. sameXData = [closest];
  6702. } else {
  6703. sameXData = $$.filterByX(targetsToShow, closest.x);
  6704. }
  6705. sameXData.forEach(function (d) {
  6706. $$.main.selectAll('.' + CLASS.shapes + $$.getTargetSelectorSuffix(d.id)).selectAll('.' + CLASS.shape + '-' + d.index).each(function () {
  6707. if (config.data_selection_grouped || $$.isWithinShape(this, d)) {
  6708. $$.toggleShape(this, d, d.index);
  6709. config.data_onclick.call($$.api, d, this);
  6710. }
  6711. });
  6712. });
  6713. }
  6714. } : null).call(config.interaction_enabled && config.data_selection_draggable && $$.drag ? d3.drag().on('drag', function () {
  6715. $$.drag(d3.mouse(this));
  6716. }).on('start', function () {
  6717. $$.dragstart(d3.mouse(this));
  6718. }).on('end', function () {
  6719. $$.dragend();
  6720. }) : function () {});
  6721. };
  6722. ChartInternal.prototype.getMousePosition = function (data) {
  6723. var $$ = this;
  6724. return [$$.x(data.x), $$.getYScale(data.id)(data.value)];
  6725. };
  6726. ChartInternal.prototype.dispatchEvent = function (type, mouse) {
  6727. var $$ = this,
  6728. selector = '.' + CLASS.eventRect,
  6729. eventRect = $$.main.select(selector).node(),
  6730. box = eventRect.getBoundingClientRect(),
  6731. x = box.left + (mouse ? mouse[0] : 0),
  6732. y = box.top + (mouse ? mouse[1] : 0),
  6733. event = document.createEvent("MouseEvents");
  6734. event.initMouseEvent(type, true, true, window, 0, x, y, x, y, false, false, false, false, 0, null);
  6735. eventRect.dispatchEvent(event);
  6736. };
  6737. ChartInternal.prototype.initLegend = function () {
  6738. var $$ = this;
  6739. $$.legendItemTextBox = {};
  6740. $$.legendHasRendered = false;
  6741. $$.legend = $$.svg.append("g").attr("transform", $$.getTranslate('legend'));
  6742. if (!$$.config.legend_show) {
  6743. $$.legend.style('visibility', 'hidden');
  6744. $$.hiddenLegendIds = $$.mapToIds($$.data.targets);
  6745. return;
  6746. } // MEMO: call here to update legend box and tranlate for all
  6747. // MEMO: translate will be upated by this, so transform not needed in updateLegend()
  6748. $$.updateLegendWithDefaults();
  6749. };
  6750. ChartInternal.prototype.updateLegendWithDefaults = function () {
  6751. var $$ = this;
  6752. $$.updateLegend($$.mapToIds($$.data.targets), {
  6753. withTransform: false,
  6754. withTransitionForTransform: false,
  6755. withTransition: false
  6756. });
  6757. };
  6758. ChartInternal.prototype.updateSizeForLegend = function (legendHeight, legendWidth) {
  6759. var $$ = this,
  6760. config = $$.config,
  6761. insetLegendPosition = {
  6762. top: $$.isLegendTop ? $$.getCurrentPaddingTop() + config.legend_inset_y + 5.5 : $$.currentHeight - legendHeight - $$.getCurrentPaddingBottom() - config.legend_inset_y,
  6763. left: $$.isLegendLeft ? $$.getCurrentPaddingLeft() + config.legend_inset_x + 0.5 : $$.currentWidth - legendWidth - $$.getCurrentPaddingRight() - config.legend_inset_x + 0.5
  6764. };
  6765. $$.margin3 = {
  6766. top: $$.isLegendRight ? 0 : $$.isLegendInset ? insetLegendPosition.top : $$.currentHeight - legendHeight,
  6767. right: NaN,
  6768. bottom: 0,
  6769. left: $$.isLegendRight ? $$.currentWidth - legendWidth : $$.isLegendInset ? insetLegendPosition.left : 0
  6770. };
  6771. };
  6772. ChartInternal.prototype.transformLegend = function (withTransition) {
  6773. var $$ = this;
  6774. (withTransition ? $$.legend.transition() : $$.legend).attr("transform", $$.getTranslate('legend'));
  6775. };
  6776. ChartInternal.prototype.updateLegendStep = function (step) {
  6777. this.legendStep = step;
  6778. };
  6779. ChartInternal.prototype.updateLegendItemWidth = function (w) {
  6780. this.legendItemWidth = w;
  6781. };
  6782. ChartInternal.prototype.updateLegendItemHeight = function (h) {
  6783. this.legendItemHeight = h;
  6784. };
  6785. ChartInternal.prototype.getLegendWidth = function () {
  6786. var $$ = this;
  6787. return $$.config.legend_show ? $$.isLegendRight || $$.isLegendInset ? $$.legendItemWidth * ($$.legendStep + 1) : $$.currentWidth : 0;
  6788. };
  6789. ChartInternal.prototype.getLegendHeight = function () {
  6790. var $$ = this,
  6791. h = 0;
  6792. if ($$.config.legend_show) {
  6793. if ($$.isLegendRight) {
  6794. h = $$.currentHeight;
  6795. } else {
  6796. h = Math.max(20, $$.legendItemHeight) * ($$.legendStep + 1);
  6797. }
  6798. }
  6799. return h;
  6800. };
  6801. ChartInternal.prototype.opacityForLegend = function (legendItem) {
  6802. return legendItem.classed(CLASS.legendItemHidden) ? null : 1;
  6803. };
  6804. ChartInternal.prototype.opacityForUnfocusedLegend = function (legendItem) {
  6805. return legendItem.classed(CLASS.legendItemHidden) ? null : 0.3;
  6806. };
  6807. ChartInternal.prototype.toggleFocusLegend = function (targetIds, focus) {
  6808. var $$ = this;
  6809. targetIds = $$.mapToTargetIds(targetIds);
  6810. $$.legend.selectAll('.' + CLASS.legendItem).filter(function (id) {
  6811. return targetIds.indexOf(id) >= 0;
  6812. }).classed(CLASS.legendItemFocused, focus).transition().duration(100).style('opacity', function () {
  6813. var opacity = focus ? $$.opacityForLegend : $$.opacityForUnfocusedLegend;
  6814. return opacity.call($$, $$.d3.select(this));
  6815. });
  6816. };
  6817. ChartInternal.prototype.revertLegend = function () {
  6818. var $$ = this,
  6819. d3 = $$.d3;
  6820. $$.legend.selectAll('.' + CLASS.legendItem).classed(CLASS.legendItemFocused, false).transition().duration(100).style('opacity', function () {
  6821. return $$.opacityForLegend(d3.select(this));
  6822. });
  6823. };
  6824. ChartInternal.prototype.showLegend = function (targetIds) {
  6825. var $$ = this,
  6826. config = $$.config;
  6827. if (!config.legend_show) {
  6828. config.legend_show = true;
  6829. $$.legend.style('visibility', 'visible');
  6830. if (!$$.legendHasRendered) {
  6831. $$.updateLegendWithDefaults();
  6832. }
  6833. }
  6834. $$.removeHiddenLegendIds(targetIds);
  6835. $$.legend.selectAll($$.selectorLegends(targetIds)).style('visibility', 'visible').transition().style('opacity', function () {
  6836. return $$.opacityForLegend($$.d3.select(this));
  6837. });
  6838. };
  6839. ChartInternal.prototype.hideLegend = function (targetIds) {
  6840. var $$ = this,
  6841. config = $$.config;
  6842. if (config.legend_show && isEmpty(targetIds)) {
  6843. config.legend_show = false;
  6844. $$.legend.style('visibility', 'hidden');
  6845. }
  6846. $$.addHiddenLegendIds(targetIds);
  6847. $$.legend.selectAll($$.selectorLegends(targetIds)).style('opacity', 0).style('visibility', 'hidden');
  6848. };
  6849. ChartInternal.prototype.clearLegendItemTextBoxCache = function () {
  6850. this.legendItemTextBox = {};
  6851. };
  6852. ChartInternal.prototype.updateLegend = function (targetIds, options, transitions) {
  6853. var $$ = this,
  6854. config = $$.config;
  6855. var xForLegend, xForLegendText, xForLegendRect, yForLegend, yForLegendText, yForLegendRect, x1ForLegendTile, x2ForLegendTile, yForLegendTile;
  6856. var paddingTop = 4,
  6857. paddingRight = 10,
  6858. maxWidth = 0,
  6859. maxHeight = 0,
  6860. posMin = 10,
  6861. tileWidth = config.legend_item_tile_width + 5;
  6862. var l,
  6863. totalLength = 0,
  6864. offsets = {},
  6865. widths = {},
  6866. heights = {},
  6867. margins = [0],
  6868. steps = {},
  6869. step = 0;
  6870. var withTransition, withTransitionForTransform;
  6871. var texts, rects, tiles, background; // Skip elements when their name is set to null
  6872. targetIds = targetIds.filter(function (id) {
  6873. return !isDefined(config.data_names[id]) || config.data_names[id] !== null;
  6874. });
  6875. options = options || {};
  6876. withTransition = getOption(options, "withTransition", true);
  6877. withTransitionForTransform = getOption(options, "withTransitionForTransform", true);
  6878. function getTextBox(textElement, id) {
  6879. if (!$$.legendItemTextBox[id]) {
  6880. $$.legendItemTextBox[id] = $$.getTextRect(textElement.textContent, CLASS.legendItem, textElement);
  6881. }
  6882. return $$.legendItemTextBox[id];
  6883. }
  6884. function updatePositions(textElement, id, index) {
  6885. var reset = index === 0,
  6886. isLast = index === targetIds.length - 1,
  6887. box = getTextBox(textElement, id),
  6888. itemWidth = box.width + tileWidth + (isLast && !($$.isLegendRight || $$.isLegendInset) ? 0 : paddingRight) + config.legend_padding,
  6889. itemHeight = box.height + paddingTop,
  6890. itemLength = $$.isLegendRight || $$.isLegendInset ? itemHeight : itemWidth,
  6891. areaLength = $$.isLegendRight || $$.isLegendInset ? $$.getLegendHeight() : $$.getLegendWidth(),
  6892. margin,
  6893. maxLength; // MEMO: care about condifion of step, totalLength
  6894. function updateValues(id, withoutStep) {
  6895. if (!withoutStep) {
  6896. margin = (areaLength - totalLength - itemLength) / 2;
  6897. if (margin < posMin) {
  6898. margin = (areaLength - itemLength) / 2;
  6899. totalLength = 0;
  6900. step++;
  6901. }
  6902. }
  6903. steps[id] = step;
  6904. margins[step] = $$.isLegendInset ? 10 : margin;
  6905. offsets[id] = totalLength;
  6906. totalLength += itemLength;
  6907. }
  6908. if (reset) {
  6909. totalLength = 0;
  6910. step = 0;
  6911. maxWidth = 0;
  6912. maxHeight = 0;
  6913. }
  6914. if (config.legend_show && !$$.isLegendToShow(id)) {
  6915. widths[id] = heights[id] = steps[id] = offsets[id] = 0;
  6916. return;
  6917. }
  6918. widths[id] = itemWidth;
  6919. heights[id] = itemHeight;
  6920. if (!maxWidth || itemWidth >= maxWidth) {
  6921. maxWidth = itemWidth;
  6922. }
  6923. if (!maxHeight || itemHeight >= maxHeight) {
  6924. maxHeight = itemHeight;
  6925. }
  6926. maxLength = $$.isLegendRight || $$.isLegendInset ? maxHeight : maxWidth;
  6927. if (config.legend_equally) {
  6928. Object.keys(widths).forEach(function (id) {
  6929. widths[id] = maxWidth;
  6930. });
  6931. Object.keys(heights).forEach(function (id) {
  6932. heights[id] = maxHeight;
  6933. });
  6934. margin = (areaLength - maxLength * targetIds.length) / 2;
  6935. if (margin < posMin) {
  6936. totalLength = 0;
  6937. step = 0;
  6938. targetIds.forEach(function (id) {
  6939. updateValues(id);
  6940. });
  6941. } else {
  6942. updateValues(id, true);
  6943. }
  6944. } else {
  6945. updateValues(id);
  6946. }
  6947. }
  6948. if ($$.isLegendInset) {
  6949. step = config.legend_inset_step ? config.legend_inset_step : targetIds.length;
  6950. $$.updateLegendStep(step);
  6951. }
  6952. if ($$.isLegendRight) {
  6953. xForLegend = function xForLegend(id) {
  6954. return maxWidth * steps[id];
  6955. };
  6956. yForLegend = function yForLegend(id) {
  6957. return margins[steps[id]] + offsets[id];
  6958. };
  6959. } else if ($$.isLegendInset) {
  6960. xForLegend = function xForLegend(id) {
  6961. return maxWidth * steps[id] + 10;
  6962. };
  6963. yForLegend = function yForLegend(id) {
  6964. return margins[steps[id]] + offsets[id];
  6965. };
  6966. } else {
  6967. xForLegend = function xForLegend(id) {
  6968. return margins[steps[id]] + offsets[id];
  6969. };
  6970. yForLegend = function yForLegend(id) {
  6971. return maxHeight * steps[id];
  6972. };
  6973. }
  6974. xForLegendText = function xForLegendText(id, i) {
  6975. return xForLegend(id, i) + 4 + config.legend_item_tile_width;
  6976. };
  6977. yForLegendText = function yForLegendText(id, i) {
  6978. return yForLegend(id, i) + 9;
  6979. };
  6980. xForLegendRect = function xForLegendRect(id, i) {
  6981. return xForLegend(id, i);
  6982. };
  6983. yForLegendRect = function yForLegendRect(id, i) {
  6984. return yForLegend(id, i) - 5;
  6985. };
  6986. x1ForLegendTile = function x1ForLegendTile(id, i) {
  6987. return xForLegend(id, i) - 2;
  6988. };
  6989. x2ForLegendTile = function x2ForLegendTile(id, i) {
  6990. return xForLegend(id, i) - 2 + config.legend_item_tile_width;
  6991. };
  6992. yForLegendTile = function yForLegendTile(id, i) {
  6993. return yForLegend(id, i) + 4;
  6994. }; // Define g for legend area
  6995. l = $$.legend.selectAll('.' + CLASS.legendItem).data(targetIds).enter().append('g').attr('class', function (id) {
  6996. return $$.generateClass(CLASS.legendItem, id);
  6997. }).style('visibility', function (id) {
  6998. return $$.isLegendToShow(id) ? 'visible' : 'hidden';
  6999. }).style('cursor', 'pointer').on('click', function (id) {
  7000. if (config.legend_item_onclick) {
  7001. config.legend_item_onclick.call($$, id);
  7002. } else {
  7003. if ($$.d3.event.altKey) {
  7004. $$.api.hide();
  7005. $$.api.show(id);
  7006. } else {
  7007. $$.api.toggle(id);
  7008. $$.isTargetToShow(id) ? $$.api.focus(id) : $$.api.revert();
  7009. }
  7010. }
  7011. }).on('mouseover', function (id) {
  7012. if (config.legend_item_onmouseover) {
  7013. config.legend_item_onmouseover.call($$, id);
  7014. } else {
  7015. $$.d3.select(this).classed(CLASS.legendItemFocused, true);
  7016. if (!$$.transiting && $$.isTargetToShow(id)) {
  7017. $$.api.focus(id);
  7018. }
  7019. }
  7020. }).on('mouseout', function (id) {
  7021. if (config.legend_item_onmouseout) {
  7022. config.legend_item_onmouseout.call($$, id);
  7023. } else {
  7024. $$.d3.select(this).classed(CLASS.legendItemFocused, false);
  7025. $$.api.revert();
  7026. }
  7027. });
  7028. l.append('text').text(function (id) {
  7029. return isDefined(config.data_names[id]) ? config.data_names[id] : id;
  7030. }).each(function (id, i) {
  7031. updatePositions(this, id, i);
  7032. }).style("pointer-events", "none").attr('x', $$.isLegendRight || $$.isLegendInset ? xForLegendText : -200).attr('y', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegendText);
  7033. l.append('rect').attr("class", CLASS.legendItemEvent).style('fill-opacity', 0).attr('x', $$.isLegendRight || $$.isLegendInset ? xForLegendRect : -200).attr('y', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegendRect);
  7034. l.append('line').attr('class', CLASS.legendItemTile).style('stroke', $$.color).style("pointer-events", "none").attr('x1', $$.isLegendRight || $$.isLegendInset ? x1ForLegendTile : -200).attr('y1', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegendTile).attr('x2', $$.isLegendRight || $$.isLegendInset ? x2ForLegendTile : -200).attr('y2', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegendTile).attr('stroke-width', config.legend_item_tile_height); // Set background for inset legend
  7035. background = $$.legend.select('.' + CLASS.legendBackground + ' rect');
  7036. if ($$.isLegendInset && maxWidth > 0 && background.size() === 0) {
  7037. background = $$.legend.insert('g', '.' + CLASS.legendItem).attr("class", CLASS.legendBackground).append('rect');
  7038. }
  7039. texts = $$.legend.selectAll('text').data(targetIds).text(function (id) {
  7040. return isDefined(config.data_names[id]) ? config.data_names[id] : id;
  7041. }) // MEMO: needed for update
  7042. .each(function (id, i) {
  7043. updatePositions(this, id, i);
  7044. });
  7045. (withTransition ? texts.transition() : texts).attr('x', xForLegendText).attr('y', yForLegendText);
  7046. rects = $$.legend.selectAll('rect.' + CLASS.legendItemEvent).data(targetIds);
  7047. (withTransition ? rects.transition() : rects).attr('width', function (id) {
  7048. return widths[id];
  7049. }).attr('height', function (id) {
  7050. return heights[id];
  7051. }).attr('x', xForLegendRect).attr('y', yForLegendRect);
  7052. tiles = $$.legend.selectAll('line.' + CLASS.legendItemTile).data(targetIds);
  7053. (withTransition ? tiles.transition() : tiles).style('stroke', $$.levelColor ? function (id) {
  7054. return $$.levelColor($$.cache[id].values[0].value);
  7055. } : $$.color).attr('x1', x1ForLegendTile).attr('y1', yForLegendTile).attr('x2', x2ForLegendTile).attr('y2', yForLegendTile);
  7056. if (background) {
  7057. (withTransition ? background.transition() : background).attr('height', $$.getLegendHeight() - 12).attr('width', maxWidth * (step + 1) + 10);
  7058. } // toggle legend state
  7059. $$.legend.selectAll('.' + CLASS.legendItem).classed(CLASS.legendItemHidden, function (id) {
  7060. return !$$.isTargetToShow(id);
  7061. }); // Update all to reflect change of legend
  7062. $$.updateLegendItemWidth(maxWidth);
  7063. $$.updateLegendItemHeight(maxHeight);
  7064. $$.updateLegendStep(step); // Update size and scale
  7065. $$.updateSizes();
  7066. $$.updateScales();
  7067. $$.updateSvgSize(); // Update g positions
  7068. $$.transformAll(withTransitionForTransform, transitions);
  7069. $$.legendHasRendered = true;
  7070. };
  7071. ChartInternal.prototype.initRegion = function () {
  7072. var $$ = this;
  7073. $$.region = $$.main.append('g').attr("clip-path", $$.clipPath).attr("class", CLASS.regions);
  7074. };
  7075. ChartInternal.prototype.updateRegion = function (duration) {
  7076. var $$ = this,
  7077. config = $$.config; // hide if arc type
  7078. $$.region.style('visibility', $$.hasArcType() ? 'hidden' : 'visible');
  7079. var mainRegion = $$.main.select('.' + CLASS.regions).selectAll('.' + CLASS.region).data(config.regions);
  7080. var mainRegionEnter = mainRegion.enter().append('rect').attr("x", $$.regionX.bind($$)).attr("y", $$.regionY.bind($$)).attr("width", $$.regionWidth.bind($$)).attr("height", $$.regionHeight.bind($$)).style("fill-opacity", 0);
  7081. $$.mainRegion = mainRegionEnter.merge(mainRegion).attr('class', $$.classRegion.bind($$));
  7082. mainRegion.exit().transition().duration(duration).style("opacity", 0).remove();
  7083. };
  7084. ChartInternal.prototype.redrawRegion = function (withTransition, transition) {
  7085. var $$ = this,
  7086. regions = $$.mainRegion;
  7087. return [(withTransition ? regions.transition(transition) : regions).attr("x", $$.regionX.bind($$)).attr("y", $$.regionY.bind($$)).attr("width", $$.regionWidth.bind($$)).attr("height", $$.regionHeight.bind($$)).style("fill-opacity", function (d) {
  7088. return isValue(d.opacity) ? d.opacity : 0.1;
  7089. })];
  7090. };
  7091. ChartInternal.prototype.regionX = function (d) {
  7092. var $$ = this,
  7093. config = $$.config,
  7094. xPos,
  7095. yScale = d.axis === 'y' ? $$.y : $$.y2;
  7096. if (d.axis === 'y' || d.axis === 'y2') {
  7097. xPos = config.axis_rotated ? 'start' in d ? yScale(d.start) : 0 : 0;
  7098. } else {
  7099. xPos = config.axis_rotated ? 0 : 'start' in d ? $$.x($$.isTimeSeries() ? $$.parseDate(d.start) : d.start) : 0;
  7100. }
  7101. return xPos;
  7102. };
  7103. ChartInternal.prototype.regionY = function (d) {
  7104. var $$ = this,
  7105. config = $$.config,
  7106. yPos,
  7107. yScale = d.axis === 'y' ? $$.y : $$.y2;
  7108. if (d.axis === 'y' || d.axis === 'y2') {
  7109. yPos = config.axis_rotated ? 0 : 'end' in d ? yScale(d.end) : 0;
  7110. } else {
  7111. yPos = config.axis_rotated ? 'start' in d ? $$.x($$.isTimeSeries() ? $$.parseDate(d.start) : d.start) : 0 : 0;
  7112. }
  7113. return yPos;
  7114. };
  7115. ChartInternal.prototype.regionWidth = function (d) {
  7116. var $$ = this,
  7117. config = $$.config,
  7118. start = $$.regionX(d),
  7119. end,
  7120. yScale = d.axis === 'y' ? $$.y : $$.y2;
  7121. if (d.axis === 'y' || d.axis === 'y2') {
  7122. end = config.axis_rotated ? 'end' in d ? yScale(d.end) : $$.width : $$.width;
  7123. } else {
  7124. end = config.axis_rotated ? $$.width : 'end' in d ? $$.x($$.isTimeSeries() ? $$.parseDate(d.end) : d.end) : $$.width;
  7125. }
  7126. return end < start ? 0 : end - start;
  7127. };
  7128. ChartInternal.prototype.regionHeight = function (d) {
  7129. var $$ = this,
  7130. config = $$.config,
  7131. start = this.regionY(d),
  7132. end,
  7133. yScale = d.axis === 'y' ? $$.y : $$.y2;
  7134. if (d.axis === 'y' || d.axis === 'y2') {
  7135. end = config.axis_rotated ? $$.height : 'start' in d ? yScale(d.start) : $$.height;
  7136. } else {
  7137. end = config.axis_rotated ? 'end' in d ? $$.x($$.isTimeSeries() ? $$.parseDate(d.end) : d.end) : $$.height : $$.height;
  7138. }
  7139. return end < start ? 0 : end - start;
  7140. };
  7141. ChartInternal.prototype.isRegionOnX = function (d) {
  7142. return !d.axis || d.axis === 'x';
  7143. };
  7144. ChartInternal.prototype.getScale = function (min, max, forTimeseries) {
  7145. return (forTimeseries ? this.d3.scaleTime() : this.d3.scaleLinear()).range([min, max]);
  7146. };
  7147. ChartInternal.prototype.getX = function (min, max, domain, offset) {
  7148. var $$ = this,
  7149. scale = $$.getScale(min, max, $$.isTimeSeries()),
  7150. _scale = domain ? scale.domain(domain) : scale,
  7151. key; // Define customized scale if categorized axis
  7152. if ($$.isCategorized()) {
  7153. offset = offset || function () {
  7154. return 0;
  7155. };
  7156. scale = function scale(d, raw) {
  7157. var v = _scale(d) + offset(d);
  7158. return raw ? v : Math.ceil(v);
  7159. };
  7160. } else {
  7161. scale = function scale(d, raw) {
  7162. var v = _scale(d);
  7163. return raw ? v : Math.ceil(v);
  7164. };
  7165. } // define functions
  7166. for (key in _scale) {
  7167. scale[key] = _scale[key];
  7168. }
  7169. scale.orgDomain = function () {
  7170. return _scale.domain();
  7171. }; // define custom domain() for categorized axis
  7172. if ($$.isCategorized()) {
  7173. scale.domain = function (domain) {
  7174. if (!arguments.length) {
  7175. domain = this.orgDomain();
  7176. return [domain[0], domain[1] + 1];
  7177. }
  7178. _scale.domain(domain);
  7179. return scale;
  7180. };
  7181. }
  7182. return scale;
  7183. };
  7184. ChartInternal.prototype.getY = function (min, max, domain) {
  7185. var scale = this.getScale(min, max, this.isTimeSeriesY());
  7186. if (domain) {
  7187. scale.domain(domain);
  7188. }
  7189. return scale;
  7190. };
  7191. ChartInternal.prototype.getYScale = function (id) {
  7192. return this.axis.getId(id) === 'y2' ? this.y2 : this.y;
  7193. };
  7194. ChartInternal.prototype.getSubYScale = function (id) {
  7195. return this.axis.getId(id) === 'y2' ? this.subY2 : this.subY;
  7196. };
  7197. ChartInternal.prototype.updateScales = function () {
  7198. var $$ = this,
  7199. config = $$.config,
  7200. forInit = !$$.x; // update edges
  7201. $$.xMin = config.axis_rotated ? 1 : 0;
  7202. $$.xMax = config.axis_rotated ? $$.height : $$.width;
  7203. $$.yMin = config.axis_rotated ? 0 : $$.height;
  7204. $$.yMax = config.axis_rotated ? $$.width : 1;
  7205. $$.subXMin = $$.xMin;
  7206. $$.subXMax = $$.xMax;
  7207. $$.subYMin = config.axis_rotated ? 0 : $$.height2;
  7208. $$.subYMax = config.axis_rotated ? $$.width2 : 1; // update scales
  7209. $$.x = $$.getX($$.xMin, $$.xMax, forInit ? undefined : $$.x.orgDomain(), function () {
  7210. return $$.xAxis.tickOffset();
  7211. });
  7212. $$.y = $$.getY($$.yMin, $$.yMax, forInit ? config.axis_y_default : $$.y.domain());
  7213. $$.y2 = $$.getY($$.yMin, $$.yMax, forInit ? config.axis_y2_default : $$.y2.domain());
  7214. $$.subX = $$.getX($$.xMin, $$.xMax, $$.orgXDomain, function (d) {
  7215. return d % 1 ? 0 : $$.subXAxis.tickOffset();
  7216. });
  7217. $$.subY = $$.getY($$.subYMin, $$.subYMax, forInit ? config.axis_y_default : $$.subY.domain());
  7218. $$.subY2 = $$.getY($$.subYMin, $$.subYMax, forInit ? config.axis_y2_default : $$.subY2.domain()); // update axes
  7219. $$.xAxisTickFormat = $$.axis.getXAxisTickFormat();
  7220. $$.xAxisTickValues = $$.axis.getXAxisTickValues();
  7221. $$.yAxisTickValues = $$.axis.getYAxisTickValues();
  7222. $$.y2AxisTickValues = $$.axis.getY2AxisTickValues();
  7223. $$.xAxis = $$.axis.getXAxis($$.x, $$.xOrient, $$.xAxisTickFormat, $$.xAxisTickValues, config.axis_x_tick_outer);
  7224. $$.subXAxis = $$.axis.getXAxis($$.subX, $$.subXOrient, $$.xAxisTickFormat, $$.xAxisTickValues, config.axis_x_tick_outer);
  7225. $$.yAxis = $$.axis.getYAxis($$.y, $$.yOrient, config.axis_y_tick_format, $$.yAxisTickValues, config.axis_y_tick_outer);
  7226. $$.y2Axis = $$.axis.getYAxis($$.y2, $$.y2Orient, config.axis_y2_tick_format, $$.y2AxisTickValues, config.axis_y2_tick_outer); // Set initialized scales to brush and zoom
  7227. if (!forInit) {
  7228. if ($$.brush) {
  7229. $$.brush.updateScale($$.subX);
  7230. }
  7231. } // update for arc
  7232. if ($$.updateArc) {
  7233. $$.updateArc();
  7234. }
  7235. };
  7236. ChartInternal.prototype.selectPoint = function (target, d, i) {
  7237. var $$ = this,
  7238. config = $$.config,
  7239. cx = (config.axis_rotated ? $$.circleY : $$.circleX).bind($$),
  7240. cy = (config.axis_rotated ? $$.circleX : $$.circleY).bind($$),
  7241. r = $$.pointSelectR.bind($$);
  7242. config.data_onselected.call($$.api, d, target.node()); // add selected-circle on low layer g
  7243. $$.main.select('.' + CLASS.selectedCircles + $$.getTargetSelectorSuffix(d.id)).selectAll('.' + CLASS.selectedCircle + '-' + i).data([d]).enter().append('circle').attr("class", function () {
  7244. return $$.generateClass(CLASS.selectedCircle, i);
  7245. }).attr("cx", cx).attr("cy", cy).attr("stroke", function () {
  7246. return $$.color(d);
  7247. }).attr("r", function (d) {
  7248. return $$.pointSelectR(d) * 1.4;
  7249. }).transition().duration(100).attr("r", r);
  7250. };
  7251. ChartInternal.prototype.unselectPoint = function (target, d, i) {
  7252. var $$ = this;
  7253. $$.config.data_onunselected.call($$.api, d, target.node()); // remove selected-circle from low layer g
  7254. $$.main.select('.' + CLASS.selectedCircles + $$.getTargetSelectorSuffix(d.id)).selectAll('.' + CLASS.selectedCircle + '-' + i).transition().duration(100).attr('r', 0).remove();
  7255. };
  7256. ChartInternal.prototype.togglePoint = function (selected, target, d, i) {
  7257. selected ? this.selectPoint(target, d, i) : this.unselectPoint(target, d, i);
  7258. };
  7259. ChartInternal.prototype.selectPath = function (target, d) {
  7260. var $$ = this;
  7261. $$.config.data_onselected.call($$, d, target.node());
  7262. if ($$.config.interaction_brighten) {
  7263. target.transition().duration(100).style("fill", function () {
  7264. return $$.d3.rgb($$.color(d)).brighter(0.75);
  7265. });
  7266. }
  7267. };
  7268. ChartInternal.prototype.unselectPath = function (target, d) {
  7269. var $$ = this;
  7270. $$.config.data_onunselected.call($$, d, target.node());
  7271. if ($$.config.interaction_brighten) {
  7272. target.transition().duration(100).style("fill", function () {
  7273. return $$.color(d);
  7274. });
  7275. }
  7276. };
  7277. ChartInternal.prototype.togglePath = function (selected, target, d, i) {
  7278. selected ? this.selectPath(target, d, i) : this.unselectPath(target, d, i);
  7279. };
  7280. ChartInternal.prototype.getToggle = function (that, d) {
  7281. var $$ = this,
  7282. toggle;
  7283. if (that.nodeName === 'circle') {
  7284. if ($$.isStepType(d)) {
  7285. // circle is hidden in step chart, so treat as within the click area
  7286. toggle = function toggle() {}; // TODO: how to select step chart?
  7287. } else {
  7288. toggle = $$.togglePoint;
  7289. }
  7290. } else if (that.nodeName === 'path') {
  7291. toggle = $$.togglePath;
  7292. }
  7293. return toggle;
  7294. };
  7295. ChartInternal.prototype.toggleShape = function (that, d, i) {
  7296. var $$ = this,
  7297. d3 = $$.d3,
  7298. config = $$.config,
  7299. shape = d3.select(that),
  7300. isSelected = shape.classed(CLASS.SELECTED),
  7301. toggle = $$.getToggle(that, d).bind($$);
  7302. if (config.data_selection_enabled && config.data_selection_isselectable(d)) {
  7303. if (!config.data_selection_multiple) {
  7304. $$.main.selectAll('.' + CLASS.shapes + (config.data_selection_grouped ? $$.getTargetSelectorSuffix(d.id) : "")).selectAll('.' + CLASS.shape).each(function (d, i) {
  7305. var shape = d3.select(this);
  7306. if (shape.classed(CLASS.SELECTED)) {
  7307. toggle(false, shape.classed(CLASS.SELECTED, false), d, i);
  7308. }
  7309. });
  7310. }
  7311. shape.classed(CLASS.SELECTED, !isSelected);
  7312. toggle(!isSelected, shape, d, i);
  7313. }
  7314. };
  7315. ChartInternal.prototype.initBar = function () {
  7316. var $$ = this;
  7317. $$.main.select('.' + CLASS.chart).append("g").attr("class", CLASS.chartBars);
  7318. };
  7319. ChartInternal.prototype.updateTargetsForBar = function (targets) {
  7320. var $$ = this,
  7321. config = $$.config,
  7322. mainBars,
  7323. mainBarEnter,
  7324. classChartBar = $$.classChartBar.bind($$),
  7325. classBars = $$.classBars.bind($$),
  7326. classFocus = $$.classFocus.bind($$);
  7327. mainBars = $$.main.select('.' + CLASS.chartBars).selectAll('.' + CLASS.chartBar).data(targets).attr('class', function (d) {
  7328. return classChartBar(d) + classFocus(d);
  7329. });
  7330. mainBarEnter = mainBars.enter().append('g').attr('class', classChartBar).style("pointer-events", "none"); // Bars for each data
  7331. mainBarEnter.append('g').attr("class", classBars).style("cursor", function (d) {
  7332. return config.data_selection_isselectable(d) ? "pointer" : null;
  7333. });
  7334. };
  7335. ChartInternal.prototype.updateBar = function (durationForExit) {
  7336. var $$ = this,
  7337. barData = $$.barData.bind($$),
  7338. classBar = $$.classBar.bind($$),
  7339. initialOpacity = $$.initialOpacity.bind($$),
  7340. color = function color(d) {
  7341. return $$.color(d.id);
  7342. };
  7343. var mainBar = $$.main.selectAll('.' + CLASS.bars).selectAll('.' + CLASS.bar).data(barData);
  7344. var mainBarEnter = mainBar.enter().append('path').attr("class", classBar).style("stroke", color).style("fill", color);
  7345. $$.mainBar = mainBarEnter.merge(mainBar).style("opacity", initialOpacity);
  7346. mainBar.exit().transition().duration(durationForExit).style("opacity", 0);
  7347. };
  7348. ChartInternal.prototype.redrawBar = function (drawBar, withTransition, transition) {
  7349. return [(withTransition ? this.mainBar.transition(transition) : this.mainBar).attr('d', drawBar).style("stroke", this.color).style("fill", this.color).style("opacity", 1)];
  7350. };
  7351. ChartInternal.prototype.getBarW = function (axis, barTargetsNum) {
  7352. var $$ = this,
  7353. config = $$.config,
  7354. w = typeof config.bar_width === 'number' ? config.bar_width : barTargetsNum ? axis.tickInterval() * config.bar_width_ratio / barTargetsNum : 0;
  7355. return config.bar_width_max && w > config.bar_width_max ? config.bar_width_max : w;
  7356. };
  7357. ChartInternal.prototype.getBars = function (i, id) {
  7358. var $$ = this;
  7359. return (id ? $$.main.selectAll('.' + CLASS.bars + $$.getTargetSelectorSuffix(id)) : $$.main).selectAll('.' + CLASS.bar + (isValue(i) ? '-' + i : ''));
  7360. };
  7361. ChartInternal.prototype.expandBars = function (i, id, reset) {
  7362. var $$ = this;
  7363. if (reset) {
  7364. $$.unexpandBars();
  7365. }
  7366. $$.getBars(i, id).classed(CLASS.EXPANDED, true);
  7367. };
  7368. ChartInternal.prototype.unexpandBars = function (i) {
  7369. var $$ = this;
  7370. $$.getBars(i).classed(CLASS.EXPANDED, false);
  7371. };
  7372. ChartInternal.prototype.generateDrawBar = function (barIndices, isSub) {
  7373. var $$ = this,
  7374. config = $$.config,
  7375. getPoints = $$.generateGetBarPoints(barIndices, isSub);
  7376. return function (d, i) {
  7377. // 4 points that make a bar
  7378. var points = getPoints(d, i); // switch points if axis is rotated, not applicable for sub chart
  7379. var indexX = config.axis_rotated ? 1 : 0;
  7380. var indexY = config.axis_rotated ? 0 : 1;
  7381. var path = 'M ' + points[0][indexX] + ',' + points[0][indexY] + ' ' + 'L' + points[1][indexX] + ',' + points[1][indexY] + ' ' + 'L' + points[2][indexX] + ',' + points[2][indexY] + ' ' + 'L' + points[3][indexX] + ',' + points[3][indexY] + ' ' + 'z';
  7382. return path;
  7383. };
  7384. };
  7385. ChartInternal.prototype.generateGetBarPoints = function (barIndices, isSub) {
  7386. var $$ = this,
  7387. axis = isSub ? $$.subXAxis : $$.xAxis,
  7388. barTargetsNum = barIndices.__max__ + 1,
  7389. barW = $$.getBarW(axis, barTargetsNum),
  7390. barX = $$.getShapeX(barW, barTargetsNum, barIndices, !!isSub),
  7391. barY = $$.getShapeY(!!isSub),
  7392. barOffset = $$.getShapeOffset($$.isBarType, barIndices, !!isSub),
  7393. barSpaceOffset = barW * ($$.config.bar_space / 2),
  7394. yScale = isSub ? $$.getSubYScale : $$.getYScale;
  7395. return function (d, i) {
  7396. var y0 = yScale.call($$, d.id)(0),
  7397. offset = barOffset(d, i) || y0,
  7398. // offset is for stacked bar chart
  7399. posX = barX(d),
  7400. posY = barY(d); // fix posY not to overflow opposite quadrant
  7401. if ($$.config.axis_rotated) {
  7402. if (0 < d.value && posY < y0 || d.value < 0 && y0 < posY) {
  7403. posY = y0;
  7404. }
  7405. } // 4 points that make a bar
  7406. return [[posX + barSpaceOffset, offset], [posX + barSpaceOffset, posY - (y0 - offset)], [posX + barW - barSpaceOffset, posY - (y0 - offset)], [posX + barW - barSpaceOffset, offset]];
  7407. };
  7408. };
  7409. ChartInternal.prototype.isWithinBar = function (mouse, that) {
  7410. var box = that.getBoundingClientRect(),
  7411. seg0 = that.pathSegList.getItem(0),
  7412. seg1 = that.pathSegList.getItem(1),
  7413. x = Math.min(seg0.x, seg1.x),
  7414. y = Math.min(seg0.y, seg1.y),
  7415. w = box.width,
  7416. h = box.height,
  7417. offset = 2,
  7418. sx = x - offset,
  7419. ex = x + w + offset,
  7420. sy = y + h + offset,
  7421. ey = y - offset;
  7422. return sx < mouse[0] && mouse[0] < ex && ey < mouse[1] && mouse[1] < sy;
  7423. };
  7424. ChartInternal.prototype.getShapeIndices = function (typeFilter) {
  7425. var $$ = this,
  7426. config = $$.config,
  7427. indices = {},
  7428. i = 0,
  7429. j,
  7430. k;
  7431. $$.filterTargetsToShow($$.data.targets.filter(typeFilter, $$)).forEach(function (d) {
  7432. for (j = 0; j < config.data_groups.length; j++) {
  7433. if (config.data_groups[j].indexOf(d.id) < 0) {
  7434. continue;
  7435. }
  7436. for (k = 0; k < config.data_groups[j].length; k++) {
  7437. if (config.data_groups[j][k] in indices) {
  7438. indices[d.id] = indices[config.data_groups[j][k]];
  7439. break;
  7440. }
  7441. }
  7442. }
  7443. if (isUndefined(indices[d.id])) {
  7444. indices[d.id] = i++;
  7445. }
  7446. });
  7447. indices.__max__ = i - 1;
  7448. return indices;
  7449. };
  7450. ChartInternal.prototype.getShapeX = function (offset, targetsNum, indices, isSub) {
  7451. var $$ = this,
  7452. scale = isSub ? $$.subX : $$.x;
  7453. return function (d) {
  7454. var index = d.id in indices ? indices[d.id] : 0;
  7455. return d.x || d.x === 0 ? scale(d.x) - offset * (targetsNum / 2 - index) : 0;
  7456. };
  7457. };
  7458. ChartInternal.prototype.getShapeY = function (isSub) {
  7459. var $$ = this;
  7460. return function (d) {
  7461. var scale = isSub ? $$.getSubYScale(d.id) : $$.getYScale(d.id);
  7462. return scale(d.value);
  7463. };
  7464. };
  7465. ChartInternal.prototype.getShapeOffset = function (typeFilter, indices, isSub) {
  7466. var $$ = this,
  7467. targets = $$.orderTargets($$.filterTargetsToShow($$.data.targets.filter(typeFilter, $$))),
  7468. targetIds = targets.map(function (t) {
  7469. return t.id;
  7470. });
  7471. return function (d, i) {
  7472. var scale = isSub ? $$.getSubYScale(d.id) : $$.getYScale(d.id),
  7473. y0 = scale(0),
  7474. offset = y0;
  7475. targets.forEach(function (t) {
  7476. var values = $$.isStepType(d) ? $$.convertValuesToStep(t.values) : t.values;
  7477. if (t.id === d.id || indices[t.id] !== indices[d.id]) {
  7478. return;
  7479. }
  7480. if (targetIds.indexOf(t.id) < targetIds.indexOf(d.id)) {
  7481. // check if the x values line up
  7482. if (typeof values[i] === 'undefined' || +values[i].x !== +d.x) {
  7483. // "+" for timeseries
  7484. // if not, try to find the value that does line up
  7485. i = -1;
  7486. values.forEach(function (v, j) {
  7487. if (v.x === d.x) {
  7488. i = j;
  7489. }
  7490. });
  7491. }
  7492. if (i in values && values[i].value * d.value >= 0) {
  7493. offset += scale(values[i].value) - y0;
  7494. }
  7495. }
  7496. });
  7497. return offset;
  7498. };
  7499. };
  7500. ChartInternal.prototype.isWithinShape = function (that, d) {
  7501. var $$ = this,
  7502. shape = $$.d3.select(that),
  7503. isWithin;
  7504. if (!$$.isTargetToShow(d.id)) {
  7505. isWithin = false;
  7506. } else if (that.nodeName === 'circle') {
  7507. isWithin = $$.isStepType(d) ? $$.isWithinStep(that, $$.getYScale(d.id)(d.value)) : $$.isWithinCircle(that, $$.pointSelectR(d) * 1.5);
  7508. } else if (that.nodeName === 'path') {
  7509. isWithin = shape.classed(CLASS.bar) ? $$.isWithinBar($$.d3.mouse(that), that) : true;
  7510. }
  7511. return isWithin;
  7512. };
  7513. ChartInternal.prototype.getInterpolate = function (d) {
  7514. var $$ = this,
  7515. d3 = $$.d3,
  7516. types = {
  7517. 'linear': d3.curveLinear,
  7518. 'linear-closed': d3.curveLinearClosed,
  7519. 'basis': d3.curveBasis,
  7520. 'basis-open': d3.curveBasisOpen,
  7521. 'basis-closed': d3.curveBasisClosed,
  7522. 'bundle': d3.curveBundle,
  7523. 'cardinal': d3.curveCardinal,
  7524. 'cardinal-open': d3.curveCardinalOpen,
  7525. 'cardinal-closed': d3.curveCardinalClosed,
  7526. 'monotone': d3.curveMonotoneX,
  7527. 'step': d3.curveStep,
  7528. 'step-before': d3.curveStepBefore,
  7529. 'step-after': d3.curveStepAfter
  7530. },
  7531. type;
  7532. if ($$.isSplineType(d)) {
  7533. type = types[$$.config.spline_interpolation_type] || types.cardinal;
  7534. } else if ($$.isStepType(d)) {
  7535. type = types[$$.config.line_step_type];
  7536. } else {
  7537. type = types.linear;
  7538. }
  7539. return type;
  7540. };
  7541. ChartInternal.prototype.initLine = function () {
  7542. var $$ = this;
  7543. $$.main.select('.' + CLASS.chart).append("g").attr("class", CLASS.chartLines);
  7544. };
  7545. ChartInternal.prototype.updateTargetsForLine = function (targets) {
  7546. var $$ = this,
  7547. config = $$.config,
  7548. mainLines,
  7549. mainLineEnter,
  7550. classChartLine = $$.classChartLine.bind($$),
  7551. classLines = $$.classLines.bind($$),
  7552. classAreas = $$.classAreas.bind($$),
  7553. classCircles = $$.classCircles.bind($$),
  7554. classFocus = $$.classFocus.bind($$);
  7555. mainLines = $$.main.select('.' + CLASS.chartLines).selectAll('.' + CLASS.chartLine).data(targets).attr('class', function (d) {
  7556. return classChartLine(d) + classFocus(d);
  7557. });
  7558. mainLineEnter = mainLines.enter().append('g').attr('class', classChartLine).style('opacity', 0).style("pointer-events", "none"); // Lines for each data
  7559. mainLineEnter.append('g').attr("class", classLines); // Areas
  7560. mainLineEnter.append('g').attr('class', classAreas); // Circles for each data point on lines
  7561. mainLineEnter.append('g').attr("class", function (d) {
  7562. return $$.generateClass(CLASS.selectedCircles, d.id);
  7563. });
  7564. mainLineEnter.append('g').attr("class", classCircles).style("cursor", function (d) {
  7565. return config.data_selection_isselectable(d) ? "pointer" : null;
  7566. }); // Update date for selected circles
  7567. targets.forEach(function (t) {
  7568. $$.main.selectAll('.' + CLASS.selectedCircles + $$.getTargetSelectorSuffix(t.id)).selectAll('.' + CLASS.selectedCircle).each(function (d) {
  7569. d.value = t.values[d.index].value;
  7570. });
  7571. }); // MEMO: can not keep same color...
  7572. //mainLineUpdate.exit().remove();
  7573. };
  7574. ChartInternal.prototype.updateLine = function (durationForExit) {
  7575. var $$ = this;
  7576. var mainLine = $$.main.selectAll('.' + CLASS.lines).selectAll('.' + CLASS.line).data($$.lineData.bind($$));
  7577. var mainLineEnter = mainLine.enter().append('path').attr('class', $$.classLine.bind($$)).style("stroke", $$.color);
  7578. $$.mainLine = mainLineEnter.merge(mainLine).style("opacity", $$.initialOpacity.bind($$)).style('shape-rendering', function (d) {
  7579. return $$.isStepType(d) ? 'crispEdges' : '';
  7580. }).attr('transform', null);
  7581. mainLine.exit().transition().duration(durationForExit).style('opacity', 0);
  7582. };
  7583. ChartInternal.prototype.redrawLine = function (drawLine, withTransition, transition) {
  7584. return [(withTransition ? this.mainLine.transition(transition) : this.mainLine).attr("d", drawLine).style("stroke", this.color).style("opacity", 1)];
  7585. };
  7586. ChartInternal.prototype.generateDrawLine = function (lineIndices, isSub) {
  7587. var $$ = this,
  7588. config = $$.config,
  7589. line = $$.d3.line(),
  7590. getPoints = $$.generateGetLinePoints(lineIndices, isSub),
  7591. yScaleGetter = isSub ? $$.getSubYScale : $$.getYScale,
  7592. xValue = function xValue(d) {
  7593. return (isSub ? $$.subxx : $$.xx).call($$, d);
  7594. },
  7595. yValue = function yValue(d, i) {
  7596. return config.data_groups.length > 0 ? getPoints(d, i)[0][1] : yScaleGetter.call($$, d.id)(d.value);
  7597. };
  7598. line = config.axis_rotated ? line.x(yValue).y(xValue) : line.x(xValue).y(yValue);
  7599. if (!config.line_connectNull) {
  7600. line = line.defined(function (d) {
  7601. return d.value != null;
  7602. });
  7603. }
  7604. return function (d) {
  7605. var values = config.line_connectNull ? $$.filterRemoveNull(d.values) : d.values,
  7606. x = isSub ? $$.subX : $$.x,
  7607. y = yScaleGetter.call($$, d.id),
  7608. x0 = 0,
  7609. y0 = 0,
  7610. path;
  7611. if ($$.isLineType(d)) {
  7612. if (config.data_regions[d.id]) {
  7613. path = $$.lineWithRegions(values, x, y, config.data_regions[d.id]);
  7614. } else {
  7615. if ($$.isStepType(d)) {
  7616. values = $$.convertValuesToStep(values);
  7617. }
  7618. path = line.curve($$.getInterpolate(d))(values);
  7619. }
  7620. } else {
  7621. if (values[0]) {
  7622. x0 = x(values[0].x);
  7623. y0 = y(values[0].value);
  7624. }
  7625. path = config.axis_rotated ? "M " + y0 + " " + x0 : "M " + x0 + " " + y0;
  7626. }
  7627. return path ? path : "M 0 0";
  7628. };
  7629. };
  7630. ChartInternal.prototype.generateGetLinePoints = function (lineIndices, isSub) {
  7631. // partial duplication of generateGetBarPoints
  7632. var $$ = this,
  7633. config = $$.config,
  7634. lineTargetsNum = lineIndices.__max__ + 1,
  7635. x = $$.getShapeX(0, lineTargetsNum, lineIndices, !!isSub),
  7636. y = $$.getShapeY(!!isSub),
  7637. lineOffset = $$.getShapeOffset($$.isLineType, lineIndices, !!isSub),
  7638. yScale = isSub ? $$.getSubYScale : $$.getYScale;
  7639. return function (d, i) {
  7640. var y0 = yScale.call($$, d.id)(0),
  7641. offset = lineOffset(d, i) || y0,
  7642. // offset is for stacked area chart
  7643. posX = x(d),
  7644. posY = y(d); // fix posY not to overflow opposite quadrant
  7645. if (config.axis_rotated) {
  7646. if (0 < d.value && posY < y0 || d.value < 0 && y0 < posY) {
  7647. posY = y0;
  7648. }
  7649. } // 1 point that marks the line position
  7650. return [[posX, posY - (y0 - offset)], [posX, posY - (y0 - offset)], // needed for compatibility
  7651. [posX, posY - (y0 - offset)], // needed for compatibility
  7652. [posX, posY - (y0 - offset)] // needed for compatibility
  7653. ];
  7654. };
  7655. };
  7656. ChartInternal.prototype.lineWithRegions = function (d, x, y, _regions) {
  7657. var $$ = this,
  7658. config = $$.config,
  7659. prev = -1,
  7660. i,
  7661. j,
  7662. s = "M",
  7663. sWithRegion,
  7664. xp,
  7665. yp,
  7666. dx,
  7667. dy,
  7668. dd,
  7669. diff,
  7670. diffx2,
  7671. xOffset = $$.isCategorized() ? 0.5 : 0,
  7672. xValue,
  7673. yValue,
  7674. regions = [];
  7675. function isWithinRegions(x, regions) {
  7676. var i;
  7677. for (i = 0; i < regions.length; i++) {
  7678. if (regions[i].start < x && x <= regions[i].end) {
  7679. return true;
  7680. }
  7681. }
  7682. return false;
  7683. } // Check start/end of regions
  7684. if (isDefined(_regions)) {
  7685. for (i = 0; i < _regions.length; i++) {
  7686. regions[i] = {};
  7687. if (isUndefined(_regions[i].start)) {
  7688. regions[i].start = d[0].x;
  7689. } else {
  7690. regions[i].start = $$.isTimeSeries() ? $$.parseDate(_regions[i].start) : _regions[i].start;
  7691. }
  7692. if (isUndefined(_regions[i].end)) {
  7693. regions[i].end = d[d.length - 1].x;
  7694. } else {
  7695. regions[i].end = $$.isTimeSeries() ? $$.parseDate(_regions[i].end) : _regions[i].end;
  7696. }
  7697. }
  7698. } // Set scales
  7699. xValue = config.axis_rotated ? function (d) {
  7700. return y(d.value);
  7701. } : function (d) {
  7702. return x(d.x);
  7703. };
  7704. yValue = config.axis_rotated ? function (d) {
  7705. return x(d.x);
  7706. } : function (d) {
  7707. return y(d.value);
  7708. }; // Define svg generator function for region
  7709. function generateM(points) {
  7710. return 'M' + points[0][0] + ' ' + points[0][1] + ' ' + points[1][0] + ' ' + points[1][1];
  7711. }
  7712. if ($$.isTimeSeries()) {
  7713. sWithRegion = function sWithRegion(d0, d1, j, diff) {
  7714. var x0 = d0.x.getTime(),
  7715. x_diff = d1.x - d0.x,
  7716. xv0 = new Date(x0 + x_diff * j),
  7717. xv1 = new Date(x0 + x_diff * (j + diff)),
  7718. points;
  7719. if (config.axis_rotated) {
  7720. points = [[y(yp(j)), x(xv0)], [y(yp(j + diff)), x(xv1)]];
  7721. } else {
  7722. points = [[x(xv0), y(yp(j))], [x(xv1), y(yp(j + diff))]];
  7723. }
  7724. return generateM(points);
  7725. };
  7726. } else {
  7727. sWithRegion = function sWithRegion(d0, d1, j, diff) {
  7728. var points;
  7729. if (config.axis_rotated) {
  7730. points = [[y(yp(j), true), x(xp(j))], [y(yp(j + diff), true), x(xp(j + diff))]];
  7731. } else {
  7732. points = [[x(xp(j), true), y(yp(j))], [x(xp(j + diff), true), y(yp(j + diff))]];
  7733. }
  7734. return generateM(points);
  7735. };
  7736. } // Generate
  7737. for (i = 0; i < d.length; i++) {
  7738. // Draw as normal
  7739. if (isUndefined(regions) || !isWithinRegions(d[i].x, regions)) {
  7740. s += " " + xValue(d[i]) + " " + yValue(d[i]);
  7741. } // Draw with region // TODO: Fix for horizotal charts
  7742. else {
  7743. xp = $$.getScale(d[i - 1].x + xOffset, d[i].x + xOffset, $$.isTimeSeries());
  7744. yp = $$.getScale(d[i - 1].value, d[i].value);
  7745. dx = x(d[i].x) - x(d[i - 1].x);
  7746. dy = y(d[i].value) - y(d[i - 1].value);
  7747. dd = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));
  7748. diff = 2 / dd;
  7749. diffx2 = diff * 2;
  7750. for (j = diff; j <= 1; j += diffx2) {
  7751. s += sWithRegion(d[i - 1], d[i], j, diff);
  7752. }
  7753. }
  7754. prev = d[i].x;
  7755. }
  7756. return s;
  7757. };
  7758. ChartInternal.prototype.updateArea = function (durationForExit) {
  7759. var $$ = this,
  7760. d3 = $$.d3;
  7761. var mainArea = $$.main.selectAll('.' + CLASS.areas).selectAll('.' + CLASS.area).data($$.lineData.bind($$));
  7762. var mainAreaEnter = mainArea.enter().append('path').attr("class", $$.classArea.bind($$)).style("fill", $$.color).style("opacity", function () {
  7763. $$.orgAreaOpacity = +d3.select(this).style('opacity');
  7764. return 0;
  7765. });
  7766. $$.mainArea = mainAreaEnter.merge(mainArea).style("opacity", $$.orgAreaOpacity);
  7767. mainArea.exit().transition().duration(durationForExit).style('opacity', 0);
  7768. };
  7769. ChartInternal.prototype.redrawArea = function (drawArea, withTransition, transition) {
  7770. return [(withTransition ? this.mainArea.transition(transition) : this.mainArea).attr("d", drawArea).style("fill", this.color).style("opacity", this.orgAreaOpacity)];
  7771. };
  7772. ChartInternal.prototype.generateDrawArea = function (areaIndices, isSub) {
  7773. var $$ = this,
  7774. config = $$.config,
  7775. area = $$.d3.area(),
  7776. getPoints = $$.generateGetAreaPoints(areaIndices, isSub),
  7777. yScaleGetter = isSub ? $$.getSubYScale : $$.getYScale,
  7778. xValue = function xValue(d) {
  7779. return (isSub ? $$.subxx : $$.xx).call($$, d);
  7780. },
  7781. value0 = function value0(d, i) {
  7782. return config.data_groups.length > 0 ? getPoints(d, i)[0][1] : yScaleGetter.call($$, d.id)($$.getAreaBaseValue(d.id));
  7783. },
  7784. value1 = function value1(d, i) {
  7785. return config.data_groups.length > 0 ? getPoints(d, i)[1][1] : yScaleGetter.call($$, d.id)(d.value);
  7786. };
  7787. area = config.axis_rotated ? area.x0(value0).x1(value1).y(xValue) : area.x(xValue).y0(config.area_above ? 0 : value0).y1(value1);
  7788. if (!config.line_connectNull) {
  7789. area = area.defined(function (d) {
  7790. return d.value !== null;
  7791. });
  7792. }
  7793. return function (d) {
  7794. var values = config.line_connectNull ? $$.filterRemoveNull(d.values) : d.values,
  7795. x0 = 0,
  7796. y0 = 0,
  7797. path;
  7798. if ($$.isAreaType(d)) {
  7799. if ($$.isStepType(d)) {
  7800. values = $$.convertValuesToStep(values);
  7801. }
  7802. path = area.curve($$.getInterpolate(d))(values);
  7803. } else {
  7804. if (values[0]) {
  7805. x0 = $$.x(values[0].x);
  7806. y0 = $$.getYScale(d.id)(values[0].value);
  7807. }
  7808. path = config.axis_rotated ? "M " + y0 + " " + x0 : "M " + x0 + " " + y0;
  7809. }
  7810. return path ? path : "M 0 0";
  7811. };
  7812. };
  7813. ChartInternal.prototype.getAreaBaseValue = function () {
  7814. return 0;
  7815. };
  7816. ChartInternal.prototype.generateGetAreaPoints = function (areaIndices, isSub) {
  7817. // partial duplication of generateGetBarPoints
  7818. var $$ = this,
  7819. config = $$.config,
  7820. areaTargetsNum = areaIndices.__max__ + 1,
  7821. x = $$.getShapeX(0, areaTargetsNum, areaIndices, !!isSub),
  7822. y = $$.getShapeY(!!isSub),
  7823. areaOffset = $$.getShapeOffset($$.isAreaType, areaIndices, !!isSub),
  7824. yScale = isSub ? $$.getSubYScale : $$.getYScale;
  7825. return function (d, i) {
  7826. var y0 = yScale.call($$, d.id)(0),
  7827. offset = areaOffset(d, i) || y0,
  7828. // offset is for stacked area chart
  7829. posX = x(d),
  7830. posY = y(d); // fix posY not to overflow opposite quadrant
  7831. if (config.axis_rotated) {
  7832. if (0 < d.value && posY < y0 || d.value < 0 && y0 < posY) {
  7833. posY = y0;
  7834. }
  7835. } // 1 point that marks the area position
  7836. return [[posX, offset], [posX, posY - (y0 - offset)], [posX, posY - (y0 - offset)], // needed for compatibility
  7837. [posX, offset] // needed for compatibility
  7838. ];
  7839. };
  7840. };
  7841. ChartInternal.prototype.updateCircle = function (cx, cy) {
  7842. var $$ = this;
  7843. var mainCircle = $$.main.selectAll('.' + CLASS.circles).selectAll('.' + CLASS.circle).data($$.lineOrScatterData.bind($$));
  7844. var mainCircleEnter = mainCircle.enter().append("circle").attr("class", $$.classCircle.bind($$)).attr("cx", cx).attr("cy", cy).attr("r", $$.pointR.bind($$)).style("fill", $$.color);
  7845. $$.mainCircle = mainCircleEnter.merge(mainCircle).style("opacity", $$.initialOpacityForCircle.bind($$));
  7846. mainCircle.exit().style("opacity", 0);
  7847. };
  7848. ChartInternal.prototype.redrawCircle = function (cx, cy, withTransition, transition) {
  7849. var $$ = this,
  7850. selectedCircles = $$.main.selectAll('.' + CLASS.selectedCircle);
  7851. return [(withTransition ? $$.mainCircle.transition(transition) : $$.mainCircle).style('opacity', this.opacityForCircle.bind($$)).style("fill", $$.color).attr("cx", cx).attr("cy", cy), (withTransition ? selectedCircles.transition(transition) : selectedCircles).attr("cx", cx).attr("cy", cy)];
  7852. };
  7853. ChartInternal.prototype.circleX = function (d) {
  7854. return d.x || d.x === 0 ? this.x(d.x) : null;
  7855. };
  7856. ChartInternal.prototype.updateCircleY = function () {
  7857. var $$ = this,
  7858. lineIndices,
  7859. getPoints;
  7860. if ($$.config.data_groups.length > 0) {
  7861. lineIndices = $$.getShapeIndices($$.isLineType), getPoints = $$.generateGetLinePoints(lineIndices);
  7862. $$.circleY = function (d, i) {
  7863. return getPoints(d, i)[0][1];
  7864. };
  7865. } else {
  7866. $$.circleY = function (d) {
  7867. return $$.getYScale(d.id)(d.value);
  7868. };
  7869. }
  7870. };
  7871. ChartInternal.prototype.getCircles = function (i, id) {
  7872. var $$ = this;
  7873. return (id ? $$.main.selectAll('.' + CLASS.circles + $$.getTargetSelectorSuffix(id)) : $$.main).selectAll('.' + CLASS.circle + (isValue(i) ? '-' + i : ''));
  7874. };
  7875. ChartInternal.prototype.expandCircles = function (i, id, reset) {
  7876. var $$ = this,
  7877. r = $$.pointExpandedR.bind($$);
  7878. if (reset) {
  7879. $$.unexpandCircles();
  7880. }
  7881. $$.getCircles(i, id).classed(CLASS.EXPANDED, true).attr('r', r);
  7882. };
  7883. ChartInternal.prototype.unexpandCircles = function (i) {
  7884. var $$ = this,
  7885. r = $$.pointR.bind($$);
  7886. $$.getCircles(i).filter(function () {
  7887. return $$.d3.select(this).classed(CLASS.EXPANDED);
  7888. }).classed(CLASS.EXPANDED, false).attr('r', r);
  7889. };
  7890. ChartInternal.prototype.pointR = function (d) {
  7891. var $$ = this,
  7892. config = $$.config;
  7893. return $$.isStepType(d) ? 0 : isFunction(config.point_r) ? config.point_r(d) : config.point_r;
  7894. };
  7895. ChartInternal.prototype.pointExpandedR = function (d) {
  7896. var $$ = this,
  7897. config = $$.config;
  7898. if (config.point_focus_expand_enabled) {
  7899. return isFunction(config.point_focus_expand_r) ? config.point_focus_expand_r(d) : config.point_focus_expand_r ? config.point_focus_expand_r : $$.pointR(d) * 1.75;
  7900. } else {
  7901. return $$.pointR(d);
  7902. }
  7903. };
  7904. ChartInternal.prototype.pointSelectR = function (d) {
  7905. var $$ = this,
  7906. config = $$.config;
  7907. return isFunction(config.point_select_r) ? config.point_select_r(d) : config.point_select_r ? config.point_select_r : $$.pointR(d) * 4;
  7908. };
  7909. ChartInternal.prototype.isWithinCircle = function (that, r) {
  7910. var d3 = this.d3,
  7911. mouse = d3.mouse(that),
  7912. d3_this = d3.select(that),
  7913. cx = +d3_this.attr("cx"),
  7914. cy = +d3_this.attr("cy");
  7915. return Math.sqrt(Math.pow(cx - mouse[0], 2) + Math.pow(cy - mouse[1], 2)) < r;
  7916. };
  7917. ChartInternal.prototype.isWithinStep = function (that, y) {
  7918. return Math.abs(y - this.d3.mouse(that)[1]) < 30;
  7919. };
  7920. ChartInternal.prototype.getCurrentWidth = function () {
  7921. var $$ = this,
  7922. config = $$.config;
  7923. return config.size_width ? config.size_width : $$.getParentWidth();
  7924. };
  7925. ChartInternal.prototype.getCurrentHeight = function () {
  7926. var $$ = this,
  7927. config = $$.config,
  7928. h = config.size_height ? config.size_height : $$.getParentHeight();
  7929. return h > 0 ? h : 320 / ($$.hasType('gauge') && !config.gauge_fullCircle ? 2 : 1);
  7930. };
  7931. ChartInternal.prototype.getCurrentPaddingTop = function () {
  7932. var $$ = this,
  7933. config = $$.config,
  7934. padding = isValue(config.padding_top) ? config.padding_top : 0;
  7935. if ($$.title && $$.title.node()) {
  7936. padding += $$.getTitlePadding();
  7937. }
  7938. return padding;
  7939. };
  7940. ChartInternal.prototype.getCurrentPaddingBottom = function () {
  7941. var config = this.config;
  7942. return isValue(config.padding_bottom) ? config.padding_bottom : 0;
  7943. };
  7944. ChartInternal.prototype.getCurrentPaddingLeft = function (withoutRecompute) {
  7945. var $$ = this,
  7946. config = $$.config;
  7947. if (isValue(config.padding_left)) {
  7948. return config.padding_left;
  7949. } else if (config.axis_rotated) {
  7950. return !config.axis_x_show || config.axis_x_inner ? 1 : Math.max(ceil10($$.getAxisWidthByAxisId('x', withoutRecompute)), 40);
  7951. } else if (!config.axis_y_show || config.axis_y_inner) {
  7952. // && !config.axis_rotated
  7953. return $$.axis.getYAxisLabelPosition().isOuter ? 30 : 1;
  7954. } else {
  7955. return ceil10($$.getAxisWidthByAxisId('y', withoutRecompute));
  7956. }
  7957. };
  7958. ChartInternal.prototype.getCurrentPaddingRight = function () {
  7959. var $$ = this,
  7960. config = $$.config,
  7961. defaultPadding = 10,
  7962. legendWidthOnRight = $$.isLegendRight ? $$.getLegendWidth() + 20 : 0;
  7963. if (isValue(config.padding_right)) {
  7964. return config.padding_right + 1; // 1 is needed not to hide tick line
  7965. } else if (config.axis_rotated) {
  7966. return defaultPadding + legendWidthOnRight;
  7967. } else if (!config.axis_y2_show || config.axis_y2_inner) {
  7968. // && !config.axis_rotated
  7969. return 2 + legendWidthOnRight + ($$.axis.getY2AxisLabelPosition().isOuter ? 20 : 0);
  7970. } else {
  7971. return ceil10($$.getAxisWidthByAxisId('y2')) + legendWidthOnRight;
  7972. }
  7973. };
  7974. ChartInternal.prototype.getParentRectValue = function (key) {
  7975. var parent = this.selectChart.node(),
  7976. v;
  7977. while (parent && parent.tagName !== 'BODY') {
  7978. try {
  7979. v = parent.getBoundingClientRect()[key];
  7980. } catch (e) {
  7981. if (key === 'width') {
  7982. // In IE in certain cases getBoundingClientRect
  7983. // will cause an "unspecified error"
  7984. v = parent.offsetWidth;
  7985. }
  7986. }
  7987. if (v) {
  7988. break;
  7989. }
  7990. parent = parent.parentNode;
  7991. }
  7992. return v;
  7993. };
  7994. ChartInternal.prototype.getParentWidth = function () {
  7995. return this.getParentRectValue('width');
  7996. };
  7997. ChartInternal.prototype.getParentHeight = function () {
  7998. var h = this.selectChart.style('height');
  7999. return h.indexOf('px') > 0 ? +h.replace('px', '') : 0;
  8000. };
  8001. ChartInternal.prototype.getSvgLeft = function (withoutRecompute) {
  8002. var $$ = this,
  8003. config = $$.config,
  8004. hasLeftAxisRect = config.axis_rotated || !config.axis_rotated && !config.axis_y_inner,
  8005. leftAxisClass = config.axis_rotated ? CLASS.axisX : CLASS.axisY,
  8006. leftAxis = $$.main.select('.' + leftAxisClass).node(),
  8007. svgRect = leftAxis && hasLeftAxisRect ? leftAxis.getBoundingClientRect() : {
  8008. right: 0
  8009. },
  8010. chartRect = $$.selectChart.node().getBoundingClientRect(),
  8011. hasArc = $$.hasArcType(),
  8012. svgLeft = svgRect.right - chartRect.left - (hasArc ? 0 : $$.getCurrentPaddingLeft(withoutRecompute));
  8013. return svgLeft > 0 ? svgLeft : 0;
  8014. };
  8015. ChartInternal.prototype.getAxisWidthByAxisId = function (id, withoutRecompute) {
  8016. var $$ = this,
  8017. position = $$.axis.getLabelPositionById(id);
  8018. return $$.axis.getMaxTickWidth(id, withoutRecompute) + (position.isInner ? 20 : 40);
  8019. };
  8020. ChartInternal.prototype.getHorizontalAxisHeight = function (axisId) {
  8021. var $$ = this,
  8022. config = $$.config,
  8023. h = 30;
  8024. if (axisId === 'x' && !config.axis_x_show) {
  8025. return 8;
  8026. }
  8027. if (axisId === 'x' && config.axis_x_height) {
  8028. return config.axis_x_height;
  8029. }
  8030. if (axisId === 'y' && !config.axis_y_show) {
  8031. return config.legend_show && !$$.isLegendRight && !$$.isLegendInset ? 10 : 1;
  8032. }
  8033. if (axisId === 'y2' && !config.axis_y2_show) {
  8034. return $$.rotated_padding_top;
  8035. } // Calculate x axis height when tick rotated
  8036. if (axisId === 'x' && !config.axis_rotated && config.axis_x_tick_rotate) {
  8037. h = 30 + $$.axis.getMaxTickWidth(axisId) * Math.cos(Math.PI * (90 - Math.abs(config.axis_x_tick_rotate)) / 180);
  8038. } // Calculate y axis height when tick rotated
  8039. if (axisId === 'y' && config.axis_rotated && config.axis_y_tick_rotate) {
  8040. h = 30 + $$.axis.getMaxTickWidth(axisId) * Math.cos(Math.PI * (90 - Math.abs(config.axis_y_tick_rotate)) / 180);
  8041. }
  8042. return h + ($$.axis.getLabelPositionById(axisId).isInner ? 0 : 10) + (axisId === 'y2' ? -10 : 0);
  8043. };
  8044. ChartInternal.prototype.initBrush = function (scale) {
  8045. var $$ = this,
  8046. d3 = $$.d3; // TODO: dynamically change brushY/brushX according to axis_rotated.
  8047. $$.brush = ($$.config.axis_rotated ? d3.brushY() : d3.brushX()).on("brush", function () {
  8048. var event = d3.event.sourceEvent;
  8049. if (event && event.type === "zoom") {
  8050. return;
  8051. }
  8052. $$.redrawForBrush();
  8053. }).on("end", function () {
  8054. var event = d3.event.sourceEvent;
  8055. if (event && event.type === "zoom") {
  8056. return;
  8057. }
  8058. if ($$.brush.empty() && event && event.type !== 'end') {
  8059. $$.brush.clear();
  8060. }
  8061. });
  8062. $$.brush.updateExtent = function () {
  8063. var range = this.scale.range(),
  8064. extent;
  8065. if ($$.config.axis_rotated) {
  8066. extent = [[0, range[0]], [$$.width2, range[1]]];
  8067. } else {
  8068. extent = [[range[0], 0], [range[1], $$.height2]];
  8069. }
  8070. this.extent(extent);
  8071. return this;
  8072. };
  8073. $$.brush.updateScale = function (scale) {
  8074. this.scale = scale;
  8075. return this;
  8076. };
  8077. $$.brush.update = function (scale) {
  8078. this.updateScale(scale || $$.subX).updateExtent();
  8079. $$.context.select('.' + CLASS.brush).call(this);
  8080. };
  8081. $$.brush.clear = function () {
  8082. $$.context.select('.' + CLASS.brush).call($$.brush.move, null);
  8083. };
  8084. $$.brush.selection = function () {
  8085. return d3.brushSelection($$.context.select('.' + CLASS.brush).node());
  8086. };
  8087. $$.brush.selectionAsValue = function (selectionAsValue, withTransition) {
  8088. var selection, brush;
  8089. if (selectionAsValue) {
  8090. if ($$.context) {
  8091. selection = [this.scale(selectionAsValue[0]), this.scale(selectionAsValue[1])];
  8092. brush = $$.context.select('.' + CLASS.brush);
  8093. if (withTransition) {
  8094. brush = brush.transition();
  8095. }
  8096. $$.brush.move(brush, selection);
  8097. }
  8098. return [];
  8099. }
  8100. selection = $$.brush.selection() || [0, 0];
  8101. return [this.scale.invert(selection[0]), this.scale.invert(selection[1])];
  8102. };
  8103. $$.brush.empty = function () {
  8104. var selection = $$.brush.selection();
  8105. return !selection || selection[0] === selection[1];
  8106. };
  8107. return $$.brush.updateScale(scale);
  8108. };
  8109. ChartInternal.prototype.initSubchart = function () {
  8110. var $$ = this,
  8111. config = $$.config,
  8112. context = $$.context = $$.svg.append("g").attr("transform", $$.getTranslate('context')),
  8113. visibility = config.subchart_show ? 'visible' : 'hidden'; // set style
  8114. context.style('visibility', visibility); // Define g for chart area
  8115. context.append('g').attr("clip-path", $$.clipPathForSubchart).attr('class', CLASS.chart); // Define g for bar chart area
  8116. context.select('.' + CLASS.chart).append("g").attr("class", CLASS.chartBars); // Define g for line chart area
  8117. context.select('.' + CLASS.chart).append("g").attr("class", CLASS.chartLines); // Add extent rect for Brush
  8118. context.append("g").attr("clip-path", $$.clipPath).attr("class", CLASS.brush); // ATTENTION: This must be called AFTER chart added
  8119. // Add Axis
  8120. $$.axes.subx = context.append("g").attr("class", CLASS.axisX).attr("transform", $$.getTranslate('subx')).attr("clip-path", config.axis_rotated ? "" : $$.clipPathForXAxis);
  8121. };
  8122. ChartInternal.prototype.initSubchartBrush = function () {
  8123. var $$ = this; // Add extent rect for Brush
  8124. $$.initBrush($$.subX).updateExtent();
  8125. $$.context.select('.' + CLASS.brush).call($$.brush);
  8126. };
  8127. ChartInternal.prototype.updateTargetsForSubchart = function (targets) {
  8128. var $$ = this,
  8129. context = $$.context,
  8130. config = $$.config,
  8131. contextLineEnter,
  8132. contextLine,
  8133. contextBarEnter,
  8134. contextBar,
  8135. classChartBar = $$.classChartBar.bind($$),
  8136. classBars = $$.classBars.bind($$),
  8137. classChartLine = $$.classChartLine.bind($$),
  8138. classLines = $$.classLines.bind($$),
  8139. classAreas = $$.classAreas.bind($$);
  8140. if (config.subchart_show) {
  8141. //-- Bar --//
  8142. contextBar = context.select('.' + CLASS.chartBars).selectAll('.' + CLASS.chartBar).data(targets);
  8143. contextBarEnter = contextBar.enter().append('g').style('opacity', 0);
  8144. contextBarEnter.merge(contextBar).attr('class', classChartBar); // Bars for each data
  8145. contextBarEnter.append('g').attr("class", classBars); //-- Line --//
  8146. contextLine = context.select('.' + CLASS.chartLines).selectAll('.' + CLASS.chartLine).data(targets);
  8147. contextLineEnter = contextLine.enter().append('g').style('opacity', 0);
  8148. contextLineEnter.merge(contextLine).attr('class', classChartLine); // Lines for each data
  8149. contextLineEnter.append("g").attr("class", classLines); // Area
  8150. contextLineEnter.append("g").attr("class", classAreas); //-- Brush --//
  8151. context.selectAll('.' + CLASS.brush + ' rect').attr(config.axis_rotated ? "width" : "height", config.axis_rotated ? $$.width2 : $$.height2);
  8152. }
  8153. };
  8154. ChartInternal.prototype.updateBarForSubchart = function (durationForExit) {
  8155. var $$ = this;
  8156. var contextBar = $$.context.selectAll('.' + CLASS.bars).selectAll('.' + CLASS.bar).data($$.barData.bind($$));
  8157. var contextBarEnter = contextBar.enter().append('path').attr("class", $$.classBar.bind($$)).style("stroke", 'none').style("fill", $$.color);
  8158. contextBar.exit().transition().duration(durationForExit).style('opacity', 0).remove();
  8159. $$.contextBar = contextBarEnter.merge(contextBar).style("opacity", $$.initialOpacity.bind($$));
  8160. };
  8161. ChartInternal.prototype.redrawBarForSubchart = function (drawBarOnSub, withTransition, duration) {
  8162. (withTransition ? this.contextBar.transition(Math.random().toString()).duration(duration) : this.contextBar).attr('d', drawBarOnSub).style('opacity', 1);
  8163. };
  8164. ChartInternal.prototype.updateLineForSubchart = function (durationForExit) {
  8165. var $$ = this;
  8166. var contextLine = $$.context.selectAll('.' + CLASS.lines).selectAll('.' + CLASS.line).data($$.lineData.bind($$));
  8167. var contextLineEnter = contextLine.enter().append('path').attr('class', $$.classLine.bind($$)).style('stroke', $$.color);
  8168. contextLine.exit().transition().duration(durationForExit).style('opacity', 0).remove();
  8169. $$.contextLine = contextLineEnter.merge(contextLine).style("opacity", $$.initialOpacity.bind($$));
  8170. };
  8171. ChartInternal.prototype.redrawLineForSubchart = function (drawLineOnSub, withTransition, duration) {
  8172. (withTransition ? this.contextLine.transition(Math.random().toString()).duration(duration) : this.contextLine).attr("d", drawLineOnSub).style('opacity', 1);
  8173. };
  8174. ChartInternal.prototype.updateAreaForSubchart = function (durationForExit) {
  8175. var $$ = this,
  8176. d3 = $$.d3;
  8177. var contextArea = $$.context.selectAll('.' + CLASS.areas).selectAll('.' + CLASS.area).data($$.lineData.bind($$));
  8178. var contextAreaEnter = contextArea.enter().append('path').attr("class", $$.classArea.bind($$)).style("fill", $$.color).style("opacity", function () {
  8179. $$.orgAreaOpacity = +d3.select(this).style('opacity');
  8180. return 0;
  8181. });
  8182. contextArea.exit().transition().duration(durationForExit).style('opacity', 0).remove();
  8183. $$.contextArea = contextAreaEnter.merge(contextArea).style("opacity", 0);
  8184. };
  8185. ChartInternal.prototype.redrawAreaForSubchart = function (drawAreaOnSub, withTransition, duration) {
  8186. (withTransition ? this.contextArea.transition(Math.random().toString()).duration(duration) : this.contextArea).attr("d", drawAreaOnSub).style("fill", this.color).style("opacity", this.orgAreaOpacity);
  8187. };
  8188. ChartInternal.prototype.redrawSubchart = function (withSubchart, transitions, duration, durationForExit, areaIndices, barIndices, lineIndices) {
  8189. var $$ = this,
  8190. d3 = $$.d3,
  8191. config = $$.config,
  8192. drawAreaOnSub,
  8193. drawBarOnSub,
  8194. drawLineOnSub;
  8195. $$.context.style('visibility', config.subchart_show ? 'visible' : 'hidden'); // subchart
  8196. if (config.subchart_show) {
  8197. // reflect main chart to extent on subchart if zoomed
  8198. if (d3.event && d3.event.type === 'zoom') {
  8199. $$.brush.selectionAsValue($$.x.orgDomain());
  8200. } // update subchart elements if needed
  8201. if (withSubchart) {
  8202. // extent rect
  8203. if (!$$.brush.empty()) {
  8204. $$.brush.selectionAsValue($$.x.orgDomain());
  8205. } // setup drawer - MEMO: this must be called after axis updated
  8206. drawAreaOnSub = $$.generateDrawArea(areaIndices, true);
  8207. drawBarOnSub = $$.generateDrawBar(barIndices, true);
  8208. drawLineOnSub = $$.generateDrawLine(lineIndices, true);
  8209. $$.updateBarForSubchart(duration);
  8210. $$.updateLineForSubchart(duration);
  8211. $$.updateAreaForSubchart(duration);
  8212. $$.redrawBarForSubchart(drawBarOnSub, duration, duration);
  8213. $$.redrawLineForSubchart(drawLineOnSub, duration, duration);
  8214. $$.redrawAreaForSubchart(drawAreaOnSub, duration, duration);
  8215. }
  8216. }
  8217. };
  8218. ChartInternal.prototype.redrawForBrush = function () {
  8219. var $$ = this,
  8220. x = $$.x,
  8221. d3 = $$.d3,
  8222. s;
  8223. $$.redraw({
  8224. withTransition: false,
  8225. withY: $$.config.zoom_rescale,
  8226. withSubchart: false,
  8227. withUpdateXDomain: true,
  8228. withEventRect: false,
  8229. withDimension: false
  8230. }); // update zoom transation binded to event rect
  8231. s = d3.event.selection || $$.brush.scale.range();
  8232. $$.main.select('.' + CLASS.eventRect).call($$.zoom.transform, d3.zoomIdentity.scale($$.width / (s[1] - s[0])).translate(-s[0], 0));
  8233. $$.config.subchart_onbrush.call($$.api, x.orgDomain());
  8234. };
  8235. ChartInternal.prototype.transformContext = function (withTransition, transitions) {
  8236. var $$ = this,
  8237. subXAxis;
  8238. if (transitions && transitions.axisSubX) {
  8239. subXAxis = transitions.axisSubX;
  8240. } else {
  8241. subXAxis = $$.context.select('.' + CLASS.axisX);
  8242. if (withTransition) {
  8243. subXAxis = subXAxis.transition();
  8244. }
  8245. }
  8246. $$.context.attr("transform", $$.getTranslate('context'));
  8247. subXAxis.attr("transform", $$.getTranslate('subx'));
  8248. };
  8249. ChartInternal.prototype.getDefaultSelection = function () {
  8250. var $$ = this,
  8251. config = $$.config,
  8252. selection = isFunction(config.axis_x_selection) ? config.axis_x_selection($$.getXDomain($$.data.targets)) : config.axis_x_selection;
  8253. if ($$.isTimeSeries()) {
  8254. selection = [$$.parseDate(selection[0]), $$.parseDate(selection[1])];
  8255. }
  8256. return selection;
  8257. };
  8258. ChartInternal.prototype.initText = function () {
  8259. var $$ = this;
  8260. $$.main.select('.' + CLASS.chart).append("g").attr("class", CLASS.chartTexts);
  8261. $$.mainText = $$.d3.selectAll([]);
  8262. };
  8263. ChartInternal.prototype.updateTargetsForText = function (targets) {
  8264. var $$ = this,
  8265. classChartText = $$.classChartText.bind($$),
  8266. classTexts = $$.classTexts.bind($$),
  8267. classFocus = $$.classFocus.bind($$);
  8268. var mainText = $$.main.select('.' + CLASS.chartTexts).selectAll('.' + CLASS.chartText).data(targets);
  8269. var mainTextEnter = mainText.enter().append('g').attr('class', classChartText).style('opacity', 0).style("pointer-events", "none");
  8270. mainTextEnter.append('g').attr('class', classTexts);
  8271. mainTextEnter.merge(mainText).attr('class', function (d) {
  8272. return classChartText(d) + classFocus(d);
  8273. });
  8274. };
  8275. ChartInternal.prototype.updateText = function (xForText, yForText, durationForExit) {
  8276. var $$ = this,
  8277. config = $$.config,
  8278. barOrLineData = $$.barOrLineData.bind($$),
  8279. classText = $$.classText.bind($$);
  8280. var mainText = $$.main.selectAll('.' + CLASS.texts).selectAll('.' + CLASS.text).data(barOrLineData);
  8281. var mainTextEnter = mainText.enter().append('text').attr("class", classText).attr('text-anchor', function (d) {
  8282. return config.axis_rotated ? d.value < 0 ? 'end' : 'start' : 'middle';
  8283. }).style("stroke", 'none').attr('x', xForText).attr('y', yForText).style("fill", function (d) {
  8284. return $$.color(d);
  8285. }).style("fill-opacity", 0);
  8286. $$.mainText = mainTextEnter.merge(mainText).text(function (d, i, j) {
  8287. return $$.dataLabelFormat(d.id)(d.value, d.id, i, j);
  8288. });
  8289. mainText.exit().transition().duration(durationForExit).style('fill-opacity', 0).remove();
  8290. };
  8291. ChartInternal.prototype.redrawText = function (xForText, yForText, forFlow, withTransition, transition) {
  8292. return [(withTransition ? this.mainText.transition(transition) : this.mainText).attr('x', xForText).attr('y', yForText).style("fill", this.color).style("fill-opacity", forFlow ? 0 : this.opacityForText.bind(this))];
  8293. };
  8294. ChartInternal.prototype.getTextRect = function (text, cls, element) {
  8295. var dummy = this.d3.select('body').append('div').classed('c3', true),
  8296. svg = dummy.append("svg").style('visibility', 'hidden').style('position', 'fixed').style('top', 0).style('left', 0),
  8297. font = this.d3.select(element).style('font'),
  8298. rect;
  8299. svg.selectAll('.dummy').data([text]).enter().append('text').classed(cls ? cls : "", true).style('font', font).text(text).each(function () {
  8300. rect = this.getBoundingClientRect();
  8301. });
  8302. dummy.remove();
  8303. return rect;
  8304. };
  8305. ChartInternal.prototype.generateXYForText = function (areaIndices, barIndices, lineIndices, forX) {
  8306. var $$ = this,
  8307. getAreaPoints = $$.generateGetAreaPoints(areaIndices, false),
  8308. getBarPoints = $$.generateGetBarPoints(barIndices, false),
  8309. getLinePoints = $$.generateGetLinePoints(lineIndices, false),
  8310. getter = forX ? $$.getXForText : $$.getYForText;
  8311. return function (d, i) {
  8312. var getPoints = $$.isAreaType(d) ? getAreaPoints : $$.isBarType(d) ? getBarPoints : getLinePoints;
  8313. return getter.call($$, getPoints(d, i), d, this);
  8314. };
  8315. };
  8316. ChartInternal.prototype.getXForText = function (points, d, textElement) {
  8317. var $$ = this,
  8318. box = textElement.getBoundingClientRect(),
  8319. xPos,
  8320. padding;
  8321. if ($$.config.axis_rotated) {
  8322. padding = $$.isBarType(d) ? 4 : 6;
  8323. xPos = points[2][1] + padding * (d.value < 0 ? -1 : 1);
  8324. } else {
  8325. xPos = $$.hasType('bar') ? (points[2][0] + points[0][0]) / 2 : points[0][0];
  8326. } // show labels regardless of the domain if value is null
  8327. if (d.value === null) {
  8328. if (xPos > $$.width) {
  8329. xPos = $$.width - box.width;
  8330. } else if (xPos < 0) {
  8331. xPos = 4;
  8332. }
  8333. }
  8334. return xPos;
  8335. };
  8336. ChartInternal.prototype.getYForText = function (points, d, textElement) {
  8337. var $$ = this,
  8338. box = textElement.getBoundingClientRect(),
  8339. yPos;
  8340. if ($$.config.axis_rotated) {
  8341. yPos = (points[0][0] + points[2][0] + box.height * 0.6) / 2;
  8342. } else {
  8343. yPos = points[2][1];
  8344. if (d.value < 0 || d.value === 0 && !$$.hasPositiveValue) {
  8345. yPos += box.height;
  8346. if ($$.isBarType(d) && $$.isSafari()) {
  8347. yPos -= 3;
  8348. } else if (!$$.isBarType(d) && $$.isChrome()) {
  8349. yPos += 3;
  8350. }
  8351. } else {
  8352. yPos += $$.isBarType(d) ? -3 : -6;
  8353. }
  8354. } // show labels regardless of the domain if value is null
  8355. if (d.value === null && !$$.config.axis_rotated) {
  8356. if (yPos < box.height) {
  8357. yPos = box.height;
  8358. } else if (yPos > this.height) {
  8359. yPos = this.height - 4;
  8360. }
  8361. }
  8362. return yPos;
  8363. };
  8364. ChartInternal.prototype.initTitle = function () {
  8365. var $$ = this;
  8366. $$.title = $$.svg.append("text").text($$.config.title_text).attr("class", $$.CLASS.title);
  8367. };
  8368. ChartInternal.prototype.redrawTitle = function () {
  8369. var $$ = this;
  8370. $$.title.attr("x", $$.xForTitle.bind($$)).attr("y", $$.yForTitle.bind($$));
  8371. };
  8372. ChartInternal.prototype.xForTitle = function () {
  8373. var $$ = this,
  8374. config = $$.config,
  8375. position = config.title_position || 'left',
  8376. x;
  8377. if (position.indexOf('right') >= 0) {
  8378. x = $$.currentWidth - $$.getTextRect($$.title.node().textContent, $$.CLASS.title, $$.title.node()).width - config.title_padding.right;
  8379. } else if (position.indexOf('center') >= 0) {
  8380. x = ($$.currentWidth - $$.getTextRect($$.title.node().textContent, $$.CLASS.title, $$.title.node()).width) / 2;
  8381. } else {
  8382. // left
  8383. x = config.title_padding.left;
  8384. }
  8385. return x;
  8386. };
  8387. ChartInternal.prototype.yForTitle = function () {
  8388. var $$ = this;
  8389. return $$.config.title_padding.top + $$.getTextRect($$.title.node().textContent, $$.CLASS.title, $$.title.node()).height;
  8390. };
  8391. ChartInternal.prototype.getTitlePadding = function () {
  8392. var $$ = this;
  8393. return $$.yForTitle() + $$.config.title_padding.bottom;
  8394. };
  8395. ChartInternal.prototype.initTooltip = function () {
  8396. var $$ = this,
  8397. config = $$.config,
  8398. i;
  8399. $$.tooltip = $$.selectChart.style("position", "relative").append("div").attr('class', CLASS.tooltipContainer).style("position", "absolute").style("pointer-events", "none").style("display", "none"); // Show tooltip if needed
  8400. if (config.tooltip_init_show) {
  8401. if ($$.isTimeSeries() && isString(config.tooltip_init_x)) {
  8402. config.tooltip_init_x = $$.parseDate(config.tooltip_init_x);
  8403. for (i = 0; i < $$.data.targets[0].values.length; i++) {
  8404. if ($$.data.targets[0].values[i].x - config.tooltip_init_x === 0) {
  8405. break;
  8406. }
  8407. }
  8408. config.tooltip_init_x = i;
  8409. }
  8410. $$.tooltip.html(config.tooltip_contents.call($$, $$.data.targets.map(function (d) {
  8411. return $$.addName(d.values[config.tooltip_init_x]);
  8412. }), $$.axis.getXAxisTickFormat(), $$.getYFormat($$.hasArcType()), $$.color));
  8413. $$.tooltip.style("top", config.tooltip_init_position.top).style("left", config.tooltip_init_position.left).style("display", "block");
  8414. }
  8415. };
  8416. ChartInternal.prototype.getTooltipSortFunction = function () {
  8417. var $$ = this,
  8418. config = $$.config;
  8419. if (config.data_groups.length === 0 || config.tooltip_order !== undefined) {
  8420. // if data are not grouped or if an order is specified
  8421. // for the tooltip values we sort them by their values
  8422. var order = config.tooltip_order;
  8423. if (order === undefined) {
  8424. order = config.data_order;
  8425. }
  8426. var valueOf = function valueOf(obj) {
  8427. return obj ? obj.value : null;
  8428. }; // if data are not grouped, we sort them by their value
  8429. if (isString(order) && order.toLowerCase() === 'asc') {
  8430. return function (a, b) {
  8431. return valueOf(a) - valueOf(b);
  8432. };
  8433. } else if (isString(order) && order.toLowerCase() === 'desc') {
  8434. return function (a, b) {
  8435. return valueOf(b) - valueOf(a);
  8436. };
  8437. } else if (isFunction(order)) {
  8438. // if the function is from data_order we need
  8439. // to wrap the returned function in order to format
  8440. // the sorted value to the expected format
  8441. var sortFunction = order;
  8442. if (config.tooltip_order === undefined) {
  8443. sortFunction = function sortFunction(a, b) {
  8444. return order(a ? {
  8445. id: a.id,
  8446. values: [a]
  8447. } : null, b ? {
  8448. id: b.id,
  8449. values: [b]
  8450. } : null);
  8451. };
  8452. }
  8453. return sortFunction;
  8454. } else if (isArray(order)) {
  8455. return function (a, b) {
  8456. return order.indexOf(a.id) - order.indexOf(b.id);
  8457. };
  8458. }
  8459. } else {
  8460. // if data are grouped, we follow the order of grouped targets
  8461. var ids = $$.orderTargets($$.data.targets).map(function (i) {
  8462. return i.id;
  8463. }); // if it was either asc or desc we need to invert the order
  8464. // returned by orderTargets
  8465. if ($$.isOrderAsc() || $$.isOrderDesc()) {
  8466. ids = ids.reverse();
  8467. }
  8468. return function (a, b) {
  8469. return ids.indexOf(a.id) - ids.indexOf(b.id);
  8470. };
  8471. }
  8472. };
  8473. ChartInternal.prototype.getTooltipContent = function (d, defaultTitleFormat, defaultValueFormat, color) {
  8474. var $$ = this,
  8475. config = $$.config,
  8476. titleFormat = config.tooltip_format_title || defaultTitleFormat,
  8477. nameFormat = config.tooltip_format_name || function (name) {
  8478. return name;
  8479. },
  8480. valueFormat = config.tooltip_format_value || defaultValueFormat,
  8481. text,
  8482. i,
  8483. title,
  8484. value,
  8485. name,
  8486. bgcolor;
  8487. var tooltipSortFunction = this.getTooltipSortFunction();
  8488. if (tooltipSortFunction) {
  8489. d.sort(tooltipSortFunction);
  8490. }
  8491. for (i = 0; i < d.length; i++) {
  8492. if (!(d[i] && (d[i].value || d[i].value === 0))) {
  8493. continue;
  8494. }
  8495. if (!text) {
  8496. title = sanitise(titleFormat ? titleFormat(d[i].x) : d[i].x);
  8497. text = "<table class='" + $$.CLASS.tooltip + "'>" + (title || title === 0 ? "<tr><th colspan='2'>" + title + "</th></tr>" : "");
  8498. }
  8499. value = sanitise(valueFormat(d[i].value, d[i].ratio, d[i].id, d[i].index, d));
  8500. if (value !== undefined) {
  8501. // Skip elements when their name is set to null
  8502. if (d[i].name === null) {
  8503. continue;
  8504. }
  8505. name = sanitise(nameFormat(d[i].name, d[i].ratio, d[i].id, d[i].index));
  8506. bgcolor = $$.levelColor ? $$.levelColor(d[i].value) : color(d[i].id);
  8507. text += "<tr class='" + $$.CLASS.tooltipName + "-" + $$.getTargetSelectorSuffix(d[i].id) + "'>";
  8508. text += "<td class='name'><span style='background-color:" + bgcolor + "'></span>" + name + "</td>";
  8509. text += "<td class='value'>" + value + "</td>";
  8510. text += "</tr>";
  8511. }
  8512. }
  8513. return text + "</table>";
  8514. };
  8515. ChartInternal.prototype.tooltipPosition = function (dataToShow, tWidth, tHeight, element) {
  8516. var $$ = this,
  8517. config = $$.config,
  8518. d3 = $$.d3;
  8519. var svgLeft, tooltipLeft, tooltipRight, tooltipTop, chartRight;
  8520. var forArc = $$.hasArcType(),
  8521. mouse = d3.mouse(element); // Determin tooltip position
  8522. if (forArc) {
  8523. tooltipLeft = ($$.width - ($$.isLegendRight ? $$.getLegendWidth() : 0)) / 2 + mouse[0];
  8524. tooltipTop = ($$.hasType('gauge') ? $$.height : $$.height / 2) + mouse[1] + 20;
  8525. } else {
  8526. svgLeft = $$.getSvgLeft(true);
  8527. if (config.axis_rotated) {
  8528. tooltipLeft = svgLeft + mouse[0] + 100;
  8529. tooltipRight = tooltipLeft + tWidth;
  8530. chartRight = $$.currentWidth - $$.getCurrentPaddingRight();
  8531. tooltipTop = $$.x(dataToShow[0].x) + 20;
  8532. } else {
  8533. tooltipLeft = svgLeft + $$.getCurrentPaddingLeft(true) + $$.x(dataToShow[0].x) + 20;
  8534. tooltipRight = tooltipLeft + tWidth;
  8535. chartRight = svgLeft + $$.currentWidth - $$.getCurrentPaddingRight();
  8536. tooltipTop = mouse[1] + 15;
  8537. }
  8538. if (tooltipRight > chartRight) {
  8539. // 20 is needed for Firefox to keep tooltip width
  8540. tooltipLeft -= tooltipRight - chartRight + 20;
  8541. }
  8542. if (tooltipTop + tHeight > $$.currentHeight) {
  8543. tooltipTop -= tHeight + 30;
  8544. }
  8545. }
  8546. if (tooltipTop < 0) {
  8547. tooltipTop = 0;
  8548. }
  8549. return {
  8550. top: tooltipTop,
  8551. left: tooltipLeft
  8552. };
  8553. };
  8554. ChartInternal.prototype.showTooltip = function (selectedData, element) {
  8555. var $$ = this,
  8556. config = $$.config;
  8557. var tWidth, tHeight, position;
  8558. var forArc = $$.hasArcType(),
  8559. dataToShow = selectedData.filter(function (d) {
  8560. return d && isValue(d.value);
  8561. }),
  8562. positionFunction = config.tooltip_position || ChartInternal.prototype.tooltipPosition;
  8563. if (dataToShow.length === 0 || !config.tooltip_show) {
  8564. return;
  8565. }
  8566. $$.tooltip.html(config.tooltip_contents.call($$, selectedData, $$.axis.getXAxisTickFormat(), $$.getYFormat(forArc), $$.color)).style("display", "block"); // Get tooltip dimensions
  8567. tWidth = $$.tooltip.property('offsetWidth');
  8568. tHeight = $$.tooltip.property('offsetHeight');
  8569. position = positionFunction.call(this, dataToShow, tWidth, tHeight, element); // Set tooltip
  8570. $$.tooltip.style("top", position.top + "px").style("left", position.left + 'px');
  8571. };
  8572. ChartInternal.prototype.hideTooltip = function () {
  8573. this.tooltip.style("display", "none");
  8574. };
  8575. ChartInternal.prototype.setTargetType = function (targetIds, type) {
  8576. var $$ = this,
  8577. config = $$.config;
  8578. $$.mapToTargetIds(targetIds).forEach(function (id) {
  8579. $$.withoutFadeIn[id] = type === config.data_types[id];
  8580. config.data_types[id] = type;
  8581. });
  8582. if (!targetIds) {
  8583. config.data_type = type;
  8584. }
  8585. };
  8586. ChartInternal.prototype.hasType = function (type, targets) {
  8587. var $$ = this,
  8588. types = $$.config.data_types,
  8589. has = false;
  8590. targets = targets || $$.data.targets;
  8591. if (targets && targets.length) {
  8592. targets.forEach(function (target) {
  8593. var t = types[target.id];
  8594. if (t && t.indexOf(type) >= 0 || !t && type === 'line') {
  8595. has = true;
  8596. }
  8597. });
  8598. } else if (Object.keys(types).length) {
  8599. Object.keys(types).forEach(function (id) {
  8600. if (types[id] === type) {
  8601. has = true;
  8602. }
  8603. });
  8604. } else {
  8605. has = $$.config.data_type === type;
  8606. }
  8607. return has;
  8608. };
  8609. ChartInternal.prototype.hasArcType = function (targets) {
  8610. return this.hasType('pie', targets) || this.hasType('donut', targets) || this.hasType('gauge', targets);
  8611. };
  8612. ChartInternal.prototype.isLineType = function (d) {
  8613. var config = this.config,
  8614. id = isString(d) ? d : d.id;
  8615. return !config.data_types[id] || ['line', 'spline', 'area', 'area-spline', 'step', 'area-step'].indexOf(config.data_types[id]) >= 0;
  8616. };
  8617. ChartInternal.prototype.isStepType = function (d) {
  8618. var id = isString(d) ? d : d.id;
  8619. return ['step', 'area-step'].indexOf(this.config.data_types[id]) >= 0;
  8620. };
  8621. ChartInternal.prototype.isSplineType = function (d) {
  8622. var id = isString(d) ? d : d.id;
  8623. return ['spline', 'area-spline'].indexOf(this.config.data_types[id]) >= 0;
  8624. };
  8625. ChartInternal.prototype.isAreaType = function (d) {
  8626. var id = isString(d) ? d : d.id;
  8627. return ['area', 'area-spline', 'area-step'].indexOf(this.config.data_types[id]) >= 0;
  8628. };
  8629. ChartInternal.prototype.isBarType = function (d) {
  8630. var id = isString(d) ? d : d.id;
  8631. return this.config.data_types[id] === 'bar';
  8632. };
  8633. ChartInternal.prototype.isScatterType = function (d) {
  8634. var id = isString(d) ? d : d.id;
  8635. return this.config.data_types[id] === 'scatter';
  8636. };
  8637. ChartInternal.prototype.isPieType = function (d) {
  8638. var id = isString(d) ? d : d.id;
  8639. return this.config.data_types[id] === 'pie';
  8640. };
  8641. ChartInternal.prototype.isGaugeType = function (d) {
  8642. var id = isString(d) ? d : d.id;
  8643. return this.config.data_types[id] === 'gauge';
  8644. };
  8645. ChartInternal.prototype.isDonutType = function (d) {
  8646. var id = isString(d) ? d : d.id;
  8647. return this.config.data_types[id] === 'donut';
  8648. };
  8649. ChartInternal.prototype.isArcType = function (d) {
  8650. return this.isPieType(d) || this.isDonutType(d) || this.isGaugeType(d);
  8651. };
  8652. ChartInternal.prototype.lineData = function (d) {
  8653. return this.isLineType(d) ? [d] : [];
  8654. };
  8655. ChartInternal.prototype.arcData = function (d) {
  8656. return this.isArcType(d.data) ? [d] : [];
  8657. };
  8658. /* not used
  8659. function scatterData(d) {
  8660. return isScatterType(d) ? d.values : [];
  8661. }
  8662. */
  8663. ChartInternal.prototype.barData = function (d) {
  8664. return this.isBarType(d) ? d.values : [];
  8665. };
  8666. ChartInternal.prototype.lineOrScatterData = function (d) {
  8667. return this.isLineType(d) || this.isScatterType(d) ? d.values : [];
  8668. };
  8669. ChartInternal.prototype.barOrLineData = function (d) {
  8670. return this.isBarType(d) || this.isLineType(d) ? d.values : [];
  8671. };
  8672. ChartInternal.prototype.isSafari = function () {
  8673. var ua = window.navigator.userAgent;
  8674. return ua.indexOf('Safari') >= 0 && ua.indexOf('Chrome') < 0;
  8675. };
  8676. ChartInternal.prototype.isChrome = function () {
  8677. var ua = window.navigator.userAgent;
  8678. return ua.indexOf('Chrome') >= 0;
  8679. };
  8680. ChartInternal.prototype.initZoom = function () {
  8681. var $$ = this,
  8682. d3 = $$.d3,
  8683. config = $$.config,
  8684. startEvent;
  8685. $$.zoom = d3.zoom().on("start", function () {
  8686. if (config.zoom_type !== 'scroll') {
  8687. return;
  8688. }
  8689. var e = d3.event.sourceEvent;
  8690. if (e && e.type === "brush") {
  8691. return;
  8692. }
  8693. startEvent = e;
  8694. config.zoom_onzoomstart.call($$.api, e);
  8695. }).on("zoom", function () {
  8696. if (config.zoom_type !== 'scroll') {
  8697. return;
  8698. }
  8699. var e = d3.event.sourceEvent;
  8700. if (e && e.type === "brush") {
  8701. return;
  8702. }
  8703. $$.redrawForZoom();
  8704. config.zoom_onzoom.call($$.api, $$.x.orgDomain());
  8705. }).on('end', function () {
  8706. if (config.zoom_type !== 'scroll') {
  8707. return;
  8708. }
  8709. var e = d3.event.sourceEvent;
  8710. if (e && e.type === "brush") {
  8711. return;
  8712. } // if click, do nothing. otherwise, click interaction will be canceled.
  8713. if (e && startEvent.clientX === e.clientX && startEvent.clientY === e.clientY) {
  8714. return;
  8715. }
  8716. config.zoom_onzoomend.call($$.api, $$.x.orgDomain());
  8717. });
  8718. $$.zoom.updateDomain = function () {
  8719. if (d3.event && d3.event.transform) {
  8720. $$.x.domain(d3.event.transform.rescaleX($$.subX).domain());
  8721. }
  8722. return this;
  8723. };
  8724. $$.zoom.updateExtent = function () {
  8725. this.scaleExtent([1, Infinity]).translateExtent([[0, 0], [$$.width, $$.height]]).extent([[0, 0], [$$.width, $$.height]]);
  8726. return this;
  8727. };
  8728. $$.zoom.update = function () {
  8729. return this.updateExtent().updateDomain();
  8730. };
  8731. return $$.zoom.updateExtent();
  8732. };
  8733. ChartInternal.prototype.zoomTransform = function (range) {
  8734. var $$ = this,
  8735. s = [$$.x(range[0]), $$.x(range[1])];
  8736. return $$.d3.zoomIdentity.scale($$.width / (s[1] - s[0])).translate(-s[0], 0);
  8737. };
  8738. ChartInternal.prototype.initDragZoom = function () {
  8739. var $$ = this;
  8740. var d3 = $$.d3;
  8741. var config = $$.config;
  8742. var context = $$.context = $$.svg;
  8743. var brushXPos = $$.margin.left + 20.5;
  8744. var brushYPos = $$.margin.top + 0.5;
  8745. if (!(config.zoom_type === 'drag' && config.zoom_enabled)) {
  8746. return;
  8747. }
  8748. var getZoomedDomain = function getZoomedDomain(selection) {
  8749. return selection && selection.map(function (x) {
  8750. return $$.x.invert(x);
  8751. });
  8752. };
  8753. var brush = $$.dragZoomBrush = d3.brushX().on("start", function () {
  8754. $$.api.unzoom();
  8755. $$.svg.select("." + CLASS.dragZoom).classed("disabled", false);
  8756. config.zoom_onzoomstart.call($$.api, d3.event.sourceEvent);
  8757. }).on("brush", function () {
  8758. config.zoom_onzoom.call($$.api, getZoomedDomain(d3.event.selection));
  8759. }).on("end", function () {
  8760. if (d3.event.selection == null) {
  8761. return;
  8762. }
  8763. var zoomedDomain = getZoomedDomain(d3.event.selection);
  8764. if (!config.zoom_disableDefaultBehavior) {
  8765. $$.api.zoom(zoomedDomain);
  8766. }
  8767. $$.svg.select("." + CLASS.dragZoom).classed("disabled", true);
  8768. config.zoom_onzoomend.call($$.api, zoomedDomain);
  8769. });
  8770. context.append("g").classed(CLASS.dragZoom, true).attr("clip-path", $$.clipPath).attr("transform", "translate(" + brushXPos + "," + brushYPos + ")").call(brush);
  8771. };
  8772. ChartInternal.prototype.getZoomDomain = function () {
  8773. var $$ = this,
  8774. config = $$.config,
  8775. d3 = $$.d3,
  8776. min = d3.min([$$.orgXDomain[0], config.zoom_x_min]),
  8777. max = d3.max([$$.orgXDomain[1], config.zoom_x_max]);
  8778. return [min, max];
  8779. };
  8780. ChartInternal.prototype.redrawForZoom = function () {
  8781. var $$ = this,
  8782. d3 = $$.d3,
  8783. config = $$.config,
  8784. zoom = $$.zoom,
  8785. x = $$.x;
  8786. if (!config.zoom_enabled) {
  8787. return;
  8788. }
  8789. if ($$.filterTargetsToShow($$.data.targets).length === 0) {
  8790. return;
  8791. }
  8792. zoom.update();
  8793. if (config.zoom_disableDefaultBehavior) {
  8794. return;
  8795. }
  8796. if ($$.isCategorized() && x.orgDomain()[0] === $$.orgXDomain[0]) {
  8797. x.domain([$$.orgXDomain[0] - 1e-10, x.orgDomain()[1]]);
  8798. }
  8799. $$.redraw({
  8800. withTransition: false,
  8801. withY: config.zoom_rescale,
  8802. withSubchart: false,
  8803. withEventRect: false,
  8804. withDimension: false
  8805. });
  8806. if (d3.event.sourceEvent && d3.event.sourceEvent.type === 'mousemove') {
  8807. $$.cancelClick = true;
  8808. }
  8809. };
  8810. return c3;
  8811. })));